在 openwrt 上使用清华的 ISATAP 隧道访问 IPv6

前几天看到骏骏菊苣在折腾着想给自己的路由上加上大清的 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 网络了。


#!/bin/sh
# Made by LazyCat@iLazyCat
# 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 网络。