本文介绍基于OpenWrt 23.05,构建一个IPv6-mostly家庭网络。
目前国内三大运营商的家庭宽带基本实现了IPv6全覆盖。那么在2025年的今天,我们可以抛弃IPv4,只使用ipv6了吗?基于这个问题我在家里搞了一个纯ipv6的试验网。
所谓IPv6-mostly,个人理解就是在一个双栈的网络下。对于支持IPv6-Only的终端只使用IPv6协议栈,不使用IPv4协议栈,在访问IPv4网络时通过NAT64进行协议栈转换。对于仍然需要使用IPv4的终端,仍然维持双栈配置,从而实现平滑过渡。
这里还涉及到一系列的过渡技术,包括NAT64、DNS64、PREF64、DHCP Option 108、464XLT等。
终端支持情况
问了AI,现代的操作系统对IPv6-Only的支持情况已经很好了。基本上手机的操作系统都能很好适应IPv6-Only,因为app版本迭代快,并且有相应的审核机制在这里。如果一个app不支持IPv6,那么他很难上架到应用商店。
Windows 这边,系统层面是没问题了。但是为了兼容要老旧程序,IPv6-Only的支持的情况实际上还是需要看具体的软件。
以下是AI给出的答案,仅供参考,生成时间为2025年2月。
总结对比
平台 | 系统版本要求 | 核心技术 | 开发者适配重点 | 局限性 |
---|---|---|---|---|
Android | 5.0+(部分功能需更高版本) | 464XLAT、SLAAC | 避免IPv4硬编码,替换底层Socket API | 设备碎片化,DHCPv6支持不足 |
iOS | 9.0+ | DNS64/NAT64、CLAT集成 | 使用高层API,禁用IP地址硬编码 | 低版本iOS(<9.0)不兼容IPv6-only |
Windows | Windows 10 1703+ | 464XLAT、NAT64 | 适配双栈API,优化企业级网络配置 | 老旧版本需手动配置IPv6 |
建立IPv6-Only 的vlan
为了不影响原有使用的网络和方便调试,这里先新建一个vlan只配置IPv6地址。
我这里运营商给到的DHCPv6-PD前缀是一段/60的,可以划分出2个/61,或者4个/62,或者8个/63,或者16个/64子网。
在主网关上新建一个接口命名为lan8,使用静态地址协议,关联到eth0.8,表示eth0打上vlan tag 8,不配置IPv4,IPv6分配长度/61,表示这个接口会申请一段/61的地址,IPv6 分配提示8,表示会从DHCPv6-PD前缀的第8个ID开始申请地址。
例如运营商给我的DHCPv6-PD是2001:db8:d20::/60,那这个接口分配的地址将会是2001:db8:d20:8::/61。
/etc/config/network
配置如下。
1 | config interface 'lan8' |
lan8接口的DHCP服务器页面勾选”忽略此接口”,表示关闭DHCPv4服务器。RA 服务和DHCPv6 服务均配置为服务器模式,勾选启用 SLAAC,IPv6 RA设置RA 标记增加M标记。/etc/config/dhcp
配置如下
1 | config dhcp 'lan8' |
配置好后,把电脑接入这个vlan,会发现只能自动获取到IPv6地址,访问ipv6.test-ipv6.com,他会告诉我:你只接入了 IPv6 互联网,没有接入 IPv4。你可真勇敢!
访问了一些比较常见的网站,例如淘宝、京东、百度贴吧、B站大部分都可以正常使用,不是只有首页能打开那种,点进去图片和视频都能正常加载,和几年前比确实进步很大。
也有不能用的,例如:百度新闻、百度地图、高德地图、bing搜索、deepseek、豆瓣、github、csdn等。
配置NAT64
为了解决转换到IPv6-only后还需要访问IPv4的问题,我这里在旁路增加一台OpenWrt设备,负责实现NAT64和DNS64。
新增的OpenWrt设备,名字就叫NAT64吧,Wan口接入vlan2,也就是原来在用的双栈vlan,配置静态IPv4地址。Lan口接入vlan8获取自动获取IPv6地址。
NAT64和NAT44道理是差不多的,首先所有的IPv4地址全部映射到一个NAT64的前缀上,例如64:ff9b::/96,这是一个NAT64的通用前缀,当然也可以跟据实际需要自定义其他前缀。
当vlan8的终端想去访问192.0.2.1的时候,通过DNS64域名解析让他实际去访问64:ff9b::192.0.2.1,流量会走终端的默认路由到达主网关,在主网关上把64:ff9b::/96这个IP段路由到NAT64设备,NAT64设备进行地址转换后以wan口vlan2 的IPv4作为源地址,192.0.2.1作为目标地址走NAT64设备的默认路由到达主网关,主网关再进行NAT44出互联网。
在OpenWrt里,使用jool可以实现NAT64转换,安装jool。
1 | opkg update |
安装完成后在/etc/jool/jool-nat64.conf.json已经有很多默认的参数,使用默认参数基本上也可以满足要求,在日后遇到瓶颈时候再来深入微调。
但是有几个地方是需要改的,pool4是NAT64转换后使用的IPv4地址池。我这里只是用1个地址,改成NAT64设备的Wan口IPv4地址。也可以分配一个地址块,这和IPv4 NAT地址池的概念是类似的。如果分配一个地址块,需要在主网关上把地址块路由过来。
其次就是端口范围,由于我使用的是接口地址,所以端口范围最好在sysctl net.ipv4.ip_local_port_range
的范围内。默认的范围是
1 | net.ipv4.ip_local_port_range = 32768 60999 |
在/etc/sysctl.conf
,加入以下一段,把端口范围改大一点,然后sysctl -p
应用
1 | net.ipv4.ip_local_port_range = 32768 65535 |
附上/etc/jool/jool-nat64.conf.json
的完整配置
1 | { |
别忘了启用jool
1 | uci set jool.general.enabled="1" |
在主网关上添加64:ff9b::/96
静态路由指向NAT64设备,主网关设备的/etc/config/network
加入
1 | config route6 |
其中fd20:d20:0:8::cd7
是NAT64设备lan口(vlan8)的ULA前缀地址,ULA地址由主网关通过DHCPv6分配,基本上属于固定地址了,实在不放心可以在DHCPv6的静态租约里面固定后缀。当然也可以使用FE80开头的本地链路地址。
找一台vlan8的终端,ping测一下64:ff9b::223.5.5.5
,如无意外应该是可以ping通的。
配置DNS64、PREF64
有了NAT64后还需要DNS64来配合把域名的A记录转换为AAAA记录。配置DNS64后当一个域名有AAAA记录,DNS64服务器直接返回该域名的AAAA记录,如果域名没有AAAA记录只有A记录,那么DNS64服务器将通过NAT64前缀合成一个IPv6地址返回,引导终端访问NAT64服务。
在OpneWrt里用unbound可以实现DNS64这个功能。
1 | opkg update |
OpneWrt的dns服务默认由dnsmasq提供,所以dnsmasq会占用53端口。我这里把他修改成别的端口,然后启用unbound。
/etc/config/dhcp
配置文件修改dnsmasq的dns端口
1 | config dnsmasq |
/etc/config/unbound
配置文件开启DNS64,配置NAT64前缀,并把根域名转发至上游的DNS服务器,相当于把unbound配置成一个DNS递归服务器。
1 | config unbound 'ub_main' |
在主网关的/etc/config/dhcp
,通过RA下发DNS服务器地址。默认是下发主网关本身作为DNS服务器,我把ubound部署在NAT64设备(也就是旁网关)上,所以需要修改下发DNS地址为旁网关的地址。
1 | config dhcp 'lan8' |
配置完成后通过nslookup一个仅有A记录的域名,可以看到有NAT64前缀的AAAA记录返回。
1 | nslookup ipv4.3322.net |
PREF64是通过路由器公告(RA)或DHCPv6,向客户端动态传递NAT64前缀信息,在主网关的/etc/config/dhcp
加入配置或者在luci界面均可进行配置。
1 | config dhcp 'lan8' |
在vlan8的终端上抓包确认PREF64是否已经通告RA宣告tcpdump -i eth0.8 -nnv icmp6
1 | 01:36:43.670678 IP6 (flowlabel 0x7e65c, hlim 255, next-header ICMPv6 (58) payload length: 192) fe80::xxxx:xxxx:xxxx:xxxx > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 192 |
可以看到option (38) 包含了NAT64前缀,说明成功了。tcpdump version 4.99.4还识别不出来option (38) 所以显示为unknown option。
不过暂时还不知道有什么直观的办法去验证PREF64的具体作用,开没开感觉区别不大,猜想可能在大型网络中,有多个NAT64设备的时候,通过PREF64同时通告多个NAT64前缀实现可以负载分担的效果。
也有可能我手上的终端还不支持PREF64,或者系统的CLAT在没有PREF64的情况下自动转换成了公共NAT64前缀64:ff9b::/96
。
以下是AI给出的PREF64支持情况(2025年2月)。
各平台支持情况
平台 | DNS64支持 | PREF64支持 |
---|---|---|
Android | 支持(需Android 5.0+) | 部分支持(Android 12+) |
iOS | 完全支持(iOS 9.0+) | 支持(iOS 14+) |
Windows | 支持(Windows 10 1703+) | 需手动配置或依赖第三方工具 |
为原有的双栈vlan开启DHCP Option 108
开启办法,在主网关的DHCPv4里面开启即可/etc/config/dhcp
或LUCI页面配置均可,其中0:0:7:8=0x78(16进制)= 1800秒 = 30分钟。
1 | config dhcp 'lan2' |
开启后,在当前网络支持IPv6-only的前提下(包括但不限于已经具备NAT64、DNS64、PREF64、464XLT等能力),支持DHCP Option 108的终端将会在获取到IPv4地址30分钟后,释放IPv4地址租约,取消所在接口的IPv4地址,并运行在IPv6-only模式。
我暂时还没开启这个选项,一方面还不清楚我的终端是否支持DHCP Option 108。截止2025年2月,AI也不认识DHCP Option 108,没法给出支持情况。另一方面,我还需要长期运行并观察NAT64/DNS64的稳定性和可用性,待坑都踩完只再考虑把在主vlan开启这个选项。
总结
以上所有操作所用的OpenWrt版本均为官网23.05,部署完成后我将会持续使用观察。
另外,浏览器安装IPvFoo这个插件可以方便查看当前网站有多少域名使用了多少IPv6。
Enjoy~~
参考:
https://blog.lingxh.com/post/464xlat/
https://ripe87.ripe.net/wp-content/uploads/presentations/8-IPv6-mostly_on_OpenWRT.pdf
https://openwrt.org/docs/guide-user/network/ipv6/nat64
https://datatracker.ietf.org/doc/html/rfc8925