Skip to content

Commit 1c08958

Browse files
blink-so[bot]f0ssel
andcommitted
Fix HTTP connection handling with buffered reader approach
- Replace byte-consumption approach with bufio.Reader.Peek() - Avoid issues with already-read bytes in HTTP parsing - Add buffered connection wrappers for both HTTP and TLS handling - Should resolve 'connection reset by peer' in privileged mode - Maintains protocol detection while preserving complete request data Co-authored-by: f0ssel <[email protected]>
1 parent c297fa5 commit 1c08958

File tree

1 file changed

+77
-10
lines changed

1 file changed

+77
-10
lines changed

proxy/proxy.go

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -480,23 +480,21 @@ func (p *Server) handleDecryptedHTTPS(w http.ResponseWriter, r *http.Request) {
480480
func (p *Server) handleConnectionWithTLSDetection(conn net.Conn) {
481481
defer conn.Close()
482482

483-
// Peek at the first byte to detect TLS handshake
484-
conn.SetReadDeadline(time.Now().Add(5 * time.Second))
485-
firstByte := make([]byte, 1)
486-
n, err := conn.Read(firstByte)
487-
if err != nil || n == 0 {
488-
p.logger.Debug("Failed to read first byte from connection", "error", err)
483+
// Use a buffered reader to peek at the first byte without consuming it
484+
bufReader := bufio.NewReader(conn)
485+
firstByte, err := bufReader.Peek(1)
486+
if err != nil {
487+
p.logger.Debug("Failed to peek at connection data", "error", err)
489488
return
490489
}
491-
conn.SetReadDeadline(time.Time{}) // Clear deadline
492490

493491
// TLS handshake starts with 0x16 (TLS Content Type: Handshake)
494-
if firstByte[0] == 0x16 {
492+
if len(firstByte) > 0 && firstByte[0] == 0x16 {
495493
p.logger.Debug("Detected TLS handshake, performing TLS termination")
496-
p.handleTLSTermination(conn, firstByte)
494+
p.handleTLSTerminationBuffered(bufReader, conn)
497495
} else {
498496
p.logger.Debug("Detected HTTP request, handling normally")
499-
p.handleHTTPConnection(conn, firstByte)
497+
p.handleHTTPConnectionBuffered(bufReader, conn)
500498
}
501499
}
502500

@@ -569,14 +567,20 @@ type connectionWithPrefix struct {
569567
net.Conn
570568
prefix []byte
571569
prefixRead bool
570+
mu sync.Mutex
572571
}
573572

574573
func (c *connectionWithPrefix) Read(b []byte) (n int, err error) {
574+
c.mu.Lock()
575+
defer c.mu.Unlock()
576+
575577
if !c.prefixRead && len(c.prefix) > 0 {
578+
// Return the prefix data first
576579
n = copy(b, c.prefix)
577580
c.prefixRead = true
578581
return n, nil
579582
}
583+
// After prefix is read, delegate to underlying connection
580584
return c.Conn.Read(b)
581585
}
582586

@@ -615,4 +619,67 @@ func (l *singleConnListener) Close() error {
615619

616620
func (l *singleConnListener) Addr() net.Addr {
617621
return l.conn.LocalAddr()
622+
}
623+
624+
// handleHTTPConnectionBuffered handles regular HTTP connections using buffered reader
625+
func (p *Server) handleHTTPConnectionBuffered(bufReader *bufio.Reader, conn net.Conn) {
626+
p.logger.Debug("Starting buffered HTTP connection handling")
627+
628+
// Create a connection that uses the buffered reader
629+
bufferedConn := &bufferedConnection{
630+
Conn: conn,
631+
reader: bufReader,
632+
}
633+
634+
p.logger.Debug("Created buffered connection, starting HTTP server")
635+
636+
// Create HTTP server to handle this connection
637+
server := &http.Server{
638+
Handler: http.HandlerFunc(p.handleHTTP),
639+
}
640+
641+
p.logger.Debug("About to serve buffered HTTP connection")
642+
643+
// Serve the HTTP request
644+
err := server.Serve(&singleConnListener{conn: bufferedConn})
645+
if err != nil && err != io.EOF && !isConnectionClosed(err) {
646+
p.logger.Debug("Buffered HTTP connection error", "error", err)
647+
} else {
648+
p.logger.Debug("Buffered HTTP connection completed successfully")
649+
}
650+
}
651+
652+
// handleTLSTerminationBuffered performs TLS termination using buffered reader
653+
func (p *Server) handleTLSTerminationBuffered(bufReader *bufio.Reader, conn net.Conn) {
654+
// Create a connection that uses the buffered reader
655+
bufferedConn := &bufferedConnection{
656+
Conn: conn,
657+
reader: bufReader,
658+
}
659+
660+
// Extract hostname from TLS SNI (TODO: implement SNI parsing)
661+
hostname := "unknown-host"
662+
663+
// Perform TLS handshake with our certificate
664+
tlsConn := tls.Server(bufferedConn, p.tlsConfig)
665+
err := tlsConn.Handshake()
666+
if err != nil {
667+
p.logger.Debug("Buffered TLS handshake failed", "error", err)
668+
return
669+
}
670+
671+
p.logger.Debug("Buffered TLS handshake successful, processing decrypted HTTPS traffic")
672+
673+
// Handle the decrypted HTTPS requests
674+
p.handleTLSConnection(tlsConn, hostname)
675+
}
676+
677+
// bufferedConnection wraps a connection with a buffered reader
678+
type bufferedConnection struct {
679+
net.Conn
680+
reader *bufio.Reader
681+
}
682+
683+
func (bc *bufferedConnection) Read(b []byte) (n int, err error) {
684+
return bc.reader.Read(b)
618685
}

0 commit comments

Comments
 (0)