Files
OmniRoute/docs/bdd/proxy-egress-isolation.feature
Diego Rodrigues de Sa e Souza 7219f2b38d feat(proxy): IPv6-only egress enforcement + close IP-leak paths (#3777)
Implements end-to-end proxy egress isolation with address-family enforcement and closes four real IP-leak paths surfaced by the proxy subsystem audit.

IPv6-only egress:
- Detect proxy family (IPv6/IPv4 literal, or per-account auto/ipv4/ipv6 directive) and pin the connect family (family:6/4 + autoSelectFamily:false) on both ProxyAgent (proxyTls) and a custom SOCKS connector that threads socket_options.family into SocksClient (fetch-socks can't), so Happy Eyeballs cannot pick IPv4 for an IPv6-only policy.
- De-bracket IPv6-literal proxy hosts (socksOptions.host + proxyHealth tcpCheck) — fixes ENOTFOUND on [::1]-style SOCKS proxies and health checks.
- Fail-closed when an IPv6-only hostname proxy has no AAAA (PROXY_FAMILY_UNAVAILABLE) instead of leaking over v4.
- DB migration 099 adds the proxy family column; family is preserved through the resolveProxyForConnection cascade and proxies/upstreamProxy modules.

Leak fixes:
- L1: web TLS clients (grok/claude/chatgpt/perplexity) now fail-closed on proxy-resolution error instead of silently going direct (was the highest-risk asymmetry).
- L2: safeResolveProxy fail-closed by default (PROXY_FAIL_OPEN opt-out).
- L3: API-key usage/quota fetch routed through the connection proxy context.
- L4: NVIDIA validation proxy bypass (#3226) documented.

Tests: 46 TDD unit tests + BDD egress-isolation matrix. typecheck:core + eslint clean.
Gemini 'critical' SOCKS finding verified as a false positive (socks accepts proxy.host; see PR thread).

Integrated into release/v3.8.24.
2026-06-13 14:18:09 -03:00

30 lines
1.3 KiB
Gherkin

Feature: Proxy egress isolation and IPv6-only enforcement
As an operator routing provider traffic through proxies
I want every request to egress only through the assigned proxy (and only over IPv6 when an IPv6 proxy is set)
So that the real host IP and IPv4 are never leaked
Scenario: IPv6-literal proxy de-brackets and connects over IPv6
Given a proxy configured as socks5://[2001:db8::1]:1080
When the dispatcher options are built
Then the SOCKS host is 2001:db8::1 and the resolved family is 6
Scenario: IPv6 hostname proxy forces IPv6-only egress
Given a proxy hostname with family=ipv6
When the dispatcher family is resolved
Then the connect family is pinned to 6
Scenario: IPv6-only egress is fail-closed when no AAAA exists
Given a proxy hostname with family=ipv6 and no AAAA record
When the family is asserted
Then it is refused and never egresses over IPv4
Scenario: Family directive contradicting a literal is rejected
Given a proxy 203.0.113.7 with family=ipv6
When the dispatcher family is resolved
Then it throws a configuration error
Scenario: Web TLS clients are fail-closed
Given a web TLS client whose proxy resolution throws
When the proxy URL is resolved
Then it throws instead of connecting directly