手机连上 WiFi 却没网,真凶是差了四年的系统时间
一台闲置很久的手机,状态栏一直显示「已连接,无法访问互联网」。我一开始怀疑路由器、怀疑 WiFi 模块,结果 ping 通、DNS 通、HTTP 也通——唯独 HTTPS 全部握手失败。顺着这条线挖下去,真凶和网络一点关系都没有。
现象,以及一个错误的直觉
手边有一台闲置挺久的手机(Android 12),想拿出来当备用机。连上家里的 WiFi 之后,状态栏一直提示「已连接,无法访问互联网」,浏览器打不开页面,App 也全部超时。
第一反应自然是 WiFi 的问题:重启路由器、忘记网络重连、切到 5GHz,全都没有用。但有一点很关键——同一个 WiFi 下其他设备上网都正常。这句话基本就把路由器整体和宽带上游排除掉了,问题要么在手机,要么在这台手机和路由器之间的那段链路上。
先把网络侧排干净
别急着怀疑手机,先在同网段的 Mac 上确认上游是好的:
# 网关与 DNS
IP: 192.168.31.225 默认网关: 192.168.31.1
nameserver[0] : 192.168.31.1
# 连通性
$ ping -c 2 8.8.8.8
2 packets transmitted, 2 packets received, 0.0% packet loss
# 域名解析
$ dscacheutil -q host -a name www.apple.com
ip_address: 113.215.226.138
全部正常。DNS 由路由器(192.168.31.1)代理,解析正常、出口正常,上游一点问题都没有。
接着我扫了一遍整个 /24 网段,想确认一件事:手机到底有没有拿到 IP?
$ seq 1 254 | xargs -P 64 -I{} ping -c 1 -W 1 192.168.31.{} >/dev/null 2>&1
$ arp -a | grep -v incomplete
扫出来二十来台设备,其中三台没有主机名。逻辑是这样的:既然手机显示「已连接」,那它必然已经拿到了 IP,也就必然在这张表里。 这一点本身就排除了一大类故障——DHCP 拿不到地址、二层关联失败,那些的表现是根本连不上,而不是「连上了却没网」。
所以范围缩小到:手机有了 IP、能上二层,但流量出不去。
用 adb 进系统里看
在设置界面里点来点去效率太低,直接进系统看。Android 有两条路:
- USB 调试:设置 → 关于手机 → 连点「版本号」7 次 → 开发者选项 → 打开「USB 调试」,插线后在手机上允许本机调试。
- 无线调试(Android 11+):开发者选项 → 无线调试 → 使用配对码配对。它走局域网 TCP,不需要互联网,同网段的电脑就能连——网络坏了但局域网通的情况下,这条路反而更顺。
连上之后先看基本状态:
$ adb shell getprop ro.product.model
$ adb shell getprop ro.build.version.release
12
$ adb shell cmd wifi status
Wifi is connected to "HOME-WIFI"
Supplicant state: COMPLETED, Wi-Fi standard: 6,
RSSI: -56, Link speed: 149Mbps, Frequency: 2457MHz
信号 -56dBm、链路速率 149Mbps、802.11ax——射频层健康得很,不是信号问题。
一个差点让我误判的细节
第一次看到路由表的时候,我差点直接下结论:
$ adb shell ip route
192.168.31.0/24 dev wlan0 proto kernel scope link src 192.168.31.162
只有一条链路路由,没有默认路由。这看起来太像「网关没配上」了——而网关缺失确实会导致上不了网。
但这是 Android 的正常现象。Android 用的是按网络分表的策略路由:每个 network 有自己的 routing table,靠 fwmark 决定走哪张表;ip route 不带参数只显示 main 表,默认路由在别的表里。如果在这里就下结论,就会去修一个根本不存在的问题。
验证方法很直接——ping 一个公网 IP:
$ adb shell ping -c 4 -W 2 8.8.8.8
4 packets transmitted, 4 received, 0% packet loss
$ adb shell ping -c 4 -W 2 223.5.5.5
4 packets transmitted, 4 received, 0% packet loss
通的,零丢包。默认路由存在且在生效,这条路排除。
真正的矛盾:HTTP 通,HTTPS 不通
到这里线索才开始收敛。把探测拆成几层分别测,结果非常有指向性:
| 探测层 | 结果 |
|---|---|
| ICMP(ping 公网 IP) | ✅ 零丢包 |
| DNS(解析域名) | ✅ 正常返回 IP |
| 纯 HTTP(80 端口) | ✅ HTTP/1.0 200 OK |
| HTTPS(443 端口) | ❌ 全部握手失败 |
手机自带的 curl 给出了确切原因:
$ adb shell curl -I https://www.baidu.com
curl: (60) SSL certificate problem: certificate is not yet valid
* TLSv1.2 (OUT), TLS alert, certificate expired (557)
certificate is not yet valid——证书「尚未生效」。这是 TLS 校验里对证书有效期起点的判断:服务器的证书生效时间,晚于手机认为的「现在」。
决定性证据
系统自己的网络验证日志把整件事说完了。Android 判断一个 WiFi「有没有互联网」,靠的是一组探针,同时跑 DNS、HTTP 和 HTTPS:
NetworkMonitor/100: PROBE_DNS www.googleapis.cn 47ms OK 202.101.48.43
NetworkMonitor/100: PROBE_HTTP http://one.lenovo.com/generate_204 time=23ms ret=204
NetworkMonitor/100: PROBE_HTTP http://www.googleapis.cn/generate_204 time=68ms ret=204
NetworkMonitor/100: PROBE_HTTPS https://one.lenovo.com/generate_204
Probe failed with exception javax.net.ssl.SSLHandshakeException:
Unacceptable certificate: CN=GeoTrust G2 TLS CN RSA4096 SHA256 2022 CA1
NetworkMonitor/100: PROBE_HTTPS https://www.googleapis.cn/generate_204
Probe failed with exception javax.net.ssl.SSLHandshakeException:
Unacceptable certificate: CN=WE2, O=Google Trust Services, C=US
NetworkMonitor/100: isCaptivePortal: isSuccessful()=false isPortal()=false
RedirectUrl=null isPartialConnectivity()=true Time=146ms
注意最后一行:isSuccessful()=false、isPortal()=false、isPartialConnectivity()=true。系统判定为「部分连通」——这正是状态栏那句「已连接,无法访问互联网」的出处。它不是随便报的,而是一次真实探测的结论:HTTP 那半边通了,HTTPS 那半边挂了。
真凶
$ adb shell date
Tue Jul 19 19:40:52 CST 2022 # 手机认为的现在
$ curl -sI https://www.baidu.com | grep -i '^date:'
Date: Wed, 30 Sep 2026 07:28:50 GMT # 服务器的真实时间
$ adb shell 'settings get global auto_time; getprop ro.build.date; cat /proc/uptime'
0 # 自动设置时间:关闭
Wed Jun 22 05:21:42 CDT 2022 # 固件编译日期
867.88 6132.27 # 开机才 14 分钟
手机的系统时间停在 2022-07-19,比真实时间慢了四年多。固件编译日期是 2022-06,开机只有 14 分钟——说明它上电后从 RTC 的默认值起步,而「自动设置时间」是关着的,于是它永远不会去联网校时,时间就永久停在四年前。
为什么时间错会导致「没网」
- 现在的 App 几乎全部走 HTTPS;
- TLS 握手会校验证书的有效期区间,当设备时间早于证书的
notBefore时,会判定「尚未生效」并拒绝连接; - 于是所有 App 全部超时,症状看起来和「网络不通」一模一样;
- 而 ICMP、DNS、纯 HTTP 都不涉及证书,所以它们一直是好的。
第 4 点是最坑的地方:越底层的检测越正常,越容易把人往「网络没通」的方向带。 ping 得通、DNS 能解析,这两个「网络正常」的经典证据在这里反而是误导。
修复与复验
$ adb shell settings put global auto_time 1
$ adb shell settings put global auto_time_zone 1
# 三秒内完成 NTP 同步
$ adb shell date
Wed Sep 30 15:29:35 CST 2026
改完之后逐项复验:
| 项目 | 修复前 | 修复后 |
|---|---|---|
https://www.baidu.com | ❌ 证书未生效 | ✅ HTTP 200,TLS 校验通过 |
https://www.google.cn | ❌ 证书未生效 | ✅ HTTP 200 |
partialConnectivity 标记 | 存在 | 0 次 |
| 该网络的 capability | PARTIAL_CONNECTIVITY | VALIDATED |
| NetworkMonitor 判定 | isPartialConnectivity()=true | isSuccessful()=true |
最关键的是网络能力标记从 PARTIAL_CONNECTIVITY 变成了 VALIDATED——这是系统认定「这个网络确实有互联网」的正式标记。系统不再报「无法访问互联网」,问题结束。
我自己踩的一个坑
为了催系统立刻重新验证,我顺手切了一次飞行模式。结果 WiFi 断开再回来后,框架把这个网络标记成了永久禁用:
NetworkSelectionStatus NETWORK_SELECTION_PERMANENTLY_DISABLED
mNetworkSelectionDisableReason NETWORK_SELECTION_DISABLED_NO_INTERNET_PERMANENT
# 日志里开始不断出现
Ignoring network selection disabled SSID: "HOME-WIFI"
这是之前「无互联网」判定留下的后遗症:系统早就把它记为「没有互联网的网络」,一旦被强制断开重连,它就正式禁用了自动加入,之后连信号最强的那个 BSSID 也不会再尝试。
正确的顺序是:先修时钟,然后等系统自然重新验证,不要用飞行模式去催它。 恢复的办法倒是很简单,在 WiFi 设置里点一下那个已保存的网络即可清除标记并连上,不需要重新输密码。
排查清单
以后再遇到「连上了但没网」,我会按这个顺序走:
- 先用同网段的另一台设备做对照——一步划分「手机侧」还是「网络侧」;
- 确认手机有没有拿到 IP——有 IP 就说明 DHCP 和二层没问题,可以直接跳过一大类怀疑;
- 搞一台能进系统的机器——
adb的效率远高于在设置界面里点; - 把探测分层测:ICMP / DNS / HTTP / HTTPS 分别打一遍,卡在哪一层,问题就在哪一层;
- 不要忽略系统时间——在 HTTPS 的世界里,它是「网络能不能用」的前提条件,而不是一个无关紧要的显示项。
这台手机现在正常了。回头看,花在这上面的时间大部分不是在修,而是在排除——真正的原因只有一行 date 的输出。