由于绿联nas的ugos pro系统疑似是默认开启了ipv6隐私扩展,导致nas的ipv6地址后64位是在每次nas重新获取ipv6地址时随机生成的,所以说博客站里提到的按照地址后64位进行防火墙规则匹配的方法失效了。找了绿联的客服反馈了目前也没有下文。目前针对这个问题,有几种变通方法,但都不太完美。
- 禁用掉路由器的ipv6防火墙,但这样做不安全
- 防火墙开放所有下级设备的相同端口,同样不够安全
- 修改ugos pro的配置文件,使之获取基于eui64的固定64位后缀的ipv6地址,可参考绿联 NAS 配置基于 EUI64 的 SLAAC IPv6 地址 | Zs’s Blog,但是这个方法日后随着系统更新可能失效,且与nas系统原有的网络配置可能冲突。对于像dh4300plus这种不能自行刷机的设备,使用root权限修改系统配置还有导致变砖的风险。
- 如果只是想自己外网访问nas,在其他支持eui64 ipv6的同网段设备上(或者路由器)设置一个vpn,比如说wireguard,然后为这种设备开放端口,通过vpn访问局域网内的nas。但是想要用这个方法开放nas的bt端口是行不通的。
- 禁用路由器的slaac地址下发,仅开启dhcpv6地址下发方式。但是这样做的代价是安卓设备在没有root的情况下不能获取ipv6地址(不知谷歌的开发者是怎么想的,一直都拒绝支持ipv6,有人说是为了隐私,但是为什么不加一个开关?近年也有说法说是要支持了,几个厂商的定制安卓也支持了,不过我目前手上的安卓设备以及鸿蒙2.0设备还没有支持的)。且本人未测试ugos pro的默认网络配置是否支持dhcpv6。
- 路由器实时获取nas的ipv6地址,然后设置cron定时任务,运行iptables规则。有关如何获取nas的地址,一种是nas上设置ddns,路由器通过解析ddns域名获取地址,但是在路由器上有解析域名失败的风险,且地址更新的延迟较高。另一种是通过ipv6邻居来获取,这样应该可以理论上把地址更新的延迟缩短到crontab任务的间隔。考虑到即便没有更新地址的延迟,即采用禁用防火墙的方法,nas与外网设备重建链接也需要时间,因此crontab任务的时间间隔影响应该是不大的。下面就介绍这种方法。
在/etc/storage或者其他持久化目录创建脚本:
|
1 2 3 4 5 6 7 8 9 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 |
#!/bin/bash # MAC address of the PC MAC="6c:1f:f7:8d:5e:0c" # Ports to open (comma separated) PORTS="36789,16881" # File to store the last applied IPv6 address LASTIP_FILE="/tmp/user_last_ugnas_ipv6" # Get the current REACHABLE IPv6 address (pick the first one) cur_ipv6="$(ip -6 neigh show | grep -i $MAC | grep REACHABLE | grep '^240e:' | awk '{print $1}' | head -n 1)" # Exit if no IPv6 address found [ -z "$cur_ipv6" ] && exit 0 # Read last IPv6 address [ -f "$LASTIP_FILE" ] && last_ipv6="$(cat $LASTIP_FILE)" || last_ipv6="" # If same as last time, do nothing if [ "$cur_ipv6" = "$last_ipv6" ]; then exit 0 fi # If previous IP exists, delete rules for old IP if [ -n "$last_ipv6" ]; then ip6tables -D FORWARD -d "$last_ipv6" -p tcp -m state --state NEW -m tcp -m multiport --dports $PORTS -j ACCEPT 2>/dev/null ip6tables -D FORWARD -d "$last_ipv6" -p udp -m state --state NEW -m udp -m multiport --dports $PORTS -j ACCEPT 2>/dev/null fi # Add new rules for the current IPv6 address ip6tables -A FORWARD -d "$cur_ipv6" -p tcp -m state --state NEW -m tcp -m multiport --dports $PORTS -j ACCEPT ip6tables -A FORWARD -d "$cur_ipv6" -p udp -m state --state NEW -m udp -m multiport --dports $PORTS -j ACCEPT # Save the current IPv6 address for next run echo "$cur_ipv6" > "$LASTIP_FILE" |
代码有四个变量需要修改:MAC,PORTS,LASTIP_FILE,第十一行的240e,顾名思义分别是nas网络接口的mac地址、需要开放的端口、保存ipv6地址的状态文件、公网ipv6地址前四个字符(电信240e,联通2408,移动2409,广电240a,这四个字符一般都不会变,目的是匹配到公网地址,防止匹配出了内网地址)。代码的基本逻辑是先用ipv6邻居检测nas的地址,然后对比状态文件的ipv6地址和实时ipv6地址,如果发现地址变了就删掉以前的ipv6地址设定的iptables规则,并设定新的规则,保存新地址,如果没有变就什么都不执行。
代码里面的iptables规则用到了一个参数-m state –state NEW,目的是仅允许新发起的连接的数据包被转发,一般来讲,Linux防火墙会自动允许同一连接的后续数据包(执行ip6tables -L FORWARD -n –line-numbers | grep -i ‘established\|related’,如果显示类似1 ACCEPT all ::/0 ::/0 state RELATED,ESTABLISHED则说明会自动允许),所以这个参数不会影响到外网访问,实测也是如此。实在不放心删掉这个参数即可。
然后在padavan webui的系统管理的服务里面编辑cron定时任务,这里我是设定为3分钟执行一次,也可以改成其他的频率。
|
1 |
*/3 * * * * /bin/bash /etc/storage/user_update_ugnas_ipv6_fw.sh |
配置好后重拨了一下宽带,实测本方法有效。