IPv6 代理不生效:雙棧網路下 IPv4 與 IPv6 出口不一致的原因與排查
網路同時有 IPv4 和 IPv6(雙棧)時,常見的“IPv6 代理不生效”其實是代理客戶端只接管了 IPv4:訪問支援 IPv6 的網站,系統優先走 IPv6 直連,流量根本沒進代理。確認方法是分別看 IPv4 和 IPv6 的出口地址是否一致;處理上要麼讓代理客戶端也接管 IPv6,要麼讓本機少用或不用 IPv6。下面按原因、確認、處理的順序說明。
為什麼雙棧網路下代理會“失效”
Happy Eyeballs:系統預設偏向 IPv6
現代作業系統和瀏覽器在連線一個域名時,會同時查詢 A(IPv4)和 AAAA(IPv6)記錄。按照 Happy Eyeballs 演算法(RFC 8305,前身是 RFC 6555),客戶端會優先嚐試 IPv6,只有在 IPv6 連線在很短時間內(RFC 8305 建議的預設值是 250 毫秒左右)沒有建立起來時,才轉去嘗試 IPv4。
所以只要本機有可用的 IPv6 地址和預設路由,目標站點又有 AAAA 記錄,連線大多會走 IPv6。國內不少家庭寬頻和行動網路已經預設下發 IPv6 地址,很多機器一直處在雙棧狀態,只是平時沒注意到。
哪些代理接管方式會漏掉 IPv6
代理是否受雙棧影響,取決於它在哪一層接管流量。
| 接管方式 | 雙棧下的表現 | 原因 |
|---|---|---|
| 系統代理 / 應用內 HTTP、SOCKS5 代理 | 通常不受影響 | 應用把域名直接交給代理,由代理端解析和連線,本機不發起 IPv6 連線 |
| 不讀系統代理的程式(部分命令列工具、SDK) | 完全繞過代理,IPv4 和 IPv6 都直連 | 程式根本沒走代理,與 IPv6 無關,但常被誤判為 IPv6 問題 |
| TUN / 虛擬網絡卡模式,只配置了 IPv4 路由 | IPv4 走代理,IPv6 直連 | 虛擬網絡卡只接管 0.0.0.0/0,IPv6 預設路由仍指向物理網絡卡 |
| 代理客戶端的 DNS 放行了 AAAA 記錄 | 部分站點走 IPv6 直連 | 解析得到真實 IPv6 地址,而規則或路由沒覆蓋 IPv6 |
| 閘道器 / 軟路由透明代理只處理 IPv4 | 區域網內所有裝置都可能出現 IPv6 直連 | 防火牆規則只寫了 iptables,沒有寫 ip6tables 或對應的 nftables 規則 |
最常見的現象:瀏覽器開啟某個支援 IPv6 的站點,顯示的地區與代理節點不一致;換一個只有 IPv4 的站點又正常;同一個頁面重新整理幾次,結果時好時壞。最後這種情況是 Happy Eyeballs 在起作用:IPv6 偶爾慢一點,連線就回落到 IPv4。
還有一種情況不算故障:同一臺機器訪問不同服務時,出口不同。對於需要穩定出口的場景(例如除錯 API 的地區路由、對比延遲),這會讓測量結果無法復現。
怎麼確認是 IPv6 繞過了代理
在瀏覽器裡:用 /ip 對照 IPv4、IPv6 與多出口
開啟 cdnping 的 IP 與環境檢測,重點看三塊:
- IPv4 / IPv6 檢測:頁面會分別給出 IPv4 和 IPv6 的出口情況。如果兩者的地理位置、ASN 明顯不同,例如 IPv4 顯示為代理節點所在地的機房網段,IPv6 顯示為本地運營商,基本可以確定是代理只接管了 IPv4。
- 多出口檢測:頁面會讀取 Claude、ChatGPT、Grok 等站點的 Cloudflare trace,看訪問不同站點時實際使用的出口。如果有的站點顯示代理出口,有的顯示本地出口,說明流量在不同路徑之間分叉了。
- 大陸分流檢測與 DNS 洩漏:分流規則和 DNS 配置也會造成出口不一致,可以順帶排除。DNS 洩漏的原理和判斷方法見 DNS 洩漏與 WebRTC 洩漏。
如果要把檢測結果發給同事或貼到 issue 裡,可以在 /ip 生成帶水印的結果圖;生成前先開啟隱藏 IP,圖裡就不會出現你的出口地址。頁面上的瀏覽器指紋在本地計算,不會上傳。
在終端裡:用 curl -4 / -6 對照出口
瀏覽器之外的程式(命令列工具、SDK、IDE 外掛)不一定和瀏覽器走同一條路,需要在終端裡單獨測一遍。Cloudflare 的 trace 介面會返回它看到的客戶端 IP,適合做對照:
# 強制 IPv4
curl -4 -s https://www.cloudflare.com/cdn-cgi/trace | grep -E '^(ip|loc|colo)='
# 強制 IPv6
curl -6 -s https://www.cloudflare.com/cdn-cgi/trace | grep -E '^(ip|loc|colo)='
# 不加引數,看系統預設選了哪一個
curl -s https://www.cloudflare.com/cdn-cgi/trace | grep -E '^(ip|loc|colo)='
結果怎麼讀:
| 現象 | 判斷 |
|---|---|
-6 報錯 “Couldn't connect” 或無路由 | 本機沒有可用 IPv6,問題不在這裡 |
-4 顯示代理出口,-6 顯示本地運營商地址 | 代理只接管了 IPv4,屬於本文討論的情況 |
-4、-6 都顯示本地地址 | 該程式沒有走代理,先檢查環境變數 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 或改用 TUN 模式 |
-4、-6 都顯示代理出口,且地區一致 | 雙棧都已接管,出口不一致要從分流規則或 DNS 查起 |
不加引數時的 ip= 是 IPv6 地址 | 預設連線走了 IPv6,與 Happy Eyeballs 的行為一致 |
再補兩條檢視本機狀態的命令:
# Linux:是否有全域性 IPv6 地址和 IPv6 預設路由
ip -6 addr show scope global
ip -6 route show default
# macOS:檢視各網絡卡的 IPv6 地址和 IPv6 路由表
ifconfig | grep inet6
netstat -rn -f inet6 | head -20
Windows 可以在 PowerShell 裡執行 Get-NetIPAddress -AddressFamily IPv6 和 Get-NetRoute -AddressFamily IPv6 -DestinationPrefix ::/0。
如果你在排查呼叫 AI 介面的程式,可以把上面的 trace 地址換成目標 API 的域名,用 curl -4 -o /dev/null -w '%{remote_ip} %{time_connect}\n' 和 -6 各跑一次,看實際連上的地址和建連耗時。AGI Plan 是 cdnping 的商業合作方,用 AGI Plan 的讀者可以用同樣的方法對 agiplan.dev 做對照,再到 /status/agiplan 看 cdnping 映象展示的 AGI Plan 可用率。
怎麼修:四種處理辦法與取捨
確認是代理只接管了 IPv4 之後,按下面的順序考慮。一般先改代理客戶端,影響範圍最小;改系統和閘道器的影響依次變大。
辦法一:在代理客戶端裡開啟 IPv6 支援
多數支援 TUN 模式的客戶端都有 IPv6 相關開關,名稱通常是“IPv6”“啟用 IPv6 路由”或在配置檔案中給虛擬網絡卡加一個 IPv6 地址段。開啟後,虛擬網絡卡會同時接管 ::/0,IPv6 流量也進入代理。
- 優點:本機網路保持完整,國內直連的站點仍然可以用 IPv6,不影響區域網內其他裝置。
- 前提:代理鏈路本身要能處理 IPv6 目標。如果遠端不支援 IPv6,常見做法是在客戶端 DNS 中只返回 A 記錄(不少客戶端有“禁用 AAAA”或“僅 IPv4 解析”選項),讓應用只發起 IPv4 連線。
- 注意:開啟後要重新跑一遍上面的
curl -6對照,確認 IPv6 出口確實變了。
辦法二:讓系統優先使用 IPv4
不關掉 IPv6,只調整地址選擇的優先順序。這樣遇到同時有 A 和 AAAA 記錄的域名時,系統會先試 IPv4。
# Linux(glibc):在 /etc/gai.conf 中加入一行
precedence ::ffff:0:0/96 100
Windows 可以透過修改字首策略實現,例如以管理員身份執行 netsh interface ipv6 set prefixpolicy ::ffff:0:0/96 60 4。macOS 沒有同樣簡便的系統級開關。
- 優點:改動小,IPv6 仍然可用。
- 侷限:隻影響走系統解析器的程式;瀏覽器內建的 DNS-over-HTTPS、自帶解析器的程式不一定遵守。只有 AAAA 記錄的站點仍會走 IPv6 直連。
辦法三:關閉系統 IPv6
效果最確定,副作用也最大。
# Linux 臨時關閉(重啟後恢復)
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
# macOS 關閉 Wi-Fi 網絡卡的 IPv6(服務名以 networksetup -listallnetworkservices 為準)
sudo networksetup -setv6off Wi-Fi
# 恢復
sudo networksetup -setv6automatic Wi-Fi
Windows 可以在網絡卡屬性中取消勾選“Internet 協議版本 6 (TCP/IPv6)”,或在 PowerShell 中使用 Disable-NetAdapterBinding -Name "乙太網" -ComponentID ms_tcpip6。
- 優點:不再有 IPv6 直連的可能,出口行為最好預測。
- 代價:失去 IPv6 帶來的直連路徑,部分國內服務或運營商網路在 IPv6 下的表現可能更好;某些系統元件依賴 IPv6 環回或鏈路本地地址,全域性關閉後可能出現難以定位的問題。微軟的官方文件也不建議完全禁用 IPv6,推薦用字首策略讓 IPv4 優先。
- 建議:先用臨時方式驗證效果,確認問題解決後再決定是否持久化。
辦法四:在閘道器或軟路由上處理
如果區域網裡的裝置都受影響,問題多半出在閘道器的透明代理只寫了 IPv4 規則。可以在閘道器上補齊 IPv6 的轉發規則,或者在閘道器上關閉 IPv6 下發(不發 RA、不開 DHCPv6)。後者等於對整個區域網執行“辦法三”,取捨相同。
四種辦法對照
| 辦法 | 影響範圍 | IPv6 是否保留 | 適合誰 |
|---|---|---|---|
| 客戶端開啟 IPv6 | 本機 | 保留 | 客戶端和遠端都支援 IPv6 |
| 系統優先 IPv4 | 本機,僅系統解析器 | 保留 | 想少改動、先緩解問題 |
| 關閉系統 IPv6 | 本機 | 不保留 | 需要出口完全可預測 |
| 閘道器處理 | 整個區域網 | 視做法而定 | 多臺裝置同時出問題 |
以上辦法只用於讓本機的網路行為和你的配置一致,方便排障和測量,不涉及繞過任何服務的地區限制。使用境外服務時請遵守其服務條款和當地法律法規。
改完之後逐項檢查
-
curl -4和curl -6的 trace 結果符合你的預期(一致,或-6已不可用) - 不加引數的
curl出口與瀏覽器一致 - /ip 頁面的 IPv4 / IPv6 卡片與多出口檢測沒有出現分叉
- DNS 洩漏檢測結果符合預期
- 在 首頁測速 跑一次,對比改動前後各 API 的“首次連線”耗時,確認沒有引入額外延遲
如果檢測之後出口已經一致,但某個 AI 服務仍然打不開,問題可能不在本地網路。可以去 /down 看對應服務有沒有其他使用者報告,或在 /status 檢視 cdnping 從 Cloudflare 邊緣每 5 分鐘一次的探測結果,再決定是繼續排查本地,還是等待服務恢復。分流相關的概念可以接著讀 分流(Split Tunneling)是什麼。