OpenWrt 配置 IPv6 NAT

网络环境

网络:华北电力大学校园网 IPv4/IPv6 双栈,IPv4/IPv6 地址皆为 DHCP

路由器:小米路由器3G, MediaTek MT7621芯片

系统版本: OpenWrt 18.06.1, 4.14.63内核

准备

一个刷写了 OpenWrt 系统的路由器。极路由和小米路由器3G都是不错的选择,其他路由器只要 CPU 在 OpenWrt 的硬件支持列表内,理论上都可以刷写。可以点击这里查看 OpenWrt 支持的硬件并下载相应的固件。

一个 IPv6 网络。使用 NAT66 的好处就在于,无论你的上端网关是用 DHCPv6 还是 SLAAC 亦或静态地址,只要你有 IPv6 地址,哪怕你分到了一个 /128 的 IPv6 地址,你也能组一个子网。

步骤

1.安装 ip6tables 和 kmod-ipt-nat6

官方版本的 OpenWrt 已经集成了ip6tables,所以执行以下安装命令时会提示“
ip6tables 已存在于root中”

opkg update
opkg install ip6tables kmod-ipt-nat6

opkg update 是每次安装软件前必需的步骤,作用是下载仓库里的软件包信息,每次重启后都必须执行,否则很大概率找不到软件。

2.更改 ULA-Prefix

在 LuCI 中进入 Network -> Interfaces ,你能看到页面下方 Global network options 中的 IPv6 ULA-Prefix (IPv6 ULA 前缀),默认情况下这是一段随机生成的 fd 开头的48位前缀,例如:fde4:8dba:82e1::1/48

LuCI 界面 IPv6 ULA-Prefix

LuCI 界面 IPv6 ULA-Prefix

你只需要把第一位的 f 改为 d ,例如下图,这一步就完成了!具体原因在下面,可以稍后再看。

LuCI 界面 IPv6 ULA-Prefix

LuCI 界面 IPv6 ULA-Prefix

fd00::/8 地址块中的地址是唯一本地地址,这个地址类似于 IPv4 中的私有地址(最典型的例子:192.168.1.123)。如果 Windows 电脑分配到这个地址不会有什么问题,但是 Android 手机如果被分配到唯一本地地址,则所有的网络请求会优先解析 IPv4。这样的话,你只能直接访问 IPv6 的 IP 地址,所有的域名解析都会优先解析为 IPv4 的地址。即使你连接了 IPv6 的 ShadowSocks VPN ,也无法改善这个问题。

为了避免这个情况,只好放弃 ULA 地址重新设置,但是为了避免地址冲突,我们需要根据 IANA 的 IPv6 分配表 选一个没有被使用的地址。可以很容易地发现 d000::/4 就是一段未分配的前缀,而且 OpenWrt 官方也推荐了这个方法,就是使用前16位为 dxxx 形式的 ULA 前缀,例如我所使用的 fde4:8dba:82e1::1/48。

3.更改 /etc/config/dhcp 文件

将 /etc/config/dhcp 文件中的 config dhcp ‘lan’ 下面的内容更改为:

config dhcp 'lan'
    option interface 'lan'
    option start '100'
    option limit '150'
    option leasetime '12h'
    option dhcpv6 'server'
    option ra 'server'
    option ra_management '1'

或者在  LuCI 中将 Network -> Interfaces ->  LAN -> DHCP Server -> IPv6 Settings 中的 Router Advertisement-Service 设为 server modeDHCPv6-Service 设为 server modeNDP-Proxy 设为 disabled  。这两步操作等价。

LuCI 界面 IPv6 Settings
LuCI 界面 IPv6 Settings

顺便可以将 DNS 设置为 Google IPv6 DNS: 2001:4860:4860::8888

或者我国下一代互联网国家工程中心的公共 DNS: 240c::6666

4.更改 /etc/firewall.user 文件

假设 WAN 对应的接口为 eth0.2 ,则在 /etc/firewall.user 文件中添加以下内容:

ip6tables -t nat -A POSTROUTING -o eth0.2 -j MASQUERADE

5.查找当前网络的 IPv6 网关地址

在 LuCI 的 Network -> Diagnostics 页面,
Traceroute 旁边的下拉框选择 IPv6,执行 Traceroute 操作,获取目前网络的 IPv6 网关地址(即第一跳的地址),假定为 2001:da8:20c:1a06::1 

一般情况下,如果在 Network -> Interfaces 界面看到自己 WAN6 接口的 IPv6 地址是 /64 的话,直接取前64位,最后4位取1,即可得到目前的 IPv6 网关地址。当然最好还是 Traceroute 测一下。

LuCI 界面 Diagnostics
LuCI 界面 Diagnostics

6.为路由器添加默认网关

使用 route -A inet6 add default gw 2001:da8:20c:1a06::1  命令,为路由器添加默认网关。这一步非常重要,不进行的话电脑能获取到 IPv6 地址但是会无法上网。完成之后,连接到路由器的计算机应该就可以正常访问 IPv6 网站了。

但是这条指令是一次性的,每次重启之后都必须执行。 如果要做到路由器开机自动添加该网关,需要在 /etc/hotplug.d/iface/ 下新建一个文件 90-ipv6 ,给予744可执行权限:

90-ipv6 权限
90-ipv6 权限

文件内容如下:

#!/bin/sh
[ "$ACTION" = ifup ] || exit 0
route -A inet6 add default gw 2001:da8:20c:1a06::1

注意替换自己的网关

7.Well Done!

最后重启一下路由器,所有的工作就完成了!你可以访问 test-ipv6.com 网站来确认自己是否已经正确接入了 IPv6 网络。

想说的话

其实 IPv6 NAT 配置起来非常简单,但是毕竟 NAT 有违 IPv6 的本意,所以之前在成功 NAT 了以后又开始尝试 IPv6 Passthrough (IPv6 穿透),即将路由器改造成 IPv4 路由器 + IPv6 交换机。但是将路由器重置十几遍后才发觉貌似不可行……偶然一次和网信办的工作人员交流了一下,了解到 IPv6 校园网虽然不计费不限速,但是也需要认证……只能胃疼地继续用 NAT66 了……

遇到的第二个问题就是 步骤2 中的前缀问题,尽管我知道 Android 有只支持 SLAAC 、无法手动配置 IPv6 DNS 等等许多还算影响不大的问题,但是前缀问题真的是导致我又重置了七八遍路由器,最后在引用的知乎专栏中才了解到了解决办法,也怪自己没有认真看官方文档。

当然,这个方法只推荐于 IPv6 需要认证,同时宿舍用路由器上网的大学教育网环境。如果 IPv6 无需认证,或者想在家中使用 IPv6 ,应该直接使用 IPv6 Passthrough (IPv6 穿透) 获取一个 2xxx 开头的全球单播地址,这样做不仅提高网络通信效率,还符合 IPv6 的初衷。

引用&资料