时效性提醒:本文首次编写发布于4 年前。
旁路由是一种homelab常见的需求,主路由用硬路由确保稳定,比如用Mikrotik的RouterOS路由器作为主路由,旁路由使用OpenWrt作为软路由,实现广告过滤和隧道等高级功能,这些功能往往都无法硬件加速,需要消耗大量CPU完成,x86的高性能软路由是很合适的选择。比起使用二级路由,可以减少在旁路由上的一次NAT(仅对于IPv4),提高利率,也便于主路由进行管理。
本文提出了一种整活之余有些实用性的特殊旁路由方案,或者也可称为IPv4不NAT的二级路由方案。
本文环境信息:
主路由RouterOS,旁路由OpenWrt,需要主路由具有3个网口(对于硬路由很容易满足),旁路由至少具备双网口,假设其都为千兆网口; 为了使用IPv6二级路由,运营商给的IPv6前缀至少需要为/63;(常见的/56、/60都可满足,但如果给的是/64,虽然或许也能实现功能,但需要不同的设置) 主内网(全功能)网段:192.168.10.0/24,辅助内网(备用/直连)网段:192.168.88.0/24
0x01 传统旁路由设置
传统的旁路由设置只针对IPv4,旁路由只需要一根网线连接内网和旁路由的LAN,旁路由的WAN空置。主路由LAN口IP为192.168.10.1/24,旁路由LAN口IP为192.168.10.2/24,在内网DHCP服务器设置中设置网关为192.168.10.2(DHCP服务器可运行在主路由或旁路由上,但只能有一个),然后在旁路由中设置网关为192.168.10.1。
这样所有客户端都会使用192.168.10.2作为网关,将出口的IP封包发到旁路由上,旁路由因为开启了ip_forward(路由器都会开启),会对这些封包进行转发:由于在旁路由上设置了192.168.10.1作为网关,于是旁路由就会将这些封包直接转发到192.168.10.1的主路由上(传统旁路由的关键就在于,由于是LAN to LAN转发,所以不会匹配防火墙中LAN to WAN的masquerade规则,即不会进行我们常说的路由器NAT)。由于封包在旁路由上进行了转发,隧道软件就可以通过防火墙NAT表中的规则对这些封包进行处理(比如redirect和tproxy),满足我们使用旁路由的需求。
在一般链接的回程(下载)时,经过主路由NAT后的入口封包的目标IP为客户端的内网IP,直接通过交换机到达客户端,无需再经过旁路由,所以理论上是可以对外网跑满双向千兆的。
0x02 传统旁路由的问题
第一个问题就是IPv6,IPv6没有单独的网关选项,对于SLAAC而言(至今Android只支持SLAAC,不支持DHCPv6),如果一台机器进行了RA(路由宣告),让客户端获得了前缀,那么客户端就会认为其是网关。由于公网IPv6前缀由PPPoE获得,所以必然是主路由进行RA,也就自动成为了所有客户端的IPv6网关,无法再指定旁路由为网关。
一个常规的IPv6 RA包
从另一个角度讲,IPv6要求所有设备(Node)必须从Router和Host这两种角色中二选一,而旁路由就恰恰是一个设备既作为Router,又作为Host。
实际上,IPv6也没必要使用旁路由,由于通常情况下IPv6不使用NAT,路由器在这里做的仅仅是转发而已,我们可以放心的使用IPv6二级路由。
另一个问题是千兆瓶颈的问题,这个千兆瓶颈只对于非直连流量(比如隧道流量)存在,即经过隧道的流量,上行和下行的速度总和 无法超过1Gbps,这是因为隧道流量返程也需要经过旁路由。对于直连流量而言,如文章第一节所述,由于返程不需要经过旁路由,所以不存在千兆瓶颈,上下行速度总和可以达到2Gbps,即跑满。不过这个问题通常不会带来影响(啥公网隧道能千兆对等),但若能一并解决了也好。
0x03 本文的魔改二级路由方案
为避免混淆,以下使用「软路由 」代指我们原本逻辑中的旁路由 (即那台OpenWrt的软路由)
这是一种双网口、IPv4旁路由+IPv6二级路由的方案,这种方案实际上更接近于标准的二级路由,但通过一些魔改,让IPv4变成旁路由模式。
拓扑如下:
图中主路由 的bridge 代表主内网,具有软路由提供的高级功能;bridge_alt 代表辅助内网,此处仅用于软路由与主路由间的通信,也可接入一个交换机作为直连/备用内网,其不具有软路由提供的高级功能,但能在软路由故障时继续提供标准(直连)的上网功能。如果主路由上不需要扩展辅助内网,也可不为辅助内网创建bridge,使用一接口代替。
这里只列出了IPv4部分的参数。IPv6部分同标准的IPv6二级路由,但要注意,IPv6的RA和DHCP Server要运行在bridge_alt接口上(见下文)。
如果你的主路由的具有硬件交换机且还有很多未用端口,那便可以省掉“主内网 交换机”,这样旁路由就是通过两根线连接了主路由,但并不会成环。
下面开始IPv4部分的详细配置介绍:
在主路由上,基于路由器模式的出厂设置(如Home AP Dual等),进行以下修改:
首先新建个Bridge,名称为“bridge_alt”:
2. 添加需要的接口到bridge_alt 中,这里我除了必要的有线端口ether1 外,还添加了机器自带的两个wlan,作为备用网络热点(主内网的wlan由独立的AP提供):
3. 为bridge 设置IP:192.168.10.1/24 ;为bridge_alt 设置IP:192.168.88.1/24 :
4. 为bridge_alt 设置分配192.168.88.0/24 的DHCP服务器;如果主内网也由主路由提供DHCP服务,则为bridge 设置分配192.168.10.0/24 的DHCP服务器,并设置网关为192.168.10.2 (下图未展示):
5. 在Interface list中,将bridge_alt 设置为LAN :
然后将软路由WAN 口与bridge_alt 的接口通过网线连接(本文中为ether0 ),然后你应该能看到软路由的WAN口从主路由获取了IP:
(你可能会疑惑:这不是二级路由的状态吗?别急,下面我们就关闭它的NAT)
下面我们在软路由中进行设置 (类似的,基于OpenWrt的默认设置):
6. 设置软路由的LAN 口IP为192.168.10.2 ;如果在主路由上设置了主内网的DHCP服务,则要关闭软路由LAN的DHCP服务(下图未展示)
7. 最为关键的一步,到防火墙中关闭WAN 区域的“IP动态伪装 ”,也就是masquerade,即我们常说的NAT:
然后将根据拓扑图,将软路由的LAN 、主路由的bridge 和主内网的设备 都接到交换机上,IPv4的设置就完成了。
关于IPv6的配置,和标准的IPv6二级路由相似,只是RA和DHCPv6 Server的接口设置有所不同,这部分网上有非常多很好的教程,比如:https://wu.renjie.im/blog/network/ros-dhcpv6/zh-cn/ ,下面仅写出在本文设置中需要注意的点。
在主路由 上,IPv6的地址设置(包括了RA)和DHCPv6的设置中,需要在且仅在bridge_alt 接口上进行设置,而不应 对bridge进行任何设置。换句话说,在IPv6下,主路由不会使用主内网bridge ,bridge 的IPv6 RA和路由完全由软路由负责,bridge 作为bridge_alt 的下级路由,形成标准的IPv6二级路由。
0x04 后记
本文的方法与普通二级路由的最大区别,其实就是对于IPv4:①在二级路由器(本文中的软路由)上关闭了LAN to WAN的masquerade NAT;②在主路由上连通了二级路由的LAN。 从而达到了类似旁路由的效果(旁路由就是为了少一层NAT)。
至于为什么可以在关闭二级路由器的NAT,不妨思考一下我们为什么在路由器上需要NAT:如果我们有一个连接上级网络的普通路由器,并关闭了NAT,那么我们发出的包其实还是可以正常的被送到远端的服务器,但由于包中的源IP地址还是我们客户端的内网IP地址,无法通过我们的内网IP向我们回应(其实通常直接就不会被远端服务器的防火墙接受)。而masquerade NAT就是一种特殊的src nat,其永远都会使用路由器本机地址,作为IP封包源地址的替换,从而让远端服务器的回应包能被正确发到路由器上,再由路由器转发给客户端。
但在本文的方法中,首先在我们的包通过二级路由器直接转发给主路由后,由于主路由是带有NAT的,远端服务器的回应包会正常的到达主路由,然后主路由在转发回应包时,由于我们配置了上面的② ,回应包可以直接发给客户端,无需经过二级路由器,也就无需二级路由器的NAT,正常的完成了一次往返的通信。
最后,本文的方法更多是整活向的。无论是直接使用单路由,还是普通的二级路由,甚至用传统旁路由方式并直接关闭IPv6,其实也没什么不好(毕竟2022年目前ISP和CDN的优化还是针对IPv4为主,很多地方依然是“关闭IPv6以提升上网体验”)。不过homelab的一大乐趣之一就是折腾各种非标准的方案和配置,本文也算是提出了一种旁路由+正常IPv6的解决方案,如果各位读者认为有改进的地方或漏洞,也欢迎在下面留言。