v1.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package proxyproto
  2. import (
  3. "bufio"
  4. "bytes"
  5. "io"
  6. "net"
  7. "strconv"
  8. "strings"
  9. )
  10. const (
  11. CRLF = "\r\n"
  12. SEPARATOR = " "
  13. )
  14. func initVersion1() *Header {
  15. header := new(Header)
  16. header.Version = 1
  17. // Command doesn't exist in v1
  18. header.Command = PROXY
  19. return header
  20. }
  21. func parseVersion1(reader *bufio.Reader) (*Header, error) {
  22. // Make sure we have a v1 header
  23. line, err := reader.ReadString('\n')
  24. if !strings.HasSuffix(line, CRLF) {
  25. return nil, ErrCantReadProtocolVersionAndCommand
  26. }
  27. tokens := strings.Split(line[:len(line)-2], SEPARATOR)
  28. if len(tokens) < 6 {
  29. return nil, ErrCantReadProtocolVersionAndCommand
  30. }
  31. header := initVersion1()
  32. // Read address family and protocol
  33. switch tokens[1] {
  34. case "TCP4":
  35. header.TransportProtocol = TCPv4
  36. case "TCP6":
  37. header.TransportProtocol = TCPv6
  38. default:
  39. header.TransportProtocol = UNSPEC
  40. }
  41. // Read addresses and ports
  42. header.SourceAddress, err = parseV1IPAddress(header.TransportProtocol, tokens[2])
  43. if err != nil {
  44. return nil, err
  45. }
  46. header.DestinationAddress, err = parseV1IPAddress(header.TransportProtocol, tokens[3])
  47. if err != nil {
  48. return nil, err
  49. }
  50. header.SourcePort, err = parseV1PortNumber(tokens[4])
  51. if err != nil {
  52. return nil, err
  53. }
  54. header.DestinationPort, err = parseV1PortNumber(tokens[5])
  55. if err != nil {
  56. return nil, err
  57. }
  58. return header, nil
  59. }
  60. func (header *Header) writeVersion1(w io.Writer) (int64, error) {
  61. // As of version 1, only "TCP4" ( \x54 \x43 \x50 \x34 ) for TCP over IPv4,
  62. // and "TCP6" ( \x54 \x43 \x50 \x36 ) for TCP over IPv6 are allowed.
  63. proto := "UNKNOWN"
  64. if header.TransportProtocol == TCPv4 {
  65. proto = "TCP4"
  66. } else if header.TransportProtocol == TCPv6 {
  67. proto = "TCP6"
  68. }
  69. var buf bytes.Buffer
  70. buf.Write(SIGV1)
  71. buf.WriteString(SEPARATOR)
  72. buf.WriteString(proto)
  73. buf.WriteString(SEPARATOR)
  74. buf.WriteString(header.SourceAddress.String())
  75. buf.WriteString(SEPARATOR)
  76. buf.WriteString(header.DestinationAddress.String())
  77. buf.WriteString(SEPARATOR)
  78. buf.WriteString(strconv.Itoa(int(header.SourcePort)))
  79. buf.WriteString(SEPARATOR)
  80. buf.WriteString(strconv.Itoa(int(header.DestinationPort)))
  81. buf.WriteString(CRLF)
  82. return buf.WriteTo(w)
  83. }
  84. func parseV1PortNumber(portStr string) (uint16, error) {
  85. var port uint16
  86. _port, err := strconv.Atoi(portStr)
  87. if err == nil {
  88. if port < 0 || port > 65535 {
  89. err = ErrInvalidPortNumber
  90. }
  91. port = uint16(_port)
  92. }
  93. return port, err
  94. }
  95. func parseV1IPAddress(protocol AddressFamilyAndProtocol, addrStr string) (addr net.IP, err error) {
  96. addr = net.ParseIP(addrStr)
  97. tryV4 := addr.To4()
  98. if (protocol == TCPv4 && tryV4 == nil) || (protocol == TCPv6 && tryV4 != nil) {
  99. err = ErrInvalidAddress
  100. }
  101. return
  102. }