默认情况下 OpenWRT 是不允许 IPv6 出流量的,本文将通过防火墙设置放通 IPv6 出流量。
测试
首先你得确保你的运营商没有屏蔽你的IPv6流量,测试的方法也很简单,一般来说OpenWRT不会屏蔽ICMP流量,可以先获得以下本机IPv6然后从外部具备IPv6的环境Ping一下,如果能通则说明至少ISP层面没有强封锁;如果干脆Ping不通的话考虑光猫或者运营商层面上是否存在限制。
如果你在本机上直接使用诸如ifconfig
等命令查看IPv6地址的话可能会比较困惑无法分辨哪个是有效IPv6:
1 2 3 4 5 6 7 8 9 10 11
| root@armbian:~# ifconfig eth0 eth0: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500 inet 192.168.8.3 netmask 255.255.255.0 broadcast 192.168.8.255 inet6 2409:56db:9b06:47f3:2173:5b3f:89d2:a20e prefixlen 64 scopeid 0x0<global> inet6 fe80::b379:19a4:99c4:48fe prefixlen 64 scopeid 0x20<link> ether F4:FC:03:DF:25:05 txqueuelen 1000 (Ethernet) RX packets 149754056 bytes 129274231243 (120.3 GiB) RX errors 0 dropped 4004 overruns 0 frame 0 TX packets 145761725 bytes 105393512031 (98.1 GiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 65
|
所以不如直接使用外部API获得当前IPv6地址:
1 2
| root@armbian:~# curl -6 ip.sb 2409:8a02:901e:9100:5ad7:8a4a:4f61:712a
|
环境
- OpenWRT:
OpenWrt 21.02-SNAPSHOT r15812+879-46b6ee7ffc / LuCI openwrt-21.02 branch git-22.245.77575-63bfee6
- 路由器:GL-MT3000
能Ping通吗?
首先从ip.sb
获得你的IPv6地址之后可以从外部具备IPv6通信能力的环境Ping一下,如果能够Ping通,则进行下一步。一般来说OpenWRT不会屏蔽ICMP流量,可以先Ping一下,如果到这里都不通一般也没必要下一步了。
能通信吗?
创建一个临时规则看一下能不能通信:打开OpenWRT-网络-防火墙-通信规则,拉到下面,新增:
- 名称随便写,但要记住
- 协议选
TCP
、UDP
和ICMP
- 源区域选WAN口所在Zone
- 源地址源端口留空
- 目标区域:
如果是以路由器本机作为测试,则选择“设备(输入)”
如果是以下面挂接设备作为测试,则选择LAN口所在Zone(推荐) - 目标地址目标端口留空
- 操作选接受
其他未提到的选项全部留空。
这个时候在你对应的目标区域下面的设备上开个http服务,我这里用的是caddy测试,比较方便主要是。别的文章提到测试80、443啥的,我倒觉得没必要,大概率不会通(53、80、443、8080)。
- 下载caddy
- 写个
caddyfile
:1 2 3 4 5 6 7
| :6666 { respond "Port-6666-Respond" }
:7788 { respond "Port-7788-Respond" }
|
- 把caddyfile和caddy主程序放在一起,然后启动caddy:
- 根据测试的端口动态调整caddyfile的内容,然后在外面
curl
一下,有正确的回应就可以了。
这个时候测试完了,到OpenWRT防火墙里面删掉刚才新建的防火墙规则,不要动别的。
设置防火墙
打开OpenWRT-网络-防火墙-通信规则,拉到下面,新增:
- 常规设置
- 名称随便写
- 协议选
TCP
、UDP
和ICMP
(或者根据实际情况写,不需要的可以不选) - 源区域选WAN口所在Zone
- 源地址指定的是访问者的地址,如果需要就指定,不需要则留空
- 源端口指定的是访问者访问目标地址的端口,如果需要就指定,不需要则留空
- 目标区域:
如果是以路由器本机作为暴露对象,则选择“设备(输入)”
如果是以下面挂接设备作为暴露对象,则选择LAN口所在Zone(推荐) - 目标地址看下面解释
- 目标端口根据实际情况写,就是要暴露出去的端口
- 操作选接受
- 高级设置
- 时间限制
其他未提到的选项均留空或保持默认,不要乱动其他的。
目标相关
首先先简单介绍一下IPv6地址的类型:
- 本地地址(链路本地地址):
只出现在一条链路上,每个网络接口都有一个这样的IPv6地址。此地址只能出现在二层链路上,不能通过三层设备。地址范围是fe80::/10
,地址组成规则:fe80+10bit的0+mac地址扩展成64bit地址。 - 唯一本地地址(ULA):
ULA在概念上更接近IPv4概念下的“局域网”的概念。指在一个组织内部可达的ipv6地址,这类地址不能出现在internet上。地址范围:fc00::/7
。 - 全球单播地址(公网IP):
等同于IPv4公网地址。用于可以聚合的链路,最后提供给网络服务提供商。这种地址类型的结构允许路由前缀的聚合,从而满足全球路由表项的数量限制。地址包括运营商管理的48位路由前缀和本地站点管理的16位子网ID,以及64位接口ID。
其中2002::/16
被称为6to4地址,就是IPv4地址转成IPv6地址;此外还有3ffe::/16
用于测试目的。
其中只有第三种适用本文的防火墙开放端口设置。并根据IPv6的获取方式分为如下几种:
- EUI-64(最推荐)
EUI-64 地址有着我们需要的优点:后缀固定不变、前缀实时更新。一般情况下,我们应该使用它。如果获得的子网大小不是 /64,可能不按预期工作。
想了解EUI-64的可以查看这篇文章(英文)
如果不确定自己的地址是不是EUI-64地址,可以在EUI-64 Calculator用自己的MAC地址计算一下并对比从ip.sb
等API获得的IPv6的后缀。 - 临时DHCPv6地址(不推荐)
这种情况下所有地址部分都不确定,不推荐。 - 固定后缀的DHCPv6地址(推荐)
在OpenWRT中可以指定客户端的DHCPv6后缀,需要对需要开放端口的设备固定DHCPv6后缀
打开网络-DHCP/DNS-静态地址分配-新增,然后指定MAC地址和IPv6后缀即可,IPv6后缀是可以随意指定的。
注意租期需要设置的比较短,否则当DHCPv6更新时客户端可能不会收到更新。
如果你的地址是EUI64地址或者指定了后缀的DHCPv6地址,那么在上面“目标地址”中可以按如下规则填写,如果路由器被分配到的子网不是/64
则根据实际情况调整:
1
| ::<需要暴露的主机的后缀>/::ffff:ffff:ffff:ffff
|
例如:
1 2
| ::E6E8:D2FF:FE94:541B/::ffff:ffff:ffff:ffff ::6699/::ffff:ffff:ffff:ffff
|
其中/::ffff:ffff:ffff:ffff
部分是掩码,写在目标地址的时候需要一并写入。
这部分内容也适用于来源地址,指定访问设备。