Merge b8abeaff50
into de1a4c463c
This commit is contained in:
commit
1562d475bb
1 changed files with 48 additions and 3 deletions
|
@ -40,6 +40,9 @@ type TCPProxy struct {
|
||||||
Default *TCPServer
|
Default *TCPServer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tlsHeaderLength = 5
|
||||||
|
var tlsMaxMessageLength = 16384
|
||||||
|
|
||||||
// Get returns the TCPServer to use for a given host.
|
// Get returns the TCPServer to use for a given host.
|
||||||
func (p *TCPProxy) Get(host string) *TCPServer {
|
func (p *TCPProxy) Get(host string) *TCPServer {
|
||||||
if p.ServerList == nil {
|
if p.ServerList == nil {
|
||||||
|
@ -59,15 +62,57 @@ func (p *TCPProxy) Get(host string) *TCPServer {
|
||||||
// and open a connection to the passthrough server.
|
// and open a connection to the passthrough server.
|
||||||
func (p *TCPProxy) Handle(conn net.Conn) {
|
func (p *TCPProxy) Handle(conn net.Conn) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
// See: https://www.ibm.com/docs/en/ztpf/1.1.0.15?topic=sessions-ssl-record-format
|
// It appears that the ClientHello must fit into *one* TLSPlaintext message:
|
||||||
data := make([]byte, 16384)
|
// When a client first connects to a server, it is REQUIRED to send the
|
||||||
|
// ClientHello as its first TLS message.
|
||||||
|
// Source: https://datatracker.ietf.org/doc/html/rfc8446#section-4.1.2
|
||||||
|
|
||||||
length, err := conn.Read(data)
|
// length: The length (in bytes) of the following
|
||||||
|
// TLSPlaintext.fragment. The length MUST NOT exceed 2^14 bytes. An
|
||||||
|
// endpoint that receives a record that exceeds this length MUST
|
||||||
|
// terminate the connection with a "record_overflow" alert.
|
||||||
|
// Source: https://datatracker.ietf.org/doc/html/rfc8446#section-5.1
|
||||||
|
// bytes 0 : content type
|
||||||
|
// bytes 1-2: legacy version
|
||||||
|
// bytes 3-4: length
|
||||||
|
// bytes 5+ : message
|
||||||
|
// https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_record
|
||||||
|
// Thus, we need to allocate 5 + 16384 bytes
|
||||||
|
data := make([]byte, tlsHeaderLength+tlsMaxMessageLength)
|
||||||
|
|
||||||
|
length := 0
|
||||||
|
ensureBytesRead := func(n int) error {
|
||||||
|
if n > len(data) {
|
||||||
|
return fmt.Errorf("attempted to read more bytes than buffer size: %d vs %d", n, len(data))
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
fragmentLength, err := conn.Read(data[length:])
|
||||||
|
length += fragmentLength
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if length >= n {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := ensureBytesRead(tlsHeaderLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.V(4).ErrorS(err, "Error reading data from the connection")
|
klog.V(4).ErrorS(err, "Error reading data from the connection")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// otherwise, ensureBytesRead may produce an index out of bounds
|
||||||
|
clientHelloLength := min(int(data[3])<<8+int(data[4]), tlsMaxMessageLength)
|
||||||
|
|
||||||
|
err = ensureBytesRead(tlsHeaderLength + clientHelloLength)
|
||||||
|
if err != nil {
|
||||||
|
klog.V(4).ErrorS(err, "Error reading ClientHello of length %d from the connection", clientHelloLength)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
proxy := p.Default
|
proxy := p.Default
|
||||||
hostname, err := parser.GetHostname(data)
|
hostname, err := parser.GetHostname(data)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
Loading…
Reference in a new issue