@@ -319,14 +319,16 @@ func (r *policyRuleSet) Allow(ctx context.Context, req *socks5.Request) (context
319319 log .Printf ("[ASK->DENY] %s:%d (no approval broker)" , dest , port )
320320 } else {
321321 // Auto-allow the SOCKS5 CONNECT without prompting the user.
322- // Approval happens per-request inside the MITM handler where
323- // the HTTP method and path are known, producing a single
324- // combined Telegram message per request instead of two
325- // separate messages (connection + request).
322+ // For TLS connections: approval happens per-request inside the
323+ // MITM handler where the HTTP method and path are known.
324+ // For non-TLS connections (SSH, plain TCP): the checker is
325+ // attached but the direct-relay path in handleWithDetection
326+ // calls CheckAndConsume once before relaying, providing a
327+ // connection-level approval prompt.
326328 allowed = true
327329 effectiveVerdict = policy .Allow
328330 reason = "ask deferred to per-request"
329- log .Printf ("[ASK->DEFER] %s:%d (approval deferred to per-request )" , dest , port )
331+ log .Printf ("[ASK->DEFER] %s:%d (approval deferred to handler )" , dest , port )
330332 }
331333 }
332334
@@ -1042,31 +1044,36 @@ func (s *Server) handleWithDetection(
10421044 return
10431045 }
10441046 case ProtoHTTP :
1045- // Plain HTTP detected by byte sniffing. go-mitmproxy only parses
1046- // TLS-intercepted traffic through CONNECT tunnels, so plain HTTP
1047- // goes through direct relay without phantom replacement.
1048- //
1049- // Known gap: credentials bound to plain HTTP on non-standard ports
1050- // will not be injected and phantom tokens will not be stripped.
1051- // This is acceptable because (1) credential bindings almost always
1052- // target HTTPS endpoints, and (2) the old goproxy-based path had
1053- // the same limitation. A future fix could add a lightweight HTTP
1054- // reverse proxy here or route plain HTTP through go-mitmproxy's
1055- // non-TLS code path if it gains support.
1047+ // Plain HTTP: no MITM handler. Check connection-level policy
1048+ // before relaying if a checker was deferred from Allow().
1049+ if checker != nil {
1050+ if v , _ := checker .CheckAndConsume (fqdn , port ); v != policy .Allow {
1051+ log .Printf ("[DETECT-DENY] %s:%d plain HTTP blocked by deferred policy" , fqdn , port )
1052+ return
1053+ }
1054+ }
10561055 relayDirect (peekConn , dialAddrs )
10571056 return
10581057 case ProtoSSH :
1058+ if checker != nil {
1059+ if v , _ := checker .CheckAndConsume (fqdn , port ); v != policy .Allow {
1060+ log .Printf ("[DETECT-DENY] %s:%d SSH blocked by deferred policy" , fqdn , port )
1061+ return
1062+ }
1063+ }
10591064 if s .sshJump != nil && binding != nil {
1060- // Pass nil for ready: SOCKS5 CONNECT already succeeded (see
1061- // comment above), so the handler's readiness signal is unused.
1062- // Both HandleConnection implementations guard with
1063- // "if ready != nil" before sending.
10641065 if err := s .sshJump .HandleConnection (peekConn , dialAddrs , hostAddr , * binding , nil ); err != nil {
10651066 log .Printf ("[SSH] handler error for %s: %v" , hostAddr , err )
10661067 }
10671068 return
10681069 }
10691070 case ProtoIMAP , ProtoSMTP :
1071+ if checker != nil {
1072+ if v , _ := checker .CheckAndConsume (fqdn , port ); v != policy .Allow {
1073+ log .Printf ("[DETECT-DENY] %s:%d %s blocked by deferred policy" , fqdn , port , proto )
1074+ return
1075+ }
1076+ }
10701077 if s .mailProxy != nil && binding != nil {
10711078 if err := s .mailProxy .HandleConnection (peekConn , dialAddrs , hostAddr , * binding , proto , nil ); err != nil {
10721079 log .Printf ("[MAIL] handler error for %s: %v" , hostAddr , err )
@@ -1082,10 +1089,23 @@ func (s *Server) handleWithDetection(
10821089 // can only route through the mail proxy and the upstream probe is wasted
10831090 // without a binding to inject.
10841091 if n == 0 && binding != nil && s .mailProxy != nil {
1092+ if checker != nil {
1093+ if v , _ := checker .CheckAndConsume (fqdn , port ); v != policy .Allow {
1094+ log .Printf ("[DETECT-DENY] %s:%d server-first blocked by deferred policy" , fqdn , port )
1095+ return
1096+ }
1097+ }
10851098 s .handleServerFirstDetection (peekConn , binding , hostAddr , dialAddrs )
10861099 return
10871100 }
10881101
1102+ // Generic fallback: direct relay. Check deferred policy first.
1103+ if checker != nil {
1104+ if v , _ := checker .CheckAndConsume (fqdn , port ); v != policy .Allow {
1105+ log .Printf ("[DETECT-DENY] %s:%d blocked by deferred policy" , fqdn , port )
1106+ return
1107+ }
1108+ }
10891109 relayDirect (peekConn , dialAddrs )
10901110}
10911111
0 commit comments