@@ -40,6 +40,11 @@ type TCPProxy struct {
40
40
Default * TCPServer
41
41
}
42
42
43
+ var (
44
+ tlsHeaderLength = 5
45
+ tlsMaxMessageLength = 16384
46
+ )
47
+
43
48
// Get returns the TCPServer to use for a given host.
44
49
func (p * TCPProxy ) Get (host string ) * TCPServer {
45
50
if p .ServerList == nil {
@@ -59,15 +64,37 @@ func (p *TCPProxy) Get(host string) *TCPServer {
59
64
// and open a connection to the passthrough server.
60
65
func (p * TCPProxy ) Handle (conn net.Conn ) {
61
66
defer conn .Close ()
62
- // See: https://www.ibm.com/docs/en/ztpf/1.1.0.15?topic=sessions-ssl-record-format
63
- data := make ([]byte , 16384 )
64
-
65
- length , err := conn .Read (data )
67
+ // It appears that the ClientHello must fit into *one* TLSPlaintext message:
68
+ // When a client first connects to a server, it is REQUIRED to send the ClientHello as its first TLS message.
69
+ // Source: https://datatracker.ietf.org/doc/html/rfc8446#section-4.1.2
70
+
71
+ // length: The length (in bytes) of the following TLSPlaintext.fragment. The length MUST NOT exceed 2^14 bytes.
72
+ // An endpoint that receives a record that exceeds this length MUST terminate the connection with a "record_overflow" alert.
73
+ // Source: https://datatracker.ietf.org/doc/html/rfc8446#section-5.1
74
+ // bytes 0 : content type
75
+ // bytes 1-2: legacy version
76
+ // bytes 3-4: length
77
+ // bytes 5+ : message
78
+ // https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_record
79
+ // Thus, we need to allocate 5 + 16384 bytes
80
+ data := make ([]byte , tlsHeaderLength + tlsMaxMessageLength )
81
+
82
+ length , err := io .ReadAtLeast (conn , data , tlsHeaderLength )
66
83
if err != nil {
67
84
klog .V (4 ).ErrorS (err , "Error reading data from the connection" )
68
85
return
69
86
}
70
87
88
+ // otherwise, ReadAtLeast may produce an index out of bounds
89
+ clientHelloLength := min (int (data [3 ])<< 8 + int (data [4 ]), tlsMaxMessageLength )
90
+
91
+ bLength , err := io .ReadAtLeast (conn , data [length :], tlsHeaderLength + clientHelloLength - length )
92
+ if err != nil {
93
+ klog .V (4 ).ErrorS (err , fmt .Sprintf ("Error reading ClientHello of length %d from the connection" , clientHelloLength ))
94
+ return
95
+ }
96
+ length += bLength
97
+
71
98
proxy := p .Default
72
99
hostname , err := parser .GetHostname (data )
73
100
if err == nil {
0 commit comments