feat(proxy): per-request policy, go-mitmproxy migration, QUIC Ask#27
Merged
nnemirovsky merged 19 commits intomainfrom Apr 12, 2026
Merged
feat(proxy): per-request policy, go-mitmproxy migration, QUIC Ask#27nnemirovsky merged 19 commits intomainfrom
nnemirovsky merged 19 commits intomainfrom
Conversation
…al channels Integrate RequestPolicyChecker into the SOCKS5 handler and QUIC/HTTP3 path. Add method/path context to approval requests so Telegram shows which HTTP request triggered the Ask verdict. Include fixes for edge cases in broker-less and default-verdict scenarios.
Replace the goproxy-based HTTPS MITM with go-mitmproxy and a unified SluiceAddon that handles per-request policy checks, credential injection (static phantom swap and binding headers), and OAuth response interception in a single addon lifecycle. Add CONNECT auth secret to prevent direct bypass of the MITM listener.
…tests Two full-pipeline integration tests proving go-mitmproxy fires per-request addon hooks for each HTTP/2 stream on a single TCP connection: - TestHTTP2PerRequestPolicyAndInjection: two HTTP/2 requests through SOCKS5 -> go-mitmproxy MITM -> TLS HTTP/2 backend. Verifies the broker is called for each stream (connection-level + per-request) and credential injection works on both streams independently. - TestHTTP2PerRequestDenySecondStream: sequencing broker allows the connection and first stream but denies the second. Verifies per-stream granularity: first request 200, second request 403, backend sees exactly one request. These tests are the key validation that the goproxy replacement works for the gRPC use case (HTTP/2 multiplexed streams with per-request policy).
Add EvaluateQUICDetailed to the policy engine for QUIC-specific Ask verdict support. Wire the per-request checker through buildHandler so HTTP/3 requests on keep-alive QUIC sessions are individually approved. Extract resolveQUICPolicy helper in server.go for clarity.
Add webhook-based verdict server and sluiceWithWebhook test helper. Add e2e tests verifying that Allow Once approves exactly one HTTP request per SOCKS5 connection and that subsequent requests are blocked.
Update CLAUDE.md and README with per-request policy details and go-mitmproxy migration notes. Move completed plan files to docs/plans/completed/.
Defer ask approval from SOCKS5 CONNECT to per-request HTTP handler so only one Telegram message appears per request (not two). The message combines destination and request info: OpenClaw wants to connect to: HTTPS httpbin.org:443 GET https://httpbin.org/ip Allow this request? Also disable Telegram web page preview on approval messages to prevent link-preview artifacts.
Non-MITM protocols (SSH, SMTP, plain HTTP, generic TCP) now check the deferred per-request policy before relaying. Without this, connections to non-TLS ports on ask destinations would pass through without any approval.
…rotocols SSH, plain TCP, and other non-MITM connections that go through the direct dial path now check the deferred per-request policy before connecting upstream. Without this, connections to ask destinations on non-TLS ports (e.g. SSH port 22) bypassed approval entirely.
Approval messages now display the negotiated HTTP version alongside the request method, e.g. "GET https://example.com/api (HTTP/2)". Helps distinguish HTTP/1.1 from HTTP/2 traffic in approval prompts.
…provals Use go-mitmproxy fork with WebSocket Requestheaders fix.
…ent port overwrite All CheckAndConsume calls in byte-detection and direct-connect paths now pass WithProtocol so protocol-scoped rules (ssh, http, imap, smtp) are matched correctly. Prevent TlsEstablishedServer from overwriting a port already captured by ServerConnected with a recovered/defaulted value.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Changes
internal/policy/engine.go: EvaluateDetailed, EvaluateQUICDetailed with MatchSourceinternal/proxy/request_policy.go: RequestPolicyChecker with seed credits, persist callback, protocol-aware evaluationinternal/proxy/addon.go: SluiceAddon (go-mitmproxy Addon) with per-request policy, credential injection, OAuth response interception, streaming phantom swapinternal/proxy/ca_adapter.go: Bridge sluice CA to go-mitmproxy cert.CA interfaceinternal/proxy/server.go: SOCKS5 routing to go-mitmproxy, pending checker handoff, QUIC Ask wiringinternal/proxy/quic.go: Per-request checker in buildHandlere2e/per_request_test.go: 4 e2e tests with webhook-driven approval flowinternal/proxy/inject.go(goproxy-based, replaced by addon.go)github.com/elazarl/goproxydependencyTest plan
go test ./... -timeout 120s(all 12 packages)go test -tags=e2e ./e2e/ -v -count=1 -timeout=300s(41 pass, 2 skip Apple Container)