家庭网络的 IPv6 接入
1. 上行接入
上行采用 PPPoE 协议。使用 Archlinux 默认的 netctl profile,能自动拿到一个 IPv6 地址,但是拿不到 PD。 参考万能的 Arch Wiki,感觉 dhcpcd 会比较好用,自己就支持 PD,还能加 hook。参考配置如下:
# /etc/dhcpcd.conf denyinterfaces end0 enu1 tun* duid noipv6rs ipv6only # The following applies to the interface WAN. interface ppp0 ipv6rs # Assign WAN the iaid 1. iaid 1 # Assign a Normal Address to the interface with iaid 1 (i.e. WAN). ia_na 1 # Delegate a prefix with wan interface iaid 1 (i.e. WAN) and lan interface LAN. ia_pd 1/::/64 enu1/0/112
# /etc/dhcpcd.exit-hooks/00-ip6-netmaps.sh if [ $interface == enu1 ]; then if [ $reason == DELEGATED6 ]; then prefix=$(awk -F '::' '{ print $1 }' <<<$new_delegated_dhcp6_prefix) snat_prefix=$prefix::/96 # 这里也能处理 IPv6 SNAT 的操作。 # 直接在线生成下游 DHCPv6 的配置。 cat <<EOF | tee /etc/dnsmasq.d/01-dhcpv6-server.conf enable-ra dhcp-range=$prefix::100,$prefix::200,112,24h EOF systemctl restart dnsmasq elif [ $reason == PREINIT ] || [ $reason == EXPIRE6 ] || [ $reason == STOPPED ]; then rm -f /etc/dnsmasq.d/01-dhcpv6-server.conf systemctl restart dnsmasq fi fi
有意思的是:
- 哪怕在 dhcpcd.conf 里不写 iana,仍然会获取到一个和 PPPoE 自己拿到的 IPv6 地址相同的 DHCPv6 Normal Address。 不知道是家宽的 DHCPv6 Server 比较死板,还是我的 dhcpcd 配置不对;
- 哪怕指定了要 /96 的前缀,上游还是会给一个 /60。我猜 PD 对前缀长度有最长限制,但是我懒得去试能否只拿到 /61 ~ /64 的前缀了。能拿到短前缀,当然很开心;
- 因为太懒,所以 hook 写得很粗暴,动辄重启 dnsmasq,时机即不充分也不必要。
2. 下行接入
选择用 DHCPv6 作为下游网络的接入。好处:
- 不是每个出口都有短于 /64 的前缀可以让我折腾,更长的前缀可以让我在每个出口用 NETMAP 对地址做一一映射的同时,留一些地址做其它用途。
坏处:
- 安卓设备都没法接入 IPv6 了,因为它们只支持 SLAAC。说实话我觉得甚至不一定是坏事,考虑到 IPv6 的安全问题可能比 IPv4 藏得更深。
参考了 前人经验,本来想用里面提到的 constructor:$iface 的语法,这样上面的 dhcpcd hook 可以简单点。 但是死活弄不出来能用的 Router Advertisement,读了源码发现两个问题:
- (我可能看错 代码 )想要弄出来 Stateful DHCPv6 的 RA,–dhcp-range 的第二个参数要么是地址区间结尾,要么是 constructor:$iface;
- constructor 语法定死了必须要 /64 的前缀。
因此最后还是自己用脚本生成 DHCPv6 的配置了,见上面的 hook。
3. Backlinks
- 多出口的家庭网络 (20251020T213424-多出口的家庭网络.org)