华硕 RT-AC86U 2900M双频千兆无线路由器使用总结(设置|配置|数据|防火墙)
-
摘要来自:
-
摘要来自:一夜暴富尧
-
摘要来自:2019-01-16
【什么值得买 摘要频道】下列精选内容摘自于《一波三折的校园网IPv6 x 华硕 AC86U》的片段:
这一段较为硬核,需要一定的专业知识,可以跳过不影响你使用。方便好奇的同学了解背后的原理,并根据自己的设备因地制宜的修改设置。
接下来我会解释上面这个脚本在让路由获取IPv6地址的部分过程中都做什么,为什么这样做。在我的网络环境里,只有把路由器设置为 IPv6 passthrough 的时候路由器能正确获取 IPv6 地址。所以需要弄清楚这个模式做了什么操作。好在华硕固件是开源的,可以直接从官网下载。下文的讨论基于写这篇文章时能拿到的最新固件 3.0.0.4.384.32797 的源码。可以到官网支持页面选择操作系统为“其他”就可以看到源码下载链接。由于梅林是基于华硕固件源码的小改版本,也可以直接看梅林仓库的代码。
拿到了源码,直接搜索 PASSTHROUGH 关键字,发现启动 IPv6 Passthrough 的代码在 asuswrt/release/src/router/rc/wan.c下面,快速过一遍 IPv6 相关的代码,发现 IPv6 的设置主要有以下几个方面。
首先是开启IPv6,设置了accept_ra, forwarding一些字段。这些字段的意义都可以 Google 到。比如下面代码中设置的字段是互斥的,一个为1另一个就得为0。这两个字段决定了系统是工作在路由状态还是工作在主机状态。ra 是 router advertisement 的缩写,是 IPv6 网络用来自动配置路由的协议。我们想让路由器在LAN的状态像主机一样获取到 IP,就需要将路由器设置为主机状态,请求路由配置。
case IPV6_PASSTHROUGH:
#endif
ipv6_sysconf(wan_ifname, "accept_ra", 1);
ipv6_sysconf(wan_ifname, "forwarding", 0);
代码中还有很多设置IPv6 相关配置的地方, 分散在各处,就不一一列出来了。总结下来就是分别在 WAN 口 和 LAN 口设置下面的相关参数。相关的代码可以在lan.c 和 wan.c 中找到。下面这段脚本就是用来设置对应参数的。
# enable IPv6 on eth0
echo 0 > /proc/sys/net/ipv6/conf/eth0/disable_ipv6
echo 2 > /proc/sys/net/ipv6/conf/eth0/accept_dad
echo 2 > /proc/sys/net/ipv6/conf/eth0/dad_transmits
echo 1 > /proc/sys/net/ipv6/conf/eth0/accept_ra
echo 0 > /proc/sys/net/ipv6/conf/eth0/forwarding
# see lan.c config_ipv6
echo 0 > /proc/sys/net/ipv6/conf/br0/disable_ipv6
echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6
echo 0 > /proc/sys/net/ipv6/conf/default/disable_ipv6
echo 2 > /proc/sys/net/ipv6/conf/br0/accept_dad
echo 2 > /proc/sys/net/ipv6/conf/br0/dad_transmits
# set_default_accept_ra
echo 1 > /proc/sys/net/ipv6/conf/all/accept_ra
echo 1 > /proc/sys/net/ipv6/conf/default/accept_ra
echo 0 > /proc/sys/net/ipv6/conf/all/forwarding
其次是开启relay功能,顺着 wan.c 再往下看,到了配置 IPv6 passthrough 的代码
case IPV6_PASSTHROUGH:
start_6relayd();
/* fall through */
#endif
case IPV6_NATIVE_DHCP:
start_dhcp6c();
这段代码做了两步操作,第一步是启动了 6relayd ,可以确认华硕是用 6relayd 做的中继,据论坛用户表示该项目不是很稳定,并且在我的网络环境无法实现中继;第二步是启动了 DHCPv6 客户端,为特定的端口分配IP。具体代码实现太长,这里贴出一小部分
int
start_dhcp6c(void)
{
char *wan_ifname = (char *) get_wan6face();
char *dhcp6c_argv[] = { "odhcp6c",
"-df",
"-R",
"-s", "/tmp/dhcp6c",
"-N", "try",
NULL, NULL, /* -c duid */
NULL, NULL, /* -FP len:iaidhex */
NULL, NULL, /* -rdns -rdomain */
NULL, NULL, /* -rsolmaxrt -r infmaxrt */
NULL, /* -v */
NULL, /* interface */
NULL };
int index = 7;
struct duid duid;
char duid_arg[sizeof(duid)*2+1];
char prefix_arg[sizeof("128:xxxxxxxx")];
int service;
...
可以看到路由器使用 odhcp6c 为自己在 WAN 口上获取IP。这个时候可以脑补这段代码获取参数值,这样比较麻烦且容易出错,所以才出现了配置部分一开头的使用ps | grep odhcp6c 查看参数的trick。经过多次验证参数是不变的,所以可以通过这个方法获取启动 odhcp6c 客户端的参数表。有一点主要注意的是默认情况下我们是为 WAN 口绑定 IP,而本文中的网络情况是 WAN 口 与 LAN 口已经被桥接在一起了,在 IPv6 的层面已经没有了内外网的区分。所以应为网桥,也就是 br0 绑定IP。
最后还需要调整防火墙设置,因为当路由器关闭了 IPv6 功能后,会默认过滤丢弃掉所有的 IPv6 数据包,所以还需要设置对应的防火墙规则。设置防火墙规则的代码散落在各处,找起来十分麻烦,且很难找全,所以祭出查看 odhcp6c 参数的方法,通过运行ip6tables -L 查看 filter 表中所有的规则,然后手写一份一样的出来就可以啦,于是就有了上面那一大长串 IPv6 的过滤规则。
最终,通过看源码可以梳理出来路由器在设置 IPv6 passthrough 后的行为如下
修改系统设置,启用所有端口的 IPv6 功能
添加防火墙规则,允许 IPv6 数据包通过路由器
开启 DHCPv6 客户端,为路由器申请IP地址
所以按照这些步骤,就可以自己手动设置桥接后的路由器通过HDCPv6服务申请IPv6 地址,还顺便复习了一波计算机网络的知识2333。