微信说「不在同一网络」,其实是被防火墙丢了包
导入聊天记录时提示两台设备不在同一网络。ping 是通的,微信也确实监听了 8015。直到从手机浏览器去访问那个端口拿到 ErrorTimeOut,方向才定下来。
手机和电脑连同一个热点,用微信导入聊天记录,电脑上弹出:
暂无法导入,请保持手机和电脑在同一网络
两台设备确实在同一个网段里。USB 网络共享试过,Wi-Fi 热点也试过,都能正常上网, 但导入就是失败。
先决条件
| 需要 | 说明 |
|---|---|
| 微信 Linux 原生版 | 3.x 与 Wine 版的导入机制不同,本文针对 4.x |
| 一台 Linux 电脑 + 一台手机 | 用手机热点或 USB 网络共享组成局域网 |
三个自查命令:
```baship -br addr # 看手机那侧的接口名和网段 sudo ufw status verbose # 防火墙是不是 UFW 在管 ss -tlnp | grep 8015 # 导入窗口打开时,这个端口在不在监听
```
这套排查在什么环境上验证过
```plaintextCachyOS (Arch) | KDE Plasma 6 | Wayland 微信 Linux 原生版 4.1.8 | UFW
```
| 项 | 是否通用 | 说明 |
|---|---|---|
| 8015 这个端口 | ⚠️ 是当时观测到的 | 微信版本变了可能变,用 `ss -tlnp` 自己确认 |
UFW 的默认 `DROP` 策略 |
⚠️ 取决于你的配置 | `ufw status verbose` 看自己的 |
`strace` 的跟踪方式 |
✅ 通用 | 任何 Linux 都能用 |
| 手机热点的网段 | ❌ 每次都不同 | 由手机 DHCP 分配,必须现场查 |
| 接口名 | ❌ 会变 | Wi-Fi 是 `wlan0`,USB 共享是 `enp6s0f4u2u2` 这类名字 |
先说那个错误提示
「请保持手机和电脑在同一网络」是一句泛化提示。微信在这条路径上失败时都会这么说, 不管真实原因是不同网段、防火墙丢包、还是别的。
所以它只能证明「这条链路没通」,不能证明两台设备不在同一子网。 顺着字面意思去查网络拓扑,会走偏。
第一步:把「看着可疑但其实正常」的先排掉
一开始怀疑的是地址段:手机热点分给电脑的地址是 `10.112.4.254`,看着不像家里的
`192.168.x.x`,当时以为是 KDE 建了什么虚拟网卡,或者被 VPN 接管了。
```baship -br addr # 看接口和地址 nmcli device # 看 NetworkManager 怎么认这个接口
```
实际拿到的:
```textWi-Fi 热点: wlan0 10.112.4.254/24 手机网关 10.112.4.49 USB 共享: enp6s0f4u2u2 10.146.37.73/24 手机网关 10.146.37.96
```
`10.0.0.0/8` 是标准 IPv4 私有地址段,和 `192.168.0.0/16` 是一回事。
地址由手机 DHCP 分配,不是异常拓扑。
第二步:两个直接验证,都不用停任何服务
验证一:微信到底有没有在监听
```bash# 先找到微信主进程的 pid,再跟踪它的网络调用 sudo strace -ff -tt -e trace=network -p <微信pid>
```
打开导入窗口,抓到的是:
```textsocket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 305 bind(305, {sa_family=AF_INET, sin_port=htons(8015), sin_addr=inet_addr("0.0.0.0")}, 16) = 0 listen(305, 8) = 0
```
`bind` 和 `listen` 都返回 0,说明三件事:
- 导入模块已经进入网络阶段
- 它在所有 IPv4 接口上监听 8015
- 不存在「没权限绑端口」的问题
这一步把排查范围从「应用没起来」缩到了「入站路径不通」。用 `ss` 也能看到同样的结论,
但 `strace` 能证明它是微信自己建的监听,而不是别的进程占了端口。
验证二:从对端访问这个端口(决定性的一步)
保持导入窗口开着,用手机浏览器访问电脑的那个端口:
```plaintexthttp://<电脑的局域网IP>:8015
```
结果是:
```plaintextErrorTimeOut
```
超时,不是拒绝。
这两种失败指向的方向不一样:
| 结果 | 含义 |
|---|---|
| 连接被拒绝 | 端口没在监听,或者应用拒绝了 |
| 超时 | 报文被丢掉了,`DROP` 的典型表现 |
顺带一个反面对照:这时候电脑是能 ping 通手机的。
```textPING 10.112.4.49 3 packets transmitted, 3 received, 0% packet loss
```
ping 通只证明 ICMP 和基础路由可用,不代表特定 TCP 端口的入站被放行。 这两件事经常被当成一件。
第三步:查防火墙
```bashsudo ufw status verbose
```
```textStatus: active Default: deny (incoming), allow (outgoing), disabled (routed)
```
再看配置:
```text/etc/default/ufw: DEFAULT_INPUT_POLICY="DROP"
```
默认入站是 DROP。 手机发往 8015 的包到了电脑就被丢了,应用层根本看不到, 所以微信只能报一句「不在同一网络」。
⚠️ 一个容易漏的地方
```textufw.service: active (exited) firewalld.service: inactive nftables.service: inactive
```
UFW 的服务状态是 `active (exited)` —— 它是一次性服务,开机时把 Netfilter 规则
写进内核就退出了,之后一直显示 `exited`。
只看 `firewalld` 或 `nftables.service` 的状态,会以为这台机器没有防火墙在管事。
它们不活动不等于没有规则,规则已经在内核里了。
修复
加一条最小放行规则:
```bashsudo ufw allow in on wlan0 from 10.112.4.0/24 to any port 8015 proto tcp
```
这条规则限定得很死,只放行:
| 限定项 | 值 |
|---|---|
| 入站接口 | `wlan0` |
| 来源网段 | 手机热点的 `/24` |
| 协议 | TCP |
| 目标端口 | 8015 |
放行后重启微信,重新进导入页面,导入成功。
USB 共享时要换接口名和网段
USB 共享走的是另一个接口,名字和网段都不一样,所以规则也得重写一条。 先查,再写:
```bashnmcli device ip -br addr
```
比如这次 USB 共享是 `enp6s0f4u2u2`、网段 `10.146.37.0/24`:
```bashsudo ufw allow in on enp6s0f4u2u2 from 10.146.37.0/24 to any port 8015 proto tcp
```
不要图省事写成 `sudo ufw allow 8015/tcp` —— 那等于对所有来源开放这个端口。
用完想删掉
```bashsudo ufw delete allow in on wlan0 from 10.112.4.0/24 to any port 8015 proto tcp
```
被排除掉的七个假设
这一段值得留着看。当时怀疑过下面这些,每一个都是停掉服务实测过的:
| 假设 | 怎么排除的 |
|---|---|
| FRP 隧道干扰 | 停掉 `frpc.service`,问题依旧 |
| strongSwan / IPsec | 服务本来就是 `inactive`,不是活动连接 |
| KDE Connect 的 SSH TUN | 停掉后 `tun66` 消失,导入仍失败 |
| Clash Verge 代理 | 停服务 + 完全重启微信,仍失败 |
| KDE Connect 用户守护进程 | 停掉后重启微信,仍失败 |
| Docker 虚拟网卡让微信选错地址 | 停 Docker、containerd 和容器、清掉 veth,仍失败 |
| 微信数据目录权限 | 目录属主权限正常、可读写、无 immutable 属性、磁盘有 700 GB 空闲 |
七个全排除,才把注意力从「谁在干扰网络」转到「包到底有没有到」。
顺序值得注意:验证一和验证二都不需要停任何服务。先做那两个, 范围就已经缩到防火墙了。上面这七个是在这之前做的,每一个都在短时间内 把机器上的一个服务关掉,属于扩大了影响面。
这套排查里能带走的
- 泛化的错误提示不可信。 「不在同一网络」不代表真的不在同一网络。
- `
10.x` 不异常。 它是标准私有段,没证据就不要当成 VPN。 - ping 通不等于端口通。 ICMP 和 TCP 入站是两条独立的路径,防火墙可以只放前者。
- 超时和拒绝是两种不同的失败。 超时指向丢包,拒绝指向没有监听。
- `
strace` 能把「应用没起来」和「网络不通」切开,比看日志直接。 - 查防火墙别只看 `
firewalld` / `nftables.service`。 UFW 可以在自身 `active (exited)` 的状态下,规则早就进了内核。 - 先做直接的、无副作用的验证,再去停服务。 顺序反了,排查成本会成倍上升。
排错
| 现象 | 可能原因 | 下一步 |
|---|---|---|
| 手机浏览器访问端口超时 | 防火墙 `DROP` |
查 `ufw status verbose` 的默认入站策略 |
| 手机浏览器连接被拒绝 | 端口没在监听 | 确认导入窗口开着,用 `ss -tlnp` 查 |
| 放行了还是不行 | 接口名或网段写错 | 重新 `ip -br addr` 确认,规则要跟实际一致 |
| Wi-Fi 能导入、USB 不能 | 两条路的接口和网段都不同 | 给 USB 接口单独加一条规则 |
| 换了手机热点就连不上 | 网段变了 | 规则里写死的是上一次的 `/24`,重新查再改 |
参考
- `
strace` / `ss` / `nmcli` / `ip`,都是系统自带 - `
ufw status verbose`,看默认策略和已有规则 - Arch Wiki: Uncomplicated Firewall