回宿舍连不上校园网,折腾一晚上,凶手是我电脑里的 Docker
返校第一晚,校园网先给我来了个下马威
lazypool:以后电脑连不上网的时候,先想想自己是不是养了一堆 docker 网桥。
事情是这样的
九月初返校,搬进宿舍,把桌子擦干净、被子铺好,然后高高兴兴把电脑支起来——想先登个校园网,把欠下的活干了。
结果连上宿舍的 Wi-Fi,信号满格,IP 也拿到了,就是死活弹不出认证页面。浏览器刷了几遍,空白;点开“网络详情”,看起来一切正常。
我第一反应是:网卡又抽风了?断开重连,不行;换了个节点,还是不行。折腾了十分钟,我开始有点烦躁。刚返校第一天,连个网都上不了,这也太倒霉了。
抓狂的开始
这时候我做了一件当时觉得挺自然的事:把问题丢给 AI,让它陪着我一起查。
于是我开始了一项传统艺能——按网上排障教程的顺序挨个试:
- 代理没关?→ 我常年挂着代理软件,先把环境变量清一遍。
- DNS 被改坏了?→ 设回自动获取。
- 随机 MAC 的锅?→改成 permanent。
- 系统时间不对?→查了一下,没问题。
全都没用。(T_T)
一个说不通的怪现象
真正让我冷静下来的是两个矛盾的现象:
我 curl http://1.1.1.1,居然有响应,而且返回的是一段认证跳转脚本:
1 | |
这说明网络其实是通的:校园网网关把我的请求劫持了,正催着我去认证。
但顺着这个地址去访问认证服务器 portal.whu.edu.cn,却怎么都连不上。ping 一下,报错长这样:
1 | |
公网能通,内网不通。这就怪了……要说是断网吧,1.1.1.1 明明有响应;要说网好吧,认证服务器又进不去。
卡在这个矛盾上,我和 AI 来回拉扯了很久,一度还想从路由、网关这些方向去加静态路由试试。
转机就藏在这行报错里
后来不知第几轮,我盯着报错看了半天,忽然觉得不对:
From LazyPool (172.19.0.1) 里的 LazyPool,是我自己电脑的主机名。
也就是说,这条“目标不可达”根本不是什么路由器发给我的,是我自己的内核在告诉我:它觉得目标 172.19.1.9 就在本机旁边,想直接投过去,结果投了个寂寞,只能自己给自己回一个不可达。
我把这个发现跟 AI 说了,它一开始还坚持认为 172.19.0.1 是网关、是路由器那边的地址,建议我去改路由。但我看了眼自己的 ip addr,真相一下就清楚了:
1 | |
那会儿我电脑里养着一堆 Docker 的虚拟网桥 br-xxxx,其中一个 br-58cf3097d2e1 占着 172.19.0.1/16 这个网段。而校园网认证服务器解析出来的地址,恰恰是 172.19.1.9——正好落在同一个网段里。
事情一下就串起来了:
- Linux 里,直连网段的路由永远比默认路由优先。所以发往
172.19.1.9的包,内核一看“这网段我本地就有啊”,就直接交给了那张 docker 网桥,压根没走wlan0的默认网关。 - 可那张网桥是空的(
NO-CARRIER),没接任何容器,包根本发不出去,于是内核只能自己报“不可达”。 - 而
1.1.1.1是公网地址,不在任何本地网段里,老老实实走wlan0出去,所以反而能通,还能收到认证跳转。
说白了:我自己电脑上的 docker 网桥,抢了校园网认证服务器的网段。搞了半天,锅在我自己这儿,跟学校网络中心一点关系没有。
解决
既然知道是谁捣乱了,处理起来就很简单——让内核把去 172.19 的包,重新交回给 wlan0 走默认路由就行:
1 | |
执行完再 ping portal.whu.edu.cn,通了。浏览器打开认证页,登录一气呵成。
不过停 docker 只是临时办法,下次一启动它,网桥又会长回来。Docker 默认会从 172.17.0.0/16 一路挑到 172.31.0.0/16 的空闲网段,而校园网、企业内网最爱用的恰恰就是 10.x 和 172.16~172.31,两边迟早要撞上。所以干脆给默认网桥换个不相干的网段,一劳永逸:
1 | |
顺带说一句,如果是 docker-compose 之类自定义网络占的网段,改 daemon.json 没用,得去 docker-compose.yml 里改 subnet,再把旧网络 docker network rm 掉。这次中招的是默认网桥,改 bip 就够了。
事后想想,几点教训
这次前前后后折腾了挺久,绝大部分时间浪费在乱猜上。躺在床上复盘,有几条想记下来,免得下次再踩。
1. 网络“连不上”,先分清是“出不去”还是“没往那儿送”
我一开始默认是网坏了,一直在往“校园网服务端有问题”的方向想。其实那次链路、IP、DNS 全都是好的,问题出在我自己电脑的路由决定上——内核把包发给了一张发不出去的空网桥。以后遇到“明明连上了却访问不了某个地址”,先问一句:这个包到底被送到哪去了?
2. 早该问内核的一句话:ip route get
“发往某个 IP 的包走哪张网卡”,这种事不用猜,直接问内核就能知道:
1 | |
如果我在瞎试那些教程之前先跑这一句,看到 dev br-58cf... 的那一刻问题就定位了,能省下好几个小时。“能访问的地址访问不了”的时候,第一反应应该是 ip route get,而不是先怀疑各种配置。
3. 报错里的“是谁在说话”,往往比报错本身更关键
同样的 Destination Host Unreachable,如果来源是路由器,那是网络/上游的问题;如果来源是你自己的主机名,那说明决策发生在本机,答案大概率在你的路由表里。我看到 LazyPool 的时候其实已经离真相很近了,可惜绕了一大圈才注意到它。
4. 跟 AI 排障,想省时间省 token,得这样喂
这次排查基本是跟 AI 一起磨过来的,回头翻记录,浪费主要在这么几处,也都是以后能避免的:
- 贴文本,别贴截图。截图我看它还经常转录出错,来回好几轮都对不上,纯纯浪费。命令输出能复制就复制。
- 一次只丢一份“最有用”的证据。比如把
ip addr的输出直接给它,比把我怀疑过的所有方向都讲一遍有用得多——讲得越多,它越容易照着清单给你把整套排查教程重写一遍。 - 它的回答当参考,别当圣旨。像
172.19.0.1它坚持说是网关,我用ip addr的事实就把它纠正了。模型负责出主意,谁对谁错得靠证据说话。 - 让它“增量回答”。聊长了它老把已经确认的结论完整复述一遍,浪费 token。一开始就让它只回“下一步该跑哪条命令 / 哪一处和上一步不同”,会快很多。
最后留个速查,下次连校园网再出幺蛾子,照着跑一遍就完事:
1 | |
折腾了这么一晚上,最大的感受其实是:电脑连不上网的时候,先别急着怪网络、怪学校,先看看是不是自己电脑里那些平时看不见的虚拟网卡在捣乱。它们平时安安静静待着,关键时刻真能给你上一课。