都说国家在大力推行IPv6了不是,咱们怎么也得整上一个不是。国内三大运营商应该基本都分配IPv6了,但是得把光猫设置成桥接模式才可以让内网的设备获得IP,如果运营商没给IPv6的话应该可以打电话问问。除此以外各大高校基本都是有教育网IPv6的,而且有的学校还不限流量。IPv6的存在是为了解决IPv4地址耗尽的问题,理论上IPv6地址可以给地球上每一个沙子都整一个hhh,设计的挺美好但是实际应用中感知并不那么强烈。而且鉴于以上的设计,IPv6是没有NAT的,虽然有NAT66的实现,但是一般也不推荐使用。

本人目前在宿舍可以直接DHCPv6获取到v6的IP,但是猜测学校是为了响应一终端一号的安全要求,分配的IP竟然是/64的,这种情况也就是所谓的无PD(Prefix Delegation)。正常情况下IPv6应该给分配一个地址前缀,然后你自己的路由设备给局域网内的设备分配这个前缀下的子IP。而无PD后这个IP就算到头了,不可以再往下分配了,这就导致了只可以单个设备使用(实在不想吐槽1202年了宿舍竟然还只能一个设备上个看视频都卡的网),所以解决这个问题的方法也简单,那就是IPv6 NAT。

这里把IPv6 ULA 前缀提出来说下,这个东西其实就是一个内网IP前缀,设计用来方便内网内主机间使用IPv6通信,但是不支持此类IP直接作为源IP访问外部的公网地址。多数情况下在OpenWrt里这个值设置了没问题,在无PD环境下还必须设置。

有PD IPv6中继

未测试 留坑

家庭用户一般是PPPoE拨号,运营商会给分配有PD的IPv6前缀,所以OpenWrt里IPv6设置选择中继就可以了

image-20211209174016924

无PD IPv6 NAT内网

先直接贴两个大佬:

我这里WAN口获取到的IPv6这样子,真的无力吐槽

image-20211209180108269

构造IPv6 NAT其实也简单,主要就是添加NAT和设置默认路由。

首先确认OpenWrt支持IPv6 NAT,这里安装了如下pkg。不过由于有很多内核模块,我其实是直接自己编译进去了,稳妥点

1
opkg install kmod-ipt-nat6 kmod-nf-nat6 ip6tables kmod-ip6tables kmod-ip6tables-extra odhcp6c odhcpd-ipv6only

然后需要设置IPv6 ULA 前缀,因为之后IPv6流量就是由被路由器分配的IPv6 ULA地址发出,到路由器进行一层NAT

ULA前缀可以在https://www.ip-six.de生成,填入自己的MAC地址即可,当然也可以生成一个Fake MAC来这里

image-20211209175407893

可以直接用uci设置也可以直接web界面上设置,有人建议把地址的第一个f改成d,按需求来吧没问题可以不改

1
2
uci set network.globals.ula_prefix="fd0f:2ff1:36ba::/48"
uci commit network

OpenWrt经过尝试后需要如下设置,且各处的使用内置的IPv6管理需要打开,DHCP/DNS设置里的禁止解析 IPv6 DNS 记录要取消

image-20211209175626852

到这里内网设备应该已经可以获取到ULA前缀的IPv6地址了

image-20211209175914086

LAN口也有了自己的v6 IP

image-20211209175953339

到这里就只剩下最后防火墙和路由配置,由于每次Interface的变化可能导致默认IPv6网关变化,所以使用了hotplug实现自动化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/bin/sh

[ "$ACTION" = ifup ] || exit 0
NETWORK_NAME=wan6
[ "$INTERFACE" = "$NETWORK_NAME" ] || exit 0

WAN6_INTERFACE=$(uci get "network.$NETWORK_NAME.ifname")
if [ -z "$WAN6_INTERFACE" ] || [ ! -e "/sys/class/net/$WAN6_INTERFACE/" ] ; then
logger -t nat6 "Fatal error: Lookup of $WAN6_NAME interface failed" && exit 1
fi

WAN6_GATEWAY=$(route -A inet6 -e | grep "$WAN6_INTERFACE" | awk '/::\/0/{print $2; exit}')
if [ -z "$WAN6_GATEWAY" ] ; then
logger -t nat6 "Fatal error: No IPv6 gateway for $WAN6_INTERFACE found" && exit 1
fi

LAN_ULA_PREFIX=$(uci get network.globals.ula_prefix)
if [ $(echo "$LAN_ULA_PREFIX" | grep -c -E "^([0-9a-fA-F]{4}):([0-9a-fA-F]{0,4}):") -ne 1 ] ; then
logger -t nat6 "Fatal error: IPv6 ULA prefix $LAN_ULA_PREFIX seems invalid" && exit 1
fi

ip6tables -t nat -I POSTROUTING -s "$LAN_ULA_PREFIX" -o "$WAN6_INTERFACE" -j MASQUERADE
if [ $? -eq 0 ] ; then
logger -t nat6 "Added IPv6 masquerading rule to the firewall (Src: $LAN_ULA_PREFIX - Dst: $WAN6_INTERFACE)"
else
logger -t nat6 "Fatal error: Failed to add IPv6 masquerading rule to the firewall (Src: $LAN_ULA_PREFIX - Dst: $WAN6_INTERFACE)" && exit 1
fi

ip -6 route add default via "$WAN6_GATEWAY" dev "$WAN6_INTERFACE" proto static metric 512 pref medium
if [ $? -eq 0 ] ; then
logger -t nat6 "Added $WAN6_GATEWAY to routing table as gateway on $WAN6_INTERFACE for outgoing connections"
else
logger -t nat6 "Error: Failed to add $WAN6_GATEWAY to routing table as gateway on $WAN6_INTERFACE for outgoing connections"
fi

exit 0

将脚本放在/etc/hotplug.d/iface下即可,命名为99-nat6NETWORK_NAME的值要根据不同设备进行修改,具体的看图吧,这个折腾了我好久,不是很了解这部分

image-20211209180948646

然后重启下wan6就可以愉快的开启IPv6之旅了

image-20211209181126525

如果你开启了SmartDNS,请勾选上IPV6服务器并添加几个IPv6的DNS服务器

image-20211209181306771