Skip to content

Commit 20b15b0

Browse files
blink-so[bot]f0ssel
andcommitted
Fix HTTPS inspection on Linux - replace HTTP server with manual request handling
- Replace singleConnListener approach with manual HTTP request reading - Use http.ReadRequest to parse HTTP/1.x requests from TLS connection - Add comprehensive debug logging for troubleshooting - Fix connection handling to properly process and respond to HTTPS requests - Resolves silent connection drops on Linux systems Tested and working: TLS termination, HTTPS decryption, rule evaluation, blocking Co-authored-by: f0ssel <[email protected]>
1 parent 010226f commit 20b15b0

File tree

1 file changed

+48
-40
lines changed

1 file changed

+48
-40
lines changed

proxy/proxy.go

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package proxy
22

33
import (
4+
"bufio"
45
"context"
56
"crypto/tls"
67
"fmt"
78
"io"
89
"log/slog"
910
"net"
1011
"net/http"
12+
"net/http/httptest"
1113
"net/url"
1214
"time"
1315

@@ -361,40 +363,68 @@ func (p *Server) handleConnect(w http.ResponseWriter, r *http.Request) {
361363
}
362364

363365
// Perform TLS handshake with the client using our certificates
366+
p.logger.Debug("Starting TLS handshake", "hostname", hostname)
364367
tlsConn := tls.Server(conn, p.tlsConfig)
365368
err = tlsConn.Handshake()
366369
if err != nil {
367370
p.logger.Error("TLS handshake failed", "hostname", hostname, "error", err)
368371
return
369372
}
373+
p.logger.Debug("TLS handshake successful", "hostname", hostname)
370374

371375
// Now we have a TLS connection - handle HTTPS requests
376+
p.logger.Debug("Starting HTTPS request handling", "hostname", hostname)
372377
p.handleTLSConnection(tlsConn, hostname)
378+
p.logger.Debug("HTTPS request handling completed", "hostname", hostname)
373379
}
374380

375381
// handleTLSConnection processes decrypted HTTPS requests over the TLS connection
376382
func (p *Server) handleTLSConnection(tlsConn *tls.Conn, hostname string) {
377-
// Create an HTTP server to handle requests over the TLS connection
378-
server := &http.Server{
379-
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
380-
// Set the hostname if not already set
381-
if r.URL.Host == "" {
382-
r.URL.Host = hostname
383+
p.logger.Debug("Creating HTTP server for TLS connection", "hostname", hostname)
384+
385+
// Use ReadRequest to manually read HTTP requests from the TLS connection
386+
bufReader := bufio.NewReader(tlsConn)
387+
for {
388+
// Read HTTP request from TLS connection
389+
req, err := http.ReadRequest(bufReader)
390+
if err != nil {
391+
if err == io.EOF {
392+
p.logger.Debug("TLS connection closed by client", "hostname", hostname)
393+
} else {
394+
p.logger.Debug("Failed to read HTTP request", "hostname", hostname, "error", err)
383395
}
384-
if r.URL.Scheme == "" {
385-
r.URL.Scheme = "https"
386-
}
387-
388-
// Process this as an HTTPS request
389-
p.handleDecryptedHTTPS(w, r)
390-
}),
391-
}
396+
break
397+
}
398+
399+
p.logger.Debug("Processing decrypted HTTPS request", "hostname", hostname, "method", req.Method, "path", req.URL.Path)
400+
401+
// Set the hostname and scheme if not already set
402+
if req.URL.Host == "" {
403+
req.URL.Host = hostname
404+
}
405+
if req.URL.Scheme == "" {
406+
req.URL.Scheme = "https"
407+
}
392408

393-
// Serve HTTP over the TLS connection
394-
err := server.Serve(&singleConnListener{conn: tlsConn})
395-
if err != nil && err != io.EOF {
396-
p.logger.Debug("TLS connection closed", "hostname", hostname, "error", err)
409+
// Create a response recorder to capture the response
410+
recorder := httptest.NewRecorder()
411+
412+
// Process the HTTPS request
413+
p.handleDecryptedHTTPS(recorder, req)
414+
415+
// Write the response back to the TLS connection
416+
resp := recorder.Result()
417+
err = resp.Write(tlsConn)
418+
if err != nil {
419+
p.logger.Debug("Failed to write response", "hostname", hostname, "error", err)
420+
break
421+
}
422+
423+
// Close connection after single request (HTTP/1.0 style)
424+
break
397425
}
426+
427+
p.logger.Debug("TLS connection handling completed", "hostname", hostname)
398428
}
399429

400430
// handleDecryptedHTTPS handles decrypted HTTPS requests and applies rules
@@ -417,26 +447,4 @@ func (p *Server) handleDecryptedHTTPS(w http.ResponseWriter, r *http.Request) {
417447

418448
// Forward the HTTPS request
419449
p.forwardHTTPSRequest(w, r)
420-
}
421-
422-
// singleConnListener wraps a single connection to implement net.Listener
423-
type singleConnListener struct {
424-
conn net.Conn
425-
used bool
426-
}
427-
428-
func (l *singleConnListener) Accept() (net.Conn, error) {
429-
if l.used {
430-
return nil, io.EOF
431-
}
432-
l.used = true
433-
return l.conn, nil
434-
}
435-
436-
func (l *singleConnListener) Close() error {
437-
return l.conn.Close()
438-
}
439-
440-
func (l *singleConnListener) Addr() net.Addr {
441-
return l.conn.LocalAddr()
442450
}

0 commit comments

Comments
 (0)