首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >有 IPv6 地址却出不去:一次 iStoreOS ip6class 错配的完整定位

有 IPv6 地址却出不去:一次 iStoreOS ip6class 错配的完整定位

原创
作者头像
东风微鸣
发布于 2026-11-10 09:51:27
发布于 2026-11-10 09:51:27
760
举报

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

NAT4 - ”对称型NAT“
NAT4 - ”对称型NAT“

这种 NAT 网络穿透能力极差,必须进行优化。优化思路有这么几种:

  • ❌ 找运营商要公网地址:试过了,不给
  • ✅ 光猫改桥接:少一层 NAT 转换,会好很多
  • ❌ 路由器配置优化,防火墙优化:测之前就已经优化过了,结果还是NAT4 - ”对称型NAT“。证明跟这条没关系。

所以联系了运营商,这几天将光猫改为了桥接,用自己的路由器 - iStoreOS(基于 OpenWrt)拨号上网。改之后如下:

iStoreOS PPPoE 拨号上网
iStoreOS PPPoE 拨号上网
NAT3 - 端口受限锥形 NAT
NAT3 - 端口受限锥形 NAT

🎉🎉🎉好歹不是最差的了!

然后这几天才发现,改了后 Tailscale netcheck 里 IPv6 那行写着 no。5 台同局域网的机器,这一行都是 no。

查下来是个前缀委派错配,就是路由器拨号模式改了,但是 IPv6 相关配置没及时更新。

📝声明:文中公网 IPv6 前缀已做掩码处理,具体数值以 xxxx 代替。

一、Tailscale 输出分析

IPv6: no, but OS has support。

这句很容易被读成「这台机器没有 IPv6」。实际上不是。

netcheck 在这一行背后至少看了三件事:

  1. 操作系统有没有 IPv6 能力、
  2. 能不能把包发出去、
  3. 能不能完成一次 STUN 往返。

用 tailscale netcheck --format json 看原始字段,5 台节点的结果完全一致:

字段

值

含义

OSHasIPv6

true

系统有 IPv6 栈

IPv6CanSend

true

有默认路由,包能发出去

IPv6

false

一次 STUN 往返都没完成

GlobalV6

空

没探到可用的全局地址

IPv6CanSend 对应的是:

  • ip -6 addr 里有全局地址(SLAAC 分到的 /64),
  • ip -6 route show 里有 default。

这两条都满足,它就是 true。

二、证据链:从 0.5ms 到黑洞

逐条测试排查:

  1. 局域网内正常:ping 路由器和同网段节点,0.5ms,0% 丢包。
  2. traceroute6 到 2400:xxxx::1:第 1 跳是路由器,第 2 跳开始全是 *。
  3. tcpdump:只看到 echo request 出去,没有任何 ICMPv6 错误回来。
  4. 在路由器上分源 ping6:路由器自身 ping6 正常,用 WAN 源 ping6 正常,用 LAN 源 ping6 100% 丢包。

到第 4 步,问题范围已经从「运营商」收缩到「路由器内部的 LAN 转发路径」。

再看出口设备:

代码语言:bash
复制
ip -6 route get 2400:xxxx::1 from <LAN地址>

输出里出口是 via fe80::1 dev eth1。

eth1 是裸物理口,不是 pppoe-wan。LAN 的 IPv6 流量被扔进了一个没有 PPPoE 封装的接口,出去了也没人接。

三、根因:三个 uci 项凑出来的错配

📝Notes:这一段是 iStoreOS/OpenWrt 的 uci 配置,其他系统的对应项名字不同,机制类似。

运营商的 PD 是 240e:xxxx:xxxx:xxxx::/60(具体前缀已掩码),也就是 16 个 /64。

LAN 上实际用的却是另一个 240e:xxxx:xxxx:xxxx::/64,压根不在上面这 16 个 /64 里。

三个 uci 项共同造成这个结果:

  1. network.lan.ip6class='wan6':LAN 只接受 wan6 这个接口提供的前缀。而 wan6 绑在裸 eth1 上,不是 PPPoE 那个 wan_6。主因。(⚠️:PPPoE之前,WAN口叫作wan6-没有下划线;PPPoE之后,WAN口叫作 wan_6 - 有下划线)
  2. network.wan.delegate='0':禁止把 PPPoE 拿到的 /60 委派给 LAN。
  3. network.wan6.device='eth1':多出来的一个 DHCPv6 客户端,绑在物理口上。

三项叠加,LAN 就拿着一个不在委派段里的 /64,配上一个指向裸 eth1 的默认路由。

四、修复与验证

  1. 备份 /etc/config/network。
  2. uci set network.lan.ip6class='wan_6'。
  3. uci set network.wan.delegate='1'。
  4. uci commit,然后 ifup lan。
  5. 验证三处:
    • ip -6 addr show br-lan,看前缀是否落在运营商的 /60 里;
    • ubus call network.interface.wan_6 status,看委派前缀;
    • uci get network.lan.ip6class,核对 class 是否匹配。
  6. 确认生效后,network.wan6.disabled='1',再 ifup wan6。

修复后 LAN 前缀变成 240e:xxxx:xxxx:xxxx::/64,默认路由走 pppoe-wan。

netcheck 从 IPv6: no 变成 IPv6: yes。如下图:

代码语言:txt
复制
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: false

ping6 从 100% 丢包变成 AliDNS 13.8ms。

手机(有 IPv6 地址)打开 Tailscale,可以 100% 稳定直连到家里的 Tailscale 其他设备。如下图:

手机 100% 稳定直连家里
手机 100% 稳定直连家里

五、最容易漏的一步:客户端旧地址

路由器修好了,客户端 netcheck 可能还是 no。

原因是 SLAAC 分下来的旧地址 valid_lft 还有大约 90 分钟,内核做源地址选择时仍然可能挑中那个旧前缀。

手工清一下:

代码语言:bash
复制
sudo ip -6 addr flush dev enp37s0 scope global

这一步漏掉,会得到「配好了但没用」的错觉。

六、附带发现:CGNAT 与打洞

排查过程中顺手看了下 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 直连没彻底断 - 时灵时不灵。

要根治还是两条路:

  • ✅ 把 IPv6 修好(已经做了),
  • ❌ 或者向电信申请公网 IP - 不可能做到

另外电信每次重拨都会换 PD 前缀,这次 PD 前缀发生了变更(具体前缀已掩码)。属正常现象,配置写进 uci 之后 LAN 会自动跟随,不用每次手动改。

七、五步排查顺序

整理成可复用的顺序,下次换台设备也能照着走:

  1. ip -6 addr / ip -6 route show:有没有全局地址、有没有默认路由。
  2. traceroute6 2400:xxxx::1:第几跳开始静默。第 1 跳死是局域网问题,第 2 跳死是网关问题。
  3. 上路由器 ping6 -I <WAN地址> <公网v6>:判断 ISP 侧通不通。
  4. ip -6 route get <公网v6> from <LAN地址>:看出口 dev 是不是 pppoe-wan 或 wan。
  5. 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 删除。

目录
  • 一、Tailscale 输出分析
  • 二、证据链:从 0.5ms 到黑洞
  • 三、根因:三个 uci 项凑出来的错配
  • 四、修复与验证
  • 五、最容易漏的一步:客户端旧地址
  • 六、附带发现:CGNAT 与打洞
  • 七、五步排查顺序
  • 总结
  • 📚️参考文档
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档