Skip to content

fix(transport): admit Mihomo IPv6 fake-IP under TUN transparency exception for canonical URLs - #3849

Closed
hualiny wants to merge 1 commit into
lidge-jun:devfrom
hualiny:fix/antigravity-quota-ipv6-fakeip
Closed

hualiny wants to merge 1 commit into
lidge-jun:devfrom
hualiny:fix/antigravity-quota-ipv6-fakeip

Conversation

@hualiny

@hualiny hualiny commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes an issue where Google Antigravity (and other canonical endpoints) fail to retrieve quotas or discover models when the client environment runs under Clash / Mihomo in TUN mode with IPv6 Fake-IP enabled (fake-ip-range6: fdfe:dcba:9876::/48) without an explicit HTTP(S)_PROXY environment variable.

Root Cause

In src/lib/provider-outbound.ts, resolveAddresses validates target IP addresses against private-network SSRF risks:

  • For IPv4 Fake-IP (198.18.0.0/15), TUN mode has an explicit transparency bypass via transparentFakeIpException(url, parsed, isCanonicalUrl, name):
    allowBenchmarkAddresses: (proxyConfigured && !noProxyMatches(parsed))
      || transparentFakeIpException(url, parsed, isCanonicalUrl, name),
  • However, for Mihomo IPv6 Fake-IP (fdfe:dcba:9876::/48, added in [Bug] Model discovery blocked by destination policy under Clash/Mihomo IPv6 fake-ip (fdfe:dcba:9876::/48) #3462), the admission was strictly gated behind effectiveProxy !== null:
    const allowMihomoIpv6FakeIp = effectiveProxy !== null && !noProxyMatches(parsed);

When running in TUN mode without HTTP(S)_PROXY (e.g. background services managed by launchd / systemd or transparent TUN proxies), DNS queries for canonical endpoints like daily-cloudcode-pa.googleapis.com return both IPv4 Fake-IP (198.18.x.x) and IPv6 Fake-IP (fdfe:dcba:9876::xx). Because allowMihomoIpv6FakeIp evaluated to false, the IPv6 ULA address was flagged as an unsafe private network address:

ProviderOutboundPolicyError: provider URL hostname daily-cloudcode-pa.googleapis.com resolves to private-network address (fdfe:dcba:9876::a9)

This aborted the request and caused Antigravity quota retrieval (retrieveUserQuotaSummary) to fail.

Fix

  1. Admit IPv6 Fake-IP under TUN transparency exception (src/lib/provider-outbound.ts):
    const isCanonicalUrl = dependencies.isCanonicalUrl ?? (() => false);
    const allowMihomoIpv6FakeIp = (effectiveProxy !== null && !noProxyMatches(parsed))
      || transparentFakeIpException(url, parsed, isCanonicalUrl, name);
  2. Safeguard proxy option:
    Ensure proxy passed to globalThis.fetch is only set when effectiveProxy is non-null.
  3. Tests:
    • Added unit test in tests/providers/provider-outbound.test.ts verifying that canonical URLs admit Mihomo IPv6 Fake-IP without proxy environment variables.
    • Updated quota test expectations in tests/providers/provider-quota.test.ts and tests/providers/provider-account-quota.test.ts (mihomo: true).

Verification

  • bun test tests/providers/provider-quota.test.ts tests/providers/provider-account-quota.test.ts tests/routing/destination-policy-resolved.test.ts tests/providers/command-code-fakeip-discovery.test.ts: 250 pass, 0 fail.
  • Verified in a live Mihomo TUN environment with IPv6 Fake-IP: fetchAntigravityUsageQuota successfully retrieves live Antigravity 5h and weekly quota without setting HTTPS_PROXY.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Summary by CodeRabbit

  • Bug Fixes
    • Improved connectivity for canonical service requests using TUN-mode transparent fake-IP handling.
    • IPv6 fake-IP admission is now enabled when applicable, including requests without proxy environment variables.
    • Requests can resolve both IPv6 and IPv4 addresses and use a reachable IPv4 connection when needed.
    • Prevented connection pinning when no effective proxy is configured.

@github-actions github-actions Bot added the bug Something isn't working label Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@coderabbitai

coderabbitai Bot commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Team

Run ID: ec8ef9e8-b33f-436d-ad98-42ac6abc392f

📥 Commits

Reviewing files that changed from the base of the PR and between 0d8b0cd and 3830862.

📒 Files selected for processing (4)
  • src/lib/provider-outbound.ts
  • tests/providers/provider-account-quota.test.ts
  • tests/providers/provider-outbound.test.ts
  • tests/providers/provider-quota.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Changes

The outbound provider now enables Mihomo IPv6 fake-IP handling for canonical TUN transparent fake-IP exceptions. Proxy pinning still requires an effective proxy. Tests cover canonical OpenCode traffic and Google Antigravity quota requests.

Mihomo IPv6 fake-IP admission

Layer / File(s) Summary
Admission logic and proxy pinning
src/lib/provider-outbound.ts
allowMihomoIpv6FakeIp now includes the canonical TUN transparency exception. Proxy pinning requires both Mihomo admission and an effective proxy.
Regression and expectation coverage
tests/providers/provider-outbound.test.ts, tests/providers/provider-account-quota.test.ts, tests/providers/provider-quota.test.ts
Tests cover proxyless canonical opencode-go requests and expect mihomo: true for canonical Google Antigravity quota resolutions.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 38308

Canonical provider requests in Mihomo TUN mode can now use IPv6 Fake-IP addresses without requiring a proxy, while requests without a configured proxy are not passed one. Covered regression tests indicate the change is ready to merge.

Sequence Diagram(s)

sequenceDiagram
  participant Request
  participant ProviderOutbound
  participant AddressResolver
  participant PinnedRequest
  Request->>ProviderOutbound: Send canonical request
  ProviderOutbound->>ProviderOutbound: Evaluate TUN transparent fake-IP exception
  ProviderOutbound->>AddressResolver: Resolve with mihomo enabled
  AddressResolver-->>ProviderOutbound: Return IPv6 and IPv4 addresses
  ProviderOutbound->>PinnedRequest: Use IPv4 address and effective proxy when present
  PinnedRequest-->>Request: Return HTTP response
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: allowing Mihomo IPv6 fake-IP admission for canonical URLs under the TUN transparency exception.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • review readiness checklist open (0/4 boxes ticked).

What to do

  • Tick all four boxes in the PR description once you're done (currently 0/4).

Review readiness checklist

  • ⬜ All CI tests are green on my local testing.
  • ⬜ I pushed my PR to the latest dev commit.
  • ⬜ I resolved all correct Codex and CodeRabbit findings.
  • ⬜ My PR is ready for review.

0/4 boxes ticked.

This PR stays in draft until every box above is ticked.

@github-actions
github-actions Bot marked this pull request as draft September 7, 2026 03:17
@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 64 / 80

이 PR은 Clash / Mihomo를 TUN 모드 + IPv6 Fake-IP(fdfe:dcba:9876::/48)로 쓰면서 HTTP(S)_PROXY 환경 변수는 없는 환경에서, Google Antigravity 할당량·모델 조회 같은 레지스트리 고정(canonical) URL이 막히던 문제를 고칩니다. 지금 dev HEAD(0d8b0cd1e, 2.46.0 open, axis1 마감 직후)의 전송 계층은 이미 src/lib/provider-outbound.ts에서 IPv4 Fake-IP(198.18.0.0/15)에 대해 transparentFakeIpException으로 TUN 투명 예외를 열어 둡니다. 반면 Mihomo IPv6 Fake-IP는 #3462 이후 effectiveProxy !== null && !noProxyMatches(parsed)만 통과시켜서, TUN만 켜고 프록시 환경 변수가 없는 launchd/systemd 백그라운드에서는 IPv6 ULA 답이 SSRF 거부로 떨어집니다. 실제 증상은 daily-cloudcode-pa.googleapis.com이 198.18.x.x와 fdfe:dcba:9876::…를 같이 돌려줄 때 IPv6 쪽 거부로 요청 전체가 끊기고, Antigravity retrieveUserQuotaSummary가 실패하는 형태입니다.

고치는 방식은 IPv4 TUN 예외와 같은 증명을 IPv6에도 붙이는 것입니다. allowMihomoIpv6FakeIp를 (프록시 바인딩) 또는 transparentFakeIpException(url, parsed, isCanonicalUrl, name)으로 OR 하고, globalThis.fetch에 넘기는 proxy는 effectiveProxy가 있을 때만 넣도록 바꿉니다. 예외는 여전히 isCanonicalUrl이 최종 요청 URL을 레지스트리 고정 목적지로 증명할 때만 열립니다. Antigravity 쪽은 이미 src/providers/quota.ts의 isCanonicalAntigravityQuotaUrl이 summary/models 두 URL만 허용하므로, 이 PR이 새로 넓히는 구멍은 “이름만 맞는 임의 baseUrl”이 아니라 이미 IPv4 TUN 예외가 쓰던 그 좁은 canonical 게이트입니다. 단위 테스트도 tests/providers/provider-outbound.test.ts에 “프록시 env 없이 canonical이면 allowMihomoIpv6FakeIp: true” 케이스를 추가했고, quota/account-quota 쪽 기대값을 mihomo: true로 맞춰 현재 canonical 경로가 실제로 그 플래그를 켠다는 사실을 반영합니다.

현재 dev 방향(axis1 quota/CLI/recovery 마감, types/config 대분할 대기)과 겹치지 않는 독립 전송/SSRF 정책 버그픽스라서 close-don't-rebase 대상이 아닙니다. 범위도 provider-outbound.ts + 테스트 네 파일이라 머지 비용이 낮고, 사용자 체감(Antigravity 할당량 TUN 실패)은 분명합니다. 다만 #3462가 IPv6 Fake-IP를 IPv4보다 엄하게 둔 이유(ULA는 “합성 Fake-IP” 표시가 없어 진짜 private 호스트와 구분이 안 됨)를 의도적으로 TUN+canonical 쪽으로 한 칸 완화하는 변경이므로, 메인테이너가 그 완화에 동의하는지가 점수와 머지 타이밍의 핵심입니다.

라인 146–148 (PR diff, src/lib/provider-outbound.ts) - allowMihomoIpv6FakeIp에 transparentFakeIpException OR를 붙인 핵심 변경. IPv4 allowBenchmarkAddresses와 대칭이라 읽기 좋고, isCanonicalUrl을 위로 올린 것도 맞음. 다만 이 한 줄이 #3462의 “스킴 매칭 프록시 필수” 문장을 사실상 폐기하는 정책 변경이라, 주석만 고친 게 아니라 보안 경계 완화임을 리뷰에서 명시해야 함.

라인 190–194 (PR diff, src/lib/provider-outbound.ts) - proxy = (allowMihomoIpv6FakeIp && effectiveProxy) ? effectiveProxy : undefined 는 TUN-only 경로에서 null/undefined proxy를 fetch에 억지로 넣지 않게 막는 올바른 가드. 프록시가 없을 때는 아래 pin-connect(pickPinnedAddress, IPv4 우선)로 가서 TUN이 Fake-IP를 가로채는 기존 IPv4 TUN 경로와 같아짐.

경로 src/lib/destination-policy.ts (isMihomoIpv6FakeIpAnswer / resolvePublicAddresses 주석) - 아직 “scheme-matched proxy에 바인딩한 뒤에만 allowMihomoIpv6FakeIp”라고 적혀 있음. 코드는 바뀌는데 정책 문서 주석이 안 바뀌면 다음 기여자가 다시 proxy-only로 되돌리거나, 반대로 더 넓게 열 위험이 있음. 같은 PR에서 주석을 TUN+canonical OR와 맞추는 편이 좋음.

경로 src/lib/provider-outbound.ts (transparentFakeIpException 블록 주석, 약 40–56행) - 설명 문장이 IPv4 198.18.0.0/15만 말하고 Mihomo IPv6 /48은 안 언급함. 이번 변경으로 이 함수가 IPv6 예외의 OR 항이 되었으니, 주석에 fdfe:dcba:9876::/48도 같이 적어야 이후 독자가 “IPv4 전용 예외”로 오해하지 않음.

경로 tests/providers/provider-outbound.test.ts (기존 #3462 describe 제목 + “without any proxy…” 테스트) - 새 canonical 테스트는 잘 추가됐지만, describe/제목은 여전히 “scheme-matched proxy에 게이트” 톤이라 스위트 서사가 어긋남. non-canonical + no-proxy는 계속 false인 게 맞고, 제목만 “proxy 또는 TUN canonical”로 고치면 됨.

경로 tests/providers/provider-quota.test.ts / provider-account-quota.test.ts (mihomo: true 기대값) - Antigravity canonical URL이면 이제 플래그가 켜지는 게 맞음. 다만 이 기대값 변경만으로는 “IPv6 Fake-IP 답이 실제로 들어와도 할당량 fetch가 성공한다”는 end-to-end를 증명하진 않음(리졸버가 돌려주는 address 목록 시나리오는 outbound 단위 테스트 쪽에 더 가깝음). 지금 추가된 outbound 테스트가 그 구멍을 메우므로 머지 블로커는 아님.

메인테이너의 판단이 필요한 지점

  • #3462가 ULA Fake-IP를 proxy-bound로 묶은 이유를, canonical + TUN 투명 예외로 한 칸 푸는 게 이번 릴리스에서 받아들일 완화인지
  • destination-policy.ts / transparentFakeIpException 주석을 같은 PR에서 맞출지, follow-up으로 둘지
  • 이 증상을 추적할 이슈 번호가 없는데, Antigravity TUN 사용자용 이슈를 열고 closes로 묶을지(선택)

너의 추천
머지 후보. dev에 바로 올려도 방향 충돌 없음. 먼저 destination-policy.ts와 transparentFakeIpException 주석을 TUN+canonical OR에 맞게 한 줄씩 고치고, 메인테이너가 “#3462 완화 OK”만 짧게 ACK하면 머지. 테스트 제목 정리는 있으면 좋고 없어도 머지를 막을 정도는 아님.

이 댓글은 grok-bot이 작성했습니다

@lidge-jun

Copy link
Copy Markdown
Owner

Landed on dev via #3872 (merge ddee5e8b4; chain-top Cross-platform CI run 34111578200 — Linux/macOS/gates/keyring/npm/docker green; Windows matrix runs once on the final release-train head by maintainer policy). carried (cherry-pick -x) plus IPv6-only path and canonical NO_PROXY negative coverage; SSRF-boundary review PASS on #3872. Your authorship is preserved with a Co-authored-by: hualiny trailer on the landed commit. Closing this PR as superseded — thank you @hualiny!

@lidge-jun lidge-jun closed this Sep 7, 2026
agentHits pushed a commit to agentHits/opencodex that referenced this pull request Sep 17, 2026
…N (carry lidge-jun#3849) [skip ci]

fix(transport): admit canonical Mihomo IPv6 with validated pinning
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants