fix(discovery): admit Mihomo IPv6 fake-IP DNS answers behind a scheme-matched proxy - #3551
fix(discovery): admit Mihomo IPv6 fake-IP DNS answers behind a scheme-matched proxy#3551lidge-jun wants to merge 5 commits into
Conversation
…-matched proxy Under Clash Verge / Mihomo with Fake-IP on a dual-stack network, provider hostnames resolve into Mihomo's default fake-ip-range6 fdfe:dcba:9876::/48. That prefix is ULA, so resolvePublicAddresses classified every answer as a private-network address and model discovery failed behind the destination policy while ordinary chat traffic — which rides the proxy as a CONNECT — kept working (#3462). The IPv4 benchmark exception (198.18/15) could not cover this: a ULA answer carries no signal that it is synthetic, so it gets a narrower gate than benchmark space. - destination-policy: new allowMihomoIpv6FakeIp option, exact /48 match, DNS answers only; literal ULA URLs, adjacent prefixes, ordinary ULA and mixed private answers still reject. classifyIpv6 and config-time validation are unchanged, so the canonical-openai benchmark opt-in in provider-routes never admits the ULA. - proxy-env: effectiveProxyFor(url) returns the variable Bun fetch will honour for the URL scheme (HTTPS_PROXY / HTTP_PROXY); ALL_PROXY is not consulted. Proxy presence alone was not a routing guarantee. - provider-outbound: the flag is derived from that scheme-matched proxy plus !NO_PROXY, and when the flag admitted an answer the fetch is bound to the same proxy via Bun's explicit proxy option instead of environment inference. Every other branch is byte-identical. Docs: providers.md "Provider diagnostic outbound safety" (en + ko/ja/zh-cn/zh-tw/fr/ru/tr). Closes #3462
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
✅ READY
Hygiene✅ Deterministic PR hygiene checks passed. |
Ingwannu
left a comment
There was a problem hiding this comment.
The security direction is appropriately narrow on this stacked head: only DNS answers in the exact fdfe:dcba:9876::/48 prefix can use the exception; literal IP URLs, adjacent ULA ranges, mixed private answers, and config-time validation remain blocked. More importantly, the admission snapshots a scheme-matched proxy before DNS and the admitted request is explicitly bound to that same proxy, so it cannot fall back to a direct connection after accepting an otherwise-private answer. NO_PROXY remains a denial for this exception.
I am requesting changes only because this security-boundary PR currently targets codex/3467-google-location-error, and #3547 is still blocked for error-precedence fixes. The repository accepts integration PRs against dev (or scoped Go work against dev2-go), and a security approval must be for the final exact diff/base—not a temporary stack parent that may change.
After #3547 is corrected and lands, retarget/rebase this PR onto the then-current dev, remove inherited stack-only files from the final diff, clear the current hygiene/attribution state, and run exact-head CI plus a fresh security review. Do not merge it into the temporary parent branch.
… the benchmark one (#3462)
리뷰 · 우선순위 66 / 80이 PR는 Clash Verge / Mihomo에서 IPv6 Fake-IP를 켠 이중 스택 환경에서, 모델 디스커버리만 막히던 문제를 고칩니다. 지금 IPv4 쪽에는 이미 #1748로 프록시 쪽도 같이 손봤습니다. 관련 이슈 #3462는 아직 OPEN이고, 베이스는 #3547( 라인 157-164 ( 라인 라인 경로 경로 hygiene 메인테이너의 판단이 필요한 지점
너의 추천 이 댓글은 grok-bot이 작성했습니다 |
Owner-authorized admin squash of child-only #3551 carry onto corrected #3608. Scheme-matched proxy snapshot, explicit proxy transport binding, exact IPv6 prefix and NO_PROXY denial retained. Existing source security assessment and current static/typecheck evidence recorded. No local tests; final dev Linux CI is the batch gate.
Summary
Under Clash Verge / Mihomo with Fake-IP on a dual-stack IPv6 network, provider hostnames resolve into Mihomo's default
fake-ip-range6fdfe:dcba:9876::/48. That prefix is ULA, soresolvePublicAddressesclassified every answer as a private-network address and model discovery failed behind the destination policy ("Discovery failed" badge, static presets) while ordinary chat traffic — which rides the proxy as a CONNECT — kept working (#3462).The existing IPv4 benchmark exception (
198.18/15, #1748) could not cover this: a ULA answer carries no signal that it is synthetic, so it gets a narrower gate than benchmark space.src/lib/destination-policy.ts: newallowMihomoIpv6FakeIpoption onresolvePublicAddresses— exact /48 match, DNS answers only. Literal ULA URLs, adjacent prefixes, ordinary ULA, loopback/metadata/RFC1918, and fake-IP mixed with a real private answer still reject.classifyIpv6andproviderDestinationResolvedError(config-time validation) are unchanged, so the canonical-openai benchmark opt-in inprovider-routes.tsnever admits the ULA.src/lib/proxy-env.ts:effectiveProxyFor(url)returns the proxy variable Bun fetch will actually honour for the URL scheme (HTTPS_PROXYforhttps:,HTTP_PROXYforhttp:);ALL_PROXYis not consulted. Presence of some proxy variable was not a routing guarantee.src/lib/provider-outbound.ts: the flag is derived from that scheme-matched proxy plus!NO_PROXY, snapshotted before the DNS await; when the flag admitted an answer, the fetch is bound to the same proxy through Bun's explicitproxyoption (BunFetchRequestInit.proxy) rather than environment inference. Every other branch is byte-identical to today.providers.md§"Provider diagnostic outbound safety" in English plus ko/ja/zh-cn/zh-tw/fr/ru/tr.Related: the open pull request for the no-proxy TUN case on canonical endpoints does not recognise the IPv6 range; this change is independent of it and neither replaces the other.
Security review (MAINTAINERS.md): this touches the SSRF destination boundary. Reviewer focus: the admission gate is only ever true when a scheme-matched proxy exists and the host is not in
NO_PROXY, and the transport is then pinned to that proxy — a hostname resolving to a genuinely reachablefdfe:dcba:9876::/48host cannot be connected directly. No credential, auth-flow, or logging change.Stack (260905 bug triage, position 2 of 5; base is #3547's head — retarget to
devafter #3547 lands):devUnit:
devlog/_plan/260905_bug_triage_stack/(000, 005, 020).Verification
bun run typecheck— exit 0.bun test tests/routing/destination-policy-resolved.test.ts tests/providers/provider-outbound.test.ts— 71 pass / 0 fail. RED-before: with the three source files stashed, 27 new assertions fail; GREEN-after.proxyoption captured), lowercase, HTTPS+HTTP_PROXY-only (deny), ALL_PROXY-only (deny), NO_PROXY match (deny), no proxy (deny);effectiveProxyForunit matrix.bun run privacy:scan— passed.Closes #3462
Checklist
devafter it landsbun run typecheckpassesbun run privacy:scanpasses