前几天看到骏骏菊苣在折腾着想给自己的路由上加上大清的 isatap 隧道访问 IPv6,本来我觉得是不太现实的,因为我电的寝室分配的 IP 地址虽然长得像外网 IP,但是实际上电信的出口就那几个,也就是说都经过了 NAT。 而 isatap 隧道需要有一个公网的 IP 作为接入点,所以没有公网 IP 就很尴尬。但是骏骏表示虽然走电信出口的话外网看来我们寝室分到的 IP 不是公网 IP,但是不要忘了还有教育网,我电寝室分到的 IP 在教育网上就是独立的 IP,他之前去上海玩儿的时候从复旦做过实验了,教育网内部是可以直接联通得,然后清华显然他们的 peer 也有教育网线路,所以理论上是可行的。理论上可行实际上怎么样就只能试一试才知道了,于是经过了一下午的参考和折腾,终于在路由器上用清华大学的 ISATAP 隧道成功搞定了 IPv6 ,为了使用方便还写了个脚本,后面会贴出来。

在折腾的过程中主要参考的是这个这个文档,同时对清华大学提供了如此方便的服务表示感谢~

先说需求,你需要有一个公网的 IP (或者至少像我电一样有一个教育网内能被访问到的 IP地址),然后一个支持 IPv6 的 Openwrt 路由(基于 Openwrt 的 LEDE 或者 PandoraBox 也都可以),可以查看有没有

/proc/net/if_inet6

这个文件,如果有的话那应该就是支持,同时想要支持 NAT 还需要一些额外的软件包,这里引用一下

 

检查内核模块和有用的软件包

ip6tables kmod-ipv6 kmod-ipt-nat6 kmod-ip6tables kmod-ip6tables-extra luci-proto-ipv6 iputils-traceroute6

kmod开头的内核模块一般无法通过opkg直接安装,其他软件包虽然可以通过opkg install直接安装,但会多占路由器存储空间,推荐在编译固件时就将这些软件包都放入固件

上述软件包除kmod-ipv6外并非必须。kmod-ipt-nat6提供IPv6 NAT支持,ip6tables kmod-ip6tables kmod-ip6tables-extra等提供IPv6防火墙,luci-proto-ipv6为LuCI提供IPv6设置选项,iputils-traceroute6为IPv6提供traceroute功能(mtr是个不错的支持双栈的traceroute替代品,如果路由器存储空间够大的话)

环境准备好之后就可以开始配置了,下面写的配置过程和方法是我自己结合了几篇文章 + 自己的实践总结出来的,所以可能和网上一些其他的方法有些出入,我自己是成功了的。

首先到路由器的 网络-》接口 设置,下面的全局选项里面吧 IPv6 ULA Prefix 清空,然后戳开 LAN 接口设置,给 LAN 接口分配一个 IPv6 的地址(这里分一个内网的地址,如 fc00:1024:1024::1/64 等,这个需要是一个内网的地址,所以只要符合内网网段的后面你想怎么写都可以。) IPv6 的网关、路由前缀留空就好。然后到下面的 IPv6 设置里,勾上 总是广播默认路由 选项。

然后打开 WAN6 的接口设置(如果支持 IPv6 的话一般都会有 WAN 和 WAN6 两个接口,没有的话可能需要手动添加)。协议选择 IPv6-in-IPv4 (RFC4213),本地 IPv4地址 填你的 WAN 接口获取到的 IP 地址或者干脆随便写一个(脚本会自动更新这个选项),远程 IPv4 地址填 166.111.21.1,本地 IPv6 地址填

2402:f000:1:1501:200:5efe:[本地 IPv4 地址]/64

这里面自己替换本地 IPv4 地址,或者随便填也可以,脚本也会更新这个选项。然后到高级设置里,去掉 默认网关 选项。

然后把下面这脚本复制到路由上,根据你的设置修改最上面的四个变量的值,然后运行一遍,不出意外的话应该就可以访问 IPv6 网络了。

01
02
03
04
05
06
07
08
09
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
37
38
39
40
41
#!/bin/sh
# 20170410
local_v4_interface=pppoe-wan
local_v6_interface=wan6
local_v6_link=6in4-wan6
local_lan_interface=br-lan
remote_v6="2402:f000:1:1501:200:5efe"
remote_v4="166.111.21.1"
echo "Shutdown IPv6 interface"
ifdown $local_v6_interface
sleep 3
local_wan_v4_addr=$(ip addr show dev $local_v4_interface | grep inet | awk '{print $2}')
echo "Get local wan IP address $local_wan_v4_addr"
local_v6_addr=$remote_v6:$local_wan_v4_addr/64
echo "Set local IPv6 address $local_v6_addr"
uci set network.$local_v6_interface.ip6addr=$local_v6_addr
uci set network.$local_v6_interface.ipaddr=$local_wan_v4_addr
uci commit network
echo "Reload network."
/etc/init.d/network reload
sleep 3
echo "Bring up IPv6 interface"
ifup $local_v6_interface
sleep 3
echo "Set up iptables rules"
ip6tables -t nat -A POSTROUTING -o $local_v6_link -j MASQUERADE
ip6tables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
ip6tables -A FORWARD -i $local_lan_interface -j ACCEPT
echo "Set up IPv6 route"
ip -6 route del default from 2402:f000:1:1501::/64
ip -6 route add default via $remote_v6:$remote_v4 dev $local_v6_link
echo "Done"

在路由上测试 IPv6 是否可用可以

ping6 ipv6.tsinghua.edu.cn

如果能 ping 通的话说明路由上是通了的,局域网内的设备可能需要断开重新连接路由,获取到 IPv6 地址之后才能访问 IPv6 网络。