
家里网络最近使用 “My NAT” 和 “NatTypeTester” 工具测了下,发现家里的 NAT 类型是最差的一种 NAT 类型:NAT4 - ”对称型NAT“。如下图:

这种 NAT 网络穿透能力极差,必须进行优化。优化思路有这么几种:
所以联系了运营商,这几天将光猫改为了桥接,用自己的路由器 - iStoreOS(基于 OpenWrt)拨号上网。改之后如下:


🎉🎉🎉好歹不是最差的了!
然后这几天才发现,改了后 Tailscale netcheck 里 IPv6 那行写着 no。5 台同局域网的机器,这一行都是 no。
查下来是个前缀委派错配,就是路由器拨号模式改了,但是 IPv6 相关配置没及时更新。
📝声明:文中公网 IPv6 前缀已做掩码处理,具体数值以
xxxx代替。
IPv6: no, but OS has support。
这句很容易被读成「这台机器没有 IPv6」。实际上不是。
netcheck 在这一行背后至少看了三件事:
用 tailscale netcheck --format json 看原始字段,5 台节点的结果完全一致:
字段 | 值 | 含义 |
|---|---|---|
| true | 系统有 IPv6 栈 |
| true | 有默认路由,包能发出去 |
| false | 一次 STUN 往返都没完成 |
| 空 | 没探到可用的全局地址 |
IPv6CanSend 对应的是:
ip -6 addr 里有全局地址(SLAAC 分到的 /64),ip -6 route show 里有 default。这两条都满足,它就是 true。
逐条测试排查:
traceroute6 到 2400:xxxx::1:第 1 跳是路由器,第 2 跳开始全是 *。tcpdump:只看到 echo request 出去,没有任何 ICMPv6 错误回来。到第 4 步,问题范围已经从「运营商」收缩到「路由器内部的 LAN 转发路径」。
再看出口设备:
ip -6 route get 2400:xxxx::1 from <LAN地址>输出里出口是 via fe80::1 dev eth1。
eth1 是裸物理口,不是 pppoe-wan。LAN 的 IPv6 流量被扔进了一个没有 PPPoE 封装的接口,出去了也没人接。
📝Notes:这一段是 iStoreOS/OpenWrt 的 uci 配置,其他系统的对应项名字不同,机制类似。
运营商的 PD 是 240e:xxxx:xxxx:xxxx::/60(具体前缀已掩码),也就是 16 个 /64。
LAN 上实际用的却是另一个 240e:xxxx:xxxx:xxxx::/64,压根不在上面这 16 个 /64 里。
三个 uci 项共同造成这个结果:
network.lan.ip6class='wan6':LAN 只接受 wan6 这个接口提供的前缀。而 wan6 绑在裸 eth1 上,不是 PPPoE 那个 wan_6。主因。(⚠️:PPPoE之前,WAN口叫作wan6-没有下划线;PPPoE之后,WAN口叫作 wan_6 - 有下划线)network.wan.delegate='0':禁止把 PPPoE 拿到的 /60 委派给 LAN。network.wan6.device='eth1':多出来的一个 DHCPv6 客户端,绑在物理口上。三项叠加,LAN 就拿着一个不在委派段里的 /64,配上一个指向裸 eth1 的默认路由。
/etc/config/network。uci set network.lan.ip6class='wan_6'。uci set network.wan.delegate='1'。uci commit,然后 ifup lan。ip -6 addr show br-lan,看前缀是否落在运营商的 /60 里;ubus call network.interface.wan_6 status,看委派前缀;uci get network.lan.ip6class,核对 class 是否匹配。network.wan6.disabled='1',再 ifup wan6。修复后 LAN 前缀变成 240e:xxxx:xxxx:xxxx::/64,默认路由走 pppoe-wan。
netcheck 从 IPv6: no 变成 IPv6: yes。如下图:
Report:
* Time: 2026-11-09 15:01:27.560476242+08:00
* UDP: true
* IPv4: yes, 49.76.xxx.xx:17338
* IPv6: yes, [240e:3a3:20bb:8xxx:xxxx:xxxx:xxxx:xxxx]:60572
* MappingVariesByDestIP: false
* PortMapping: UPnP, NAT-PMP, PCP
* CaptivePortal: falseping6 从 100% 丢包变成 AliDNS 13.8ms。
手机(有 IPv6 地址)打开 Tailscale,可以 100% 稳定直连到家里的 Tailscale 其他设备。如下图:

路由器修好了,客户端 netcheck 可能还是 no。
原因是 SLAAC 分下来的旧地址 valid_lft 还有大约 90 分钟,内核做源地址选择时仍然可能挑中那个旧前缀。
手工清一下:
sudo ip -6 addr flush dev enp37s0 scope global这一步漏掉,会得到「配好了但没用」的错觉。
排查过程中顺手看了下 pppoe-wan,地址是 100.x.x.x/32,落在 100.64.0.0/10 这个 RFC 6598 定义的共享地址空间(Shared Address Space)里。
也就是说我这条电信宽带没有公网 IPv4。
路由器上 miniupnpd 报 IGNORED: private/reserved address 不是故障,端口转发本来就到不了公网,PortMapping 里UPnP永远无法正常发挥作用。
这个 CGNAT 是 cone 型(具体是端口限制锥形)(MappingVariesByDestIP: false),IPv4 打洞依然能成,所以修复之前,基于 IPv4 直连没彻底断 - 时灵时不灵。
要根治还是两条路:
另外电信每次重拨都会换 PD 前缀,这次 PD 前缀发生了变更(具体前缀已掩码)。属正常现象,配置写进 uci 之后 LAN 会自动跟随,不用每次手动改。
整理成可复用的顺序,下次换台设备也能照着走:
ip -6 addr / ip -6 route show:有没有全局地址、有没有默认路由。traceroute6 2400:xxxx::1:第几跳开始静默。第 1 跳死是局域网问题,第 2 跳死是网关问题。ping6 -I <WAN地址> <公网v6>:判断 ISP 侧通不通。ip -6 route get <公网v6> from <LAN地址>:看出口 dev 是不是 pppoe-wan 或 wan。ubus call network.interface.wan_6 status 加 uci get network.lan.ip6class:核对委派前缀与 LAN 前缀、class 是否匹配。IPv6: no, but OS has support 的迷惑性在于它把三件事压成了一行:系统能力、发包能力、连通性。
前两个 true,第三个 false,输出就成了一个 no。
把三件事拆开,再用 ip -6 route get ... from ... 定位出口设备。
iStoreOS 上的 ip6class、delegate、wan6.device 三个项互相牵连,只改一个不够。改完记得清客户端旧地址,旧地址的 valid_lft 没走完之前,客户端可能一直拿着旧前缀。
以上。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。