高鐵 Wi-Fi 連不上的兇手







你如果跟我一樣,在高鐵上連不上 Wi-Fi,我最近的解法或許能幫到你。
症狀是 Wi-Fi 圖示顯示連上 THSR_freeWIFI_ALL 了,登入頁面從來沒跳出來,瀏覽器開任何網站都在轉圈。同一台 MacBook Air 在咖啡廳、在家裡都正常,這半年在高鐵上一直是這樣。
主因最後跟高鐵沒關係,是我自己電腦上開著的 Tailscale(把自己的幾台機器連成一個私有網路的 VPN)。
這篇分享:怎麼修、公共 Wi-Fi 的登入頁到底怎麼運作,以及 VPN 為什麼會把它整個擋在外面。
先給能用的做法
上車之後照這個順序:
- 先把 Tailscale 整個關掉——選單列圖示 → Quit,不是按「中斷連線」
- 連
THSR_freeWIFI_ALL - 登入頁沒自動跳出來的話,開 Safari 打
http://neverssl.com(刻意維持純 http 的網站,瀏覽器不會把它轉去 https) - 完成登入,確認真的有網路
- 再把 Tailscale 開回來
第 3 步用 Safari,是因為 macOS 內建的登入視窗本來就是同一套 WebKit 引擎,登入頁比較不會出狀況;neverssl.com 本來就沒有 HSTS,其實用哪個瀏覽器打都連得到。
另一個原因:把那個網路的「私密 Wi-Fi 位址」關掉(系統設定 → Wi-Fi → 該網路的「詳細資訊…」→ 私密 Wi-Fi 位址:關閉,或至少改成「固定」)。高鐵是用 MAC 位址記住你登入過,設成「輪替」的話,位址每次重連都在變,會一直被丟回登入頁。
登入頁是怎麼跳出來的
公共 Wi-Fi 的登入頁(captive portal)運作方式,本質上是一次刻意安排的中間人攻擊。你連上去的時候:
- 閘道發給你一組 IP(這是 DHCP 在做的事),順便把它自己的 DNS 伺服器也塞給你
- 閘道把所有流量都擋掉,只放行 DNS 跟它自己的登入頁
- 常見的做法是它的 DNS 伺服器對每個查詢都說謊——不管你問哪個網域,答案都是登入頁的 IP(也有的閘道不碰 DNS,直接在 HTTP 層回一個 302,把你轉去登入頁)
- 你的瀏覽器連任何網站,拿到的都是登入頁
macOS 怎麼知道自己連到的是這種網路?它會送一個探測封包:GET http://captive.apple.com/hotspot-detect.html,預期回來的內容就是 Success 這個字。三種結果:
| 探測封包拿回什麼 | macOS 判定 | 你看到 |
|---|---|---|
Success |
真的有網路 | 沒事,直接能用 |
| 被導去一個登入頁 | 這是要登入的網路 | 登入視窗自己彈出來 |
| 逾時、沒有回應 | 這個網路壞了 | 什麼都沒有 |
我的狀況是第三列。登入頁就在那裡等著要騙我,而我的電腦從頭到尾沒去問它。
兇手是 Tailscale
關掉 Tailscale,其他什麼都沒改,馬上就連上了。
卡住的地方在 DNS。Tailscale 會把自己的解析器 100.100.100.100 設成系統的第一順位,排在 Wi-Fi 那端給的那台前面,scutil --dns 看得到 utun 那組排在 en0 前面。
路由表上也沒有任何要我走 VPN 的設定。netstat 列出的預設路由有兩條(這份輸出是我事後在手機熱點上重現同一個狀況抓的,高鐵當下的閘道 IP 不是這個,兩條 default 的結構一樣):
$ netstat -rn -f inet | grep default
default 172.20.10.1 UGScg en0
default link#26 UCSIg utun2
en0 是 Wi-Fi,utun2 是 Tailscale 建的虛擬網卡。而且這時候我沒有設 exit node,tailnet 裡也沒有任何一台機器在宣告子網路路由:
$ tailscale status --json | jq '.ExitNodeStatus'
null
$ tailscale status --json | jq '.Peer[]? | select((.PrimaryRoutes//[])|length>0)'
(空的)
沒有任何一項「我要求流量走 VPN」的設定,那條通道還是把 DNS 查詢接走了。接下來就是一個死結:
- macOS 要解析
captive.apple.com - 查詢被送去 Tailscale 的
100.100.100.100,而不是高鐵那端給的那台 - 那台解析器要等通道通了才連得到,而通道自己得先連上 Tailscale 的控制伺服器跟中繼節點——那同樣需要網路
captive.apple.com解不出來,探測封包逾時- macOS 把逾時解讀成「這個網路壞了」,於是連登入視窗都不會跳
登入頁一直在那裡,我的封包沒有一個到得了。
其他 VPN 也一樣
這件事跟 Tailscale 本身沒什麼關係。任何會在你電腦上建一條通道、而那條通道自己也需要網路才建得起來的 VPN,在飯店、機場、車站這種要先登入的 Wi-Fi 上,都會卡在同一個地方。順序永遠是:先關 VPN、登入、再開回來。
公共 Wi-Fi 得先把你攔下來,才願意給你網路;VPN 整天在做的事,就是讓誰都攔不到你。得先讓它攔你一次,你才出得去。
macOS 的 captive portal 探測網址:http://captive.apple.com/hotspot-detect.html