微信说「不在同一网络」,其实是被防火墙丢了包

导入聊天记录时提示两台设备不在同一网络。ping 是通的,微信也确实监听了 8015。直到从手机浏览器去访问那个端口拿到 ErrorTimeOut,方向才定下来。

手机和电脑连同一个热点,用微信导入聊天记录,电脑上弹出:

暂无法导入,请保持手机和电脑在同一网络

两台设备确实在同一个网段里。USB 网络共享试过,Wi-Fi 热点也试过,都能正常上网, 但导入就是失败。

先决条件

需要 说明
微信 Linux 原生版 3.x 与 Wine 版的导入机制不同,本文针对 4.x
一台 Linux 电脑 + 一台手机 用手机热点或 USB 网络共享组成局域网

三个自查命令:

```bash
ip -br addr                    # 看手机那侧的接口名和网段
sudo ufw status verbose        # 防火墙是不是 UFW 在管
ss -tlnp | grep 8015           # 导入窗口打开时,这个端口在不在监听
```

这套排查在什么环境上验证过

```plaintext
CachyOS (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 接管了。

```bash
ip -br addr                    # 看接口和地址
nmcli device                   # 看 NetworkManager 怎么认这个接口
```

实际拿到的:

```text
Wi-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>
```

打开导入窗口,抓到的是:

```text
socket(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,说明三件事:

  1. 导入模块已经进入网络阶段
  2. 它在所有 IPv4 接口上监听 8015
  3. 不存在「没权限绑端口」的问题

这一步把排查范围从「应用没起来」缩到了「入站路径不通」。用 `ss` 也能看到同样的结论, 但 `strace` 能证明它是微信自己建的监听,而不是别的进程占了端口。

验证二:从对端访问这个端口(决定性的一步)

保持导入窗口开着,用手机浏览器访问电脑的那个端口:

```plaintext
http://<电脑的局域网IP>:8015
```

结果是:

```plaintext
ErrorTimeOut
```

超时,不是拒绝。

这两种失败指向的方向不一样:

结果 含义
连接被拒绝 端口没在监听,或者应用拒绝了
超时 报文被丢掉了,`DROP` 的典型表现

顺带一个反面对照:这时候电脑是能 ping 通手机的。

```text
PING 10.112.4.49
3 packets transmitted, 3 received, 0% packet loss
```

ping 通只证明 ICMP 和基础路由可用,不代表特定 TCP 端口的入站被放行。 这两件事经常被当成一件。

第三步:查防火墙

```bash
sudo ufw status verbose
```
```text
Status: active
Default: deny (incoming), allow (outgoing), disabled (routed)
```

再看配置:

```text
/etc/default/ufw: DEFAULT_INPUT_POLICY="DROP"
```

默认入站是 DROP。 手机发往 8015 的包到了电脑就被丢了,应用层根本看不到, 所以微信只能报一句「不在同一网络」。

⚠️ 一个容易漏的地方

```text
ufw.service: active (exited)
firewalld.service: inactive
nftables.service: inactive
```

UFW 的服务状态是 `active (exited)` —— 它是一次性服务,开机时把 Netfilter 规则 写进内核就退出了,之后一直显示 `exited`。

只看 `firewalld` 或 `nftables.service` 的状态,会以为这台机器没有防火墙在管事。 它们不活动不等于没有规则,规则已经在内核里了。

修复

加一条最小放行规则:

```bash
sudo ufw allow in on wlan0 from 10.112.4.0/24 to any port 8015 proto tcp
```

这条规则限定得很死,只放行:

限定项 值
入站接口 `wlan0`
来源网段 手机热点的 `/24`
协议 TCP
目标端口 8015

放行后重启微信,重新进导入页面,导入成功。

USB 共享时要换接口名和网段

USB 共享走的是另一个接口,名字和网段都不一样,所以规则也得重写一条。 先查,再写:

```bash
nmcli device
ip -br addr
```

比如这次 USB 共享是 `enp6s0f4u2u2`、网段 `10.146.37.0/24`:

```bash
sudo ufw allow in on enp6s0f4u2u2 from 10.146.37.0/24 to any port 8015 proto tcp
```

不要图省事写成 `sudo ufw allow 8015/tcp` —— 那等于对所有来源开放这个端口。

用完想删掉

```bash
sudo 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 空闲

七个全排除,才把注意力从「谁在干扰网络」转到「包到底有没有到」。

顺序值得注意:验证一和验证二都不需要停任何服务。先做那两个, 范围就已经缩到防火墙了。上面这七个是在这之前做的,每一个都在短时间内 把机器上的一个服务关掉,属于扩大了影响面。

这套排查里能带走的

  1. 泛化的错误提示不可信。 「不在同一网络」不代表真的不在同一网络。
  2. `10.x` 不异常。 它是标准私有段,没证据就不要当成 VPN。
  3. ping 通不等于端口通。 ICMP 和 TCP 入站是两条独立的路径,防火墙可以只放前者。
  4. 超时和拒绝是两种不同的失败。 超时指向丢包,拒绝指向没有监听。
  5. `strace` 能把「应用没起来」和「网络不通」切开,比看日志直接。
  6. 查防火墙别只看 `firewalld` / `nftables.service`。 UFW 可以在自身 `active (exited)` 的状态下,规则早就进了内核。
  7. 先做直接的、无副作用的验证,再去停服务。 顺序反了,排查成本会成倍上升。

排错

现象 可能原因 下一步
手机浏览器访问端口超时 防火墙 `DROP` 查 `ufw status verbose` 的默认入站策略
手机浏览器连接被拒绝 端口没在监听 确认导入窗口开着,用 `ss -tlnp` 查
放行了还是不行 接口名或网段写错 重新 `ip -br addr` 确认,规则要跟实际一致
Wi-Fi 能导入、USB 不能 两条路的接口和网段都不同 给 USB 接口单独加一条规则
换了手机热点就连不上 网段变了 规则里写死的是上一次的 `/24`,重新查再改

参考