解决小米路由器ipv6端口精准放行问题
posts/%E8%A7%A3%E5%86%B3%E5%B0%8F%E7%B1%B3%E8%B7%AF%E7%94%B1%E5%99%A8ipv6%E7%AB%AF%E5%8F%A3%E7%B2%BE%E5%87%86%E6%94%BE%E8%A1%8C%E9%97%AE%E9%A2%98背景
由于传统的 ipv4 公网联机方案带宽不够用(打游戏时游戏模组加太多而且人也多,所以打 BOSS 时容易出现卡死的情况)但又不想加钱,于是想利用 ipv6 联机。
由于我的小米路由器 R3G 打开 ipv6 后会对外部一切的流量进行拦截,导致 wifi 下的局域网设备即使有了公网 ipv6 也无法实现公网的功能,小米也没有提供关闭防火墙的功能(貌似其他型号的设备有)。
当然也可以使用有线中继模式,把设备交给光猫托管,但我的光猫会一刀切放行,等于所有设备全暴露在公网上,让人感到不安全,所以这个方案被放弃了。
所以要解决的主要就是 ipv6 端口放行问题,当然小米是一刀切拦截,但是我们不能这个放行也一刀切,所以就有了如下方案。
解决方案
更换开发版系统并开启 SSH
这个网上有很多教程了,这里不再多赘述。但由于开发版本太旧,没有开启 ipv6 功能需要我们手动开启。
开启 ipv6
ssh 连接到路由器后,使用vi
编辑/etc/config/ipv6
将list if_off 'wan'
修改为list if_on 'wan'
,修改后的文件如下:
config ipv6 'settings'
list if_on 'wan'
list if_on 'ipv6'
option ipv6_show '1'
option enabled '1'
option mode 'native'
然后重启路由器后就启用 ipv6 了。
分析 ip6tables
执行ip6tables -L
观察防火墙链规则,规则大致如下:
Chain INPUT (policy ACCEPT)
target prot opt source destination
delegate_input all anywhere anywhere
Chain FORWARD (policy DROP)
target prot opt source destination
delegate_forward all anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
delegate_output all anywhere anywhere
从规则可以看出,INPUT
和OUTPUT
都为ACCEPT
,仅有FORWARD
为DROP
,这也解释了防火墙默认打开原因。
继续观察自定义链delegate_forward
:
target prot opt source destination
forwarding_rule all anywhere anywhere /* user chain for forwarding */
ACCEPT all anywhere anywhere ctstate RELATED,ESTABLISHED
DROP all anywhere anywhere ctstate INVALID
zone_lan_forward all anywhere anywhere
zone_wan_forward all anywhere anywhere
zone_ready_forward all anywhere anywhere
reject all anywhere anywhere
这更加表明几乎拦截了一切的外部 ip 访问,当然解决这个问题也非常的简单,在delegate_forward
前附加一个ACCEPT
规则就可以了。
在 delegate_forward 前附加额外放行规则
假如我要放行当前的局域网某台设备的 22 端口,只需要我的局域网设备的全局 ipv6 地址(而不是链路 ip 地址)和放行端口号 22 就可以了。
所以我们用[ipv6]
代表可以从外部访问的全局 ipv6 地址(也就是你想从公网 ip 访问的地址),[port]
代表可以通过外部访问的端口号。
以放行一个 TCP 连接为例,我们就有了如下命令:
ip6tables -I FORWARD -d [ipv6] -p tcp --dport [port] -j ACCEPT
设置成功后,我们可以在另一台公网上的 IP 通过命令nc -zv [ipv6] [port]
方式来确定端口是否可达。
一些后续的安全考虑
通过ip a
发现小米路由器开启 ipv6 后具有公网 ip,感觉到不安全又搓了几行规则,规则如下:
ip6tables -I INPUT -p tcp --dport 22 -j REJECT # 禁用SSH
ip6tables -I INPUT -p tcp --dport 53 -j REJECT # 禁用DNS
ip6tables -I INPUT -p udp --dport 53 -j REJECT # 禁用DNS
ip6tables -I INPUT -p icmpv6 --icmpv6-type echo-request -j DROP # 禁用PING6
ip6tables -I INPUT -p tcp --dport 53 -s fe80::/10 -j ACCEPT # 允许Link Local设备访问DNS
ip6tables -I INPUT -p udp --dport 53 -s fe80::/10 -j ACCEPT # 允许Link Local设备访问DNS
由于是插入规则,规则不能打乱然后把上述命令插入到/etc/rc.local
中,开机自动会生效。
结论
这样就解决了小米路由器 ipv6 端口精确放行的问题,不过需要 ssh 登录,而且手敲 iptables,显得很硬核。不过放行 ipv6 端口也是一时只需,附加的 ip6tables 规则重启就失效了,但规则及其灵活。可以按照上文这一小结进行额外扩展,实现其他额外的放行需求。