@@ -77,7 +77,7 @@ func (p *Server) Start(ctx context.Context) error {
77
77
p .logger .Error ("Failed to create HTTP listener" , "error" , err )
78
78
return
79
79
}
80
-
80
+
81
81
for {
82
82
conn , err := listener .Accept ()
83
83
if err != nil {
@@ -90,7 +90,7 @@ func (p *Server) Start(ctx context.Context) error {
90
90
continue
91
91
}
92
92
}
93
-
93
+
94
94
// Handle connection with TLS detection
95
95
go p .handleConnectionWithTLSDetection (conn )
96
96
}
@@ -132,7 +132,7 @@ func (p *Server) Stop() error {
132
132
// handleHTTP handles regular HTTP requests and CONNECT tunneling
133
133
func (p * Server ) handleHTTP (w http.ResponseWriter , r * http.Request ) {
134
134
p .logger .Debug ("handleHTTP called" , "method" , r .Method , "url" , r .URL .String (), "host" , r .Host )
135
-
135
+
136
136
// Handle CONNECT method for HTTPS tunneling
137
137
if r .Method == "CONNECT" {
138
138
p .handleConnect (w , r )
@@ -184,20 +184,19 @@ func (p *Server) handleHTTPS(w http.ResponseWriter, r *http.Request) {
184
184
// forwardHTTPRequest forwards a regular HTTP request
185
185
func (p * Server ) forwardHTTPRequest (w http.ResponseWriter , r * http.Request ) {
186
186
p .logger .Debug ("forwardHTTPRequest called" , "method" , r .Method , "url" , r .URL .String (), "host" , r .Host )
187
-
187
+
188
188
// Create a new request to the target server
189
189
targetURL := & url.URL {
190
- Scheme : "http" ,
191
- Host : r .Host ,
192
- Path : r .URL .Path ,
190
+ Scheme : "http" ,
191
+ Host : r .Host ,
192
+ Path : r .URL .Path ,
193
193
RawQuery : r .URL .RawQuery ,
194
194
}
195
195
196
196
p .logger .Debug ("Target URL constructed" , "target" , targetURL .String ())
197
197
198
198
// Create HTTP client with very short timeout for debugging
199
199
client := & http.Client {
200
- Timeout : 2 * time .Second ,
201
200
CheckRedirect : func (req * http.Request , via []* http.Request ) error {
202
201
return http .ErrUseLastResponse // Don't follow redirects
203
202
},
@@ -223,14 +222,7 @@ func (p *Server) forwardHTTPRequest(w http.ResponseWriter, r *http.Request) {
223
222
}
224
223
225
224
p .logger .Debug ("About to make HTTP request" , "target" , targetURL .String ())
226
-
227
- // Make the request synchronously - this is the key fix
228
- p .logger .Debug ("Calling client.Do() now..." )
229
- start := time .Now ()
230
225
resp , err := client .Do (req )
231
- duration := time .Since (start )
232
- p .logger .Debug ("client.Do() completed" , "duration" , duration , "error" , err )
233
-
234
226
if err != nil {
235
227
p .logger .Error ("Failed to make forward request" , "error" , err , "target" , targetURL .String (), "error_type" , fmt .Sprintf ("%T" , err ))
236
228
http .Error (w , fmt .Sprintf ("Failed to make request: %v" , err ), http .StatusBadGateway )
@@ -281,7 +273,6 @@ func (p *Server) forwardHTTPSRequest(w http.ResponseWriter, r *http.Request) {
281
273
282
274
// Create HTTPS client
283
275
client := & http.Client {
284
- Timeout : 30 * time .Second ,
285
276
Transport : & http.Transport {
286
277
TLSClientConfig : & tls.Config {
287
278
InsecureSkipVerify : false ,
@@ -339,24 +330,7 @@ func (p *Server) writeBlockedResponse(w http.ResponseWriter, r *http.Request) {
339
330
host = r .Host
340
331
}
341
332
342
- // Handle CONNECT requests differently (HTTPS tunneling)
343
- if r .Method == "CONNECT" {
344
- fmt .Fprintf (w , `🚫 HTTPS Request Blocked by Coder Jail
345
-
346
- Connection: %s (HTTPS)
347
- Host: %s
348
-
349
- This HTTPS request was blocked by jail's security policy.
350
-
351
- To allow this request, restart jail with:
352
- --allow "%s" # Allow all methods to this host
353
- --allow "CONNECT %s" # Allow only HTTPS connections to this host
354
-
355
- For more help: https://github.com/coder/jail
356
- ` ,
357
- r .URL .Host , host , host , host )
358
- } else {
359
- fmt .Fprintf (w , `🚫 Request Blocked by Coder Jail
333
+ fmt .Fprintf (w , `🚫 Request Blocked by Coder Jail
360
334
361
335
Request: %s %s
362
336
Host: %s
@@ -367,8 +341,7 @@ To allow this request, restart jail with:
367
341
368
342
For more help: https://github.com/coder/jail
369
343
` ,
370
- r .Method , r .URL .Path , host , host , r .Method , host , r .Method )
371
- }
344
+ r .Method , r .URL .Path , host , host , r .Method , host , r .Method )
372
345
}
373
346
374
347
// handleConnect handles CONNECT requests for HTTPS tunneling with TLS termination
@@ -420,11 +393,11 @@ func (p *Server) handleConnect(w http.ResponseWriter, r *http.Request) {
420
393
421
394
// Perform TLS handshake with the client using our certificates
422
395
p .logger .Debug ("Starting TLS handshake" , "hostname" , hostname )
423
-
396
+
424
397
// Create TLS config that forces HTTP/1.1 (disable HTTP/2 ALPN)
425
398
tlsConfig := p .tlsConfig .Clone ()
426
399
tlsConfig .NextProtos = []string {"http/1.1" }
427
-
400
+
428
401
tlsConn := tls .Server (conn , tlsConfig )
429
402
err = tlsConn .Handshake ()
430
403
if err != nil {
@@ -442,7 +415,7 @@ func (p *Server) handleConnect(w http.ResponseWriter, r *http.Request) {
442
415
// handleTLSConnection processes decrypted HTTPS requests over the TLS connection
443
416
func (p * Server ) handleTLSConnection (tlsConn * tls.Conn , hostname string ) {
444
417
p .logger .Debug ("Creating HTTP server for TLS connection" , "hostname" , hostname )
445
-
418
+
446
419
// Use ReadRequest to manually read HTTP requests from the TLS connection
447
420
bufReader := bufio .NewReader (tlsConn )
448
421
for {
@@ -456,9 +429,9 @@ func (p *Server) handleTLSConnection(tlsConn *tls.Conn, hostname string) {
456
429
}
457
430
break
458
431
}
459
-
432
+
460
433
p .logger .Debug ("Processing decrypted HTTPS request" , "hostname" , hostname , "method" , req .Method , "path" , req .URL .Path )
461
-
434
+
462
435
// Set the hostname and scheme if not already set
463
436
if req .URL .Host == "" {
464
437
req .URL .Host = hostname
@@ -469,22 +442,22 @@ func (p *Server) handleTLSConnection(tlsConn *tls.Conn, hostname string) {
469
442
470
443
// Create a response recorder to capture the response
471
444
recorder := httptest .NewRecorder ()
472
-
445
+
473
446
// Process the HTTPS request
474
447
p .handleDecryptedHTTPS (recorder , req )
475
-
448
+
476
449
// Write the response back to the TLS connection
477
450
resp := recorder .Result ()
478
451
err = resp .Write (tlsConn )
479
452
if err != nil {
480
453
p .logger .Debug ("Failed to write response" , "hostname" , hostname , "error" , err )
481
454
break
482
455
}
483
-
456
+
484
457
// Close connection after single request (HTTP/1.0 style)
485
458
break
486
459
}
487
-
460
+
488
461
p .logger .Debug ("TLS connection handling completed" , "hostname" , hostname )
489
462
}
490
463
@@ -556,50 +529,50 @@ func (p *Server) handleConnectionWithTLSDetection(conn net.Conn) {
556
529
func (p * Server ) handleTLSTermination (conn net.Conn , firstByte []byte ) {
557
530
// Create a connection that prepends the first byte we already read
558
531
connWithFirstByte := & connectionWithPrefix {
559
- Conn : conn ,
532
+ Conn : conn ,
560
533
prefix : firstByte ,
561
534
}
562
535
563
536
// We need to extract the SNI (Server Name Indication) from the TLS handshake
564
537
// to generate the appropriate certificate. For now, use a default hostname.
565
538
hostname := "unknown-host"
566
-
539
+
567
540
// TODO: Extract hostname from TLS ClientHello SNI extension
568
541
// For now, we'll perform TLS termination with a generic certificate
569
-
542
+
570
543
// Perform TLS handshake with our certificate
571
544
tlsConn := tls .Server (connWithFirstByte , p .tlsConfig )
572
545
err := tlsConn .Handshake ()
573
546
if err != nil {
574
547
p .logger .Debug ("TLS handshake failed" , "error" , err )
575
548
return
576
549
}
577
-
550
+
578
551
p .logger .Debug ("TLS handshake successful, processing decrypted HTTPS traffic" )
579
-
552
+
580
553
// Now handle the decrypted HTTPS requests using our existing logic
581
554
p .handleTLSConnection (tlsConn , hostname )
582
555
}
583
556
584
557
// handleHTTPConnection handles regular HTTP connections
585
558
func (p * Server ) handleHTTPConnection (conn net.Conn , firstByte []byte ) {
586
559
p .logger .Debug ("Starting HTTP connection handling" )
587
-
560
+
588
561
// Create a connection that prepends the first byte we already read
589
562
connWithFirstByte := & connectionWithPrefix {
590
- Conn : conn ,
563
+ Conn : conn ,
591
564
prefix : firstByte ,
592
565
}
593
566
594
567
p .logger .Debug ("Created connection wrapper, starting HTTP server" )
595
-
568
+
596
569
// Create HTTP server to handle this connection
597
570
server := & http.Server {
598
571
Handler : http .HandlerFunc (p .handleHTTP ),
599
572
}
600
573
601
574
p .logger .Debug ("About to serve HTTP connection" )
602
-
575
+
603
576
// Serve the HTTP request
604
577
err := server .Serve (& singleConnListener {conn : connWithFirstByte })
605
578
if err != nil && err != io .EOF && ! isConnectionClosed (err ) {
@@ -619,15 +592,15 @@ func (p *Server) handleHTTPWithTLSTermination(w http.ResponseWriter, r *http.Req
619
592
// connectionWithPrefix wraps a connection and prepends some data
620
593
type connectionWithPrefix struct {
621
594
net.Conn
622
- prefix []byte
595
+ prefix []byte
623
596
prefixRead bool
624
- mu sync.Mutex
597
+ mu sync.Mutex
625
598
}
626
599
627
600
func (c * connectionWithPrefix ) Read (b []byte ) (n int , err error ) {
628
601
c .mu .Lock ()
629
602
defer c .mu .Unlock ()
630
-
603
+
631
604
if ! c .prefixRead && len (c .prefix ) > 0 {
632
605
// Return the prefix data first
633
606
n = copy (b , c .prefix )
@@ -659,7 +632,7 @@ type singleConnListener struct {
659
632
func (l * singleConnListener ) Accept () (net.Conn , error ) {
660
633
l .mu .Lock ()
661
634
defer l .mu .Unlock ()
662
-
635
+
663
636
if l .used {
664
637
return nil , io .EOF
665
638
}
@@ -678,7 +651,7 @@ func (l *singleConnListener) Addr() net.Addr {
678
651
// handleHTTPConnectionDirect handles HTTP connections directly without HTTP server framework
679
652
func (p * Server ) handleHTTPConnectionDirect (bufReader * bufio.Reader , conn net.Conn ) {
680
653
p .logger .Debug ("Starting direct HTTP connection handling" )
681
-
654
+
682
655
// Parse the HTTP request manually
683
656
req , err := http .ReadRequest (bufReader )
684
657
if err != nil {
@@ -717,12 +690,12 @@ func (p *Server) handleHTTPConnectionDirect(bufReader *bufio.Reader, conn net.Co
717
690
// forwardHTTPRequestDirect forwards HTTP request and writes response directly to connection
718
691
func (p * Server ) forwardHTTPRequestDirect (req * http.Request , conn net.Conn ) {
719
692
p .logger .Debug ("forwardHTTPRequestDirect called" , "method" , req .Method , "url" , req .URL .String (), "host" , req .Host )
720
-
693
+
721
694
// Create target URL
722
695
targetURL := & url.URL {
723
- Scheme : "http" ,
724
- Host : req .Host ,
725
- Path : req .URL .Path ,
696
+ Scheme : "http" ,
697
+ Host : req .Host ,
698
+ Path : req .URL .Path ,
726
699
RawQuery : req .URL .RawQuery ,
727
700
}
728
701
@@ -786,7 +759,7 @@ func (p *Server) forwardHTTPRequestDirect(req *http.Request, conn net.Conn) {
786
759
conn .Write ([]byte (headerLine ))
787
760
}
788
761
}
789
-
762
+
790
763
// End headers
791
764
conn .Write ([]byte ("\r \n " ))
792
765
@@ -805,31 +778,31 @@ func (p *Server) forwardHTTPRequestDirect(req *http.Request, conn net.Conn) {
805
778
func (p * Server ) handleTLSTerminationDirect (bufReader * bufio.Reader , conn net.Conn ) {
806
779
// Create a connection that uses the buffered reader
807
780
bufferedConn := & bufferedConnection {
808
- Conn : conn ,
781
+ Conn : conn ,
809
782
reader : bufReader ,
810
783
}
811
784
812
785
// Extract hostname from TLS SNI (TODO: implement SNI parsing)
813
786
hostname := "unknown-host"
814
-
787
+
815
788
// Perform TLS handshake with our certificate
816
789
tlsConn := tls .Server (bufferedConn , p .tlsConfig )
817
790
err := tlsConn .Handshake ()
818
791
if err != nil {
819
792
p .logger .Debug ("TLS handshake failed" , "error" , err )
820
793
return
821
794
}
822
-
795
+
823
796
p .logger .Debug ("TLS handshake successful, processing decrypted HTTPS traffic" )
824
-
797
+
825
798
// Handle the decrypted HTTPS requests
826
799
p .handleTLSConnection (tlsConn , hostname )
827
800
}
828
801
829
802
// connectionWrapper lets us "unread" the peeked byte
830
803
type connectionWrapper struct {
831
804
net.Conn
832
- buf []byte
805
+ buf []byte
833
806
bufUsed bool
834
807
}
835
808
@@ -862,7 +835,7 @@ func newSingleConnectionListener(conn net.Conn) *singleConnectionListener {
862
835
func (sl * singleConnectionListener ) Accept () (net.Conn , error ) {
863
836
sl .mu .Lock ()
864
837
defer sl .mu .Unlock ()
865
-
838
+
866
839
if sl .used || sl .conn == nil {
867
840
// Wait for close signal
868
841
<- sl .closed
@@ -875,14 +848,14 @@ func (sl *singleConnectionListener) Accept() (net.Conn, error) {
875
848
func (sl * singleConnectionListener ) Close () error {
876
849
sl .mu .Lock ()
877
850
defer sl .mu .Unlock ()
878
-
851
+
879
852
select {
880
853
case <- sl .closed :
881
854
// Already closed
882
855
default :
883
856
close (sl .closed )
884
857
}
885
-
858
+
886
859
if sl .conn != nil {
887
860
sl .conn .Close ()
888
861
sl .conn = nil
@@ -905,4 +878,4 @@ type bufferedConnection struct {
905
878
906
879
func (bc * bufferedConnection ) Read (b []byte ) (n int , err error ) {
907
880
return bc .reader .Read (b )
908
- }
881
+ }
0 commit comments