标签: openwrt

  • “双网线”旁路由之“完美”解决IPv6和千兆瓶颈问题

    “双网线”旁路由之“完美”解决IPv6和千兆瓶颈问题

    时效性提醒:本文首次编写发布于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等),进行以下修改:

    1. 首先新建个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下,主路由不会使用主内网bridgebridge的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的解决方案,如果各位读者认为有改进的地方或漏洞,也欢迎在下面留言。

  • ESXi + openwrt折腾软路由和万兆软交换机的一些小坑

    ESXi + openwrt折腾软路由和万兆软交换机的一些小坑

    时效性提醒:本文首次编写发布于6 年前。

    Why 软交换机?

    因为需要部署万兆电口的内网,然而目前的万兆交换机多为光口,加上光模块成本很可能得近2000。

    我希望这两条紫色的线是万兆的

    故想到用一台几百块的x86机器+一张几百块的intel x540双万兆电口网卡,在OS中桥接,做成软交换,同时也桥接若干板载的千兆网口,用来与原有的千兆有线内网连通。再同时,如果在这台机器上做虚拟化,上面的虚拟机也可以享受到万兆网络。事实证明,我还是simple young naive

    ESXi vSwitch的坑

    ESXi vSwitch即“虚拟交换机”,如果不部署vCenter server的话只能创建“标准vSwitch”,然而这确实是个“虚拟机的交换机”,对于物理端口并没有交换功能,就算你给vSwitch添加多个物理端口作为“上行链路”,也只是负载均衡、故障转移的bond,而非软交换机的bridge

    据我所知,ESXi的单机WebUI并没有任何能创建物理端口bridge的地方,而为了一个交换功能去装几十个G的vCenter server有些舍本逐末,所以就有了让VM实现交换的折中方案。

    VM负责交换时不同路径的效率问题

    这里使用的是的E3-1220L,这是一颗20w TDP、2C4T、2.2~3.4GHz的处理器,作为基准。

    这里把两张万兆网卡都直通给了VM,一个openwrt的VM。

    首先是场景1:标准的软交换的路径,效率尚可:

    外部设备A <--> 万兆网口1 <--> VM <--> 万兆网口2 <--> 外部设备B

    但如果是下面这种场景2,外部设备到路由器上另一个VM时,效率就感人了:

    外部设备A <--> 万兆网口1 <--> VM <--> 虚拟网卡 <--> ESXi虚拟交换机 <--> 虚拟网卡 <--> 目标VM

    经测试,这种情况下CPU 100%只能跑到5Gbps左右。

    而如果两张万兆网卡不使用直通的方式,场景2的效率会少很多,但场景1由于要多经过两张虚拟网卡和ESXi虚拟交换机,效率会更感人。

    解决方案的话,目前考虑用Proxmox VE替代ESXi,有待测试。

    openwrt镜像种类的选择

    x64的openwrt镜像,有和硬路由器上类似的SquashFS + overlay的根分区,或者是直接一个ext4的根分区,这里建议选择第二种,不然扩容比较麻烦。

    例如图中的第一个