-
-
Notifications
You must be signed in to change notification settings - Fork 118
Description
Hi! I found that this library is missing the ability to parse these two kinds of header, which are required by the protocol and mandatory to implement, while trying to resolve XTLS/Xray-core#166
v2 UNSPEC
When this header is received:
0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a 20 00 00 00
which is + LOCAL command (\x20) + UNSPEC address family UNSPEC protocol (\x00)
ErrUnsupportedAddressFamilyAndProtocol is returned
Lines 85 to 87 in adbbabe
| if _, ok := supportedTransportProtocol[header.TransportProtocol]; !ok { | |
| return nil, ErrUnsupportedAddressFamilyAndProtocol | |
| } |
This is because UNSPEC is absent in supportedTransportProtocol
Lines 6 to 23 in adbbabe
| const ( | |
| UNSPEC AddressFamilyAndProtocol = '\x00' | |
| TCPv4 AddressFamilyAndProtocol = '\x11' | |
| UDPv4 AddressFamilyAndProtocol = '\x12' | |
| TCPv6 AddressFamilyAndProtocol = '\x21' | |
| UDPv6 AddressFamilyAndProtocol = '\x22' | |
| UnixStream AddressFamilyAndProtocol = '\x31' | |
| UnixDatagram AddressFamilyAndProtocol = '\x32' | |
| ) | |
| var supportedTransportProtocol = map[AddressFamilyAndProtocol]bool{ | |
| TCPv4: true, | |
| UDPv4: true, | |
| TCPv6: true, | |
| UDPv6: true, | |
| UnixStream: true, | |
| UnixDatagram: true, | |
| } |
This UNSPEC header is used when HAProxy doing health checks, or the proxied client is requesting via a unix socket.
Also the protocol spec says:
Only the UNSPEC protocol byte (\x00) is mandatory to implement on the receiver.
A receiver is not required to implement other ones, provided that it
automatically falls back to the UNSPEC mode for the valid combinations above
that it does not support.
v1 PROXY UNKNOWN
When header PROXY UNKNOWN\r\n is received,
Lines 25 to 33 in adbbabe
| // 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 | |
| } |
returns ErrCantReadProtocolVersionAndCommand.
This is because in this case, there's only 2 parts separated by spaces, instead of 6 parts as
PROXY <PROTO> <SRC_ADDR> <DEST_ADDR> <SRC_PORT> <DEST_PORT>The protocol spec says:
If the announced transport protocol is "UNKNOWN", then the receiver knows that
the sender speaks the correct PROXY protocol with the appropriate version, and
SHOULD accept the connection and use the real connection's parameters as if
there were no PROXY protocol header on the wire.
Also, this kind of header can be formatted by the library.
Lines 76 to 88 in adbbabe
| func (header *Header) formatVersion1() ([]byte, 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. | |
| var proto string | |
| switch header.TransportProtocol { | |
| case TCPv4: | |
| proto = "TCP4" | |
| case TCPv6: | |
| proto = "TCP6" | |
| default: | |
| // Unknown connection (short form) | |
| return []byte("PROXY UNKNOWN\r\n"), nil | |
| } |
Although I really don't know much about Golang, I'll try my best to support you to resolve this issue. Thanks!