123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- package proxyproto
- import (
- "bufio"
- "bytes"
- "io"
- "net"
- "strconv"
- "strings"
- )
- const (
- CRLF = "\r\n"
- SEPARATOR = " "
- )
- func initVersion1() *Header {
- header := new(Header)
- header.Version = 1
- // Command doesn't exist in v1
- header.Command = PROXY
- return header
- }
- func parseVersion1(reader *bufio.Reader) (*Header, error) {
- // Make sure we have a v1 header
- line, err := reader.ReadString('\n')
- if !strings.HasSuffix(line, CRLF) {
- return nil, ErrCantReadProtocolVersionAndCommand
- }
- tokens := strings.Split(line[:len(line)-2], SEPARATOR)
- if len(tokens) < 6 {
- return nil, ErrCantReadProtocolVersionAndCommand
- }
- header := initVersion1()
- // Read address family and protocol
- switch tokens[1] {
- case "TCP4":
- header.TransportProtocol = TCPv4
- case "TCP6":
- header.TransportProtocol = TCPv6
- default:
- header.TransportProtocol = UNSPEC
- }
- // Read addresses and ports
- header.SourceAddress, err = parseV1IPAddress(header.TransportProtocol, tokens[2])
- if err != nil {
- return nil, err
- }
- header.DestinationAddress, err = parseV1IPAddress(header.TransportProtocol, tokens[3])
- if err != nil {
- return nil, err
- }
- header.SourcePort, err = parseV1PortNumber(tokens[4])
- if err != nil {
- return nil, err
- }
- header.DestinationPort, err = parseV1PortNumber(tokens[5])
- if err != nil {
- return nil, err
- }
- return header, nil
- }
- func (header *Header) writeVersion1(w io.Writer) (int64, error) {
- // As of version 1, only "TCP4" ( \x54 \x43 \x50 \x34 ) for TCP over IPv4,
- // and "TCP6" ( \x54 \x43 \x50 \x36 ) for TCP over IPv6 are allowed.
- proto := "UNKNOWN"
- if header.TransportProtocol == TCPv4 {
- proto = "TCP4"
- } else if header.TransportProtocol == TCPv6 {
- proto = "TCP6"
- }
- var buf bytes.Buffer
- buf.Write(SIGV1)
- buf.WriteString(SEPARATOR)
- buf.WriteString(proto)
- buf.WriteString(SEPARATOR)
- buf.WriteString(header.SourceAddress.String())
- buf.WriteString(SEPARATOR)
- buf.WriteString(header.DestinationAddress.String())
- buf.WriteString(SEPARATOR)
- buf.WriteString(strconv.Itoa(int(header.SourcePort)))
- buf.WriteString(SEPARATOR)
- buf.WriteString(strconv.Itoa(int(header.DestinationPort)))
- buf.WriteString(CRLF)
- return buf.WriteTo(w)
- }
- func parseV1PortNumber(portStr string) (uint16, error) {
- var port uint16
- _port, err := strconv.Atoi(portStr)
- if err == nil {
- if port < 0 || port > 65535 {
- err = ErrInvalidPortNumber
- }
- port = uint16(_port)
- }
- return port, err
- }
- func parseV1IPAddress(protocol AddressFamilyAndProtocol, addrStr string) (addr net.IP, err error) {
- addr = net.ParseIP(addrStr)
- tryV4 := addr.To4()
- if (protocol == TCPv4 && tryV4 == nil) || (protocol == TCPv6 && tryV4 != nil) {
- err = ErrInvalidAddress
- }
- return
- }
|