背景
通常来说,如果我们划分了另一个网段,流量是需要通过网关来进行路由的。例如 LAN 网段为 172.20.0.0/24
,然后我们在家庭 PVE 服务器上创建了一个用于虚拟机的 172.20.1.0/24
网段,其中 PVE 服务器的网卡的 IP 为 172.20.0.3
,为了能够使得 LAN 的设备能直接访问虚拟机的 IP 段 172.20.1.0/24
,就需要在网关设备上添加一个静态路由,指向 172.20.1.0/24
,如下图。
诚然,这样做确实可以实现 LAN 的设备能直接访问虚拟机的 IP 段而不需要设置代理,但是这样做有一个缺点:所有访问虚拟机的流量都需要经过网关处理!这就导致了网关的 CPU 负载会变高,而且网关的网络带宽也会被内网访问虚拟机的流量占用。
注意到 PVE 服务器的网卡的 IP 为 172.20.0.3
,和 LAN 位于同一网段,有没有什么办法可以直接让 LAN 的设备访问 172.20.1.0/24
段时,直接到达 172.20.0.3
而不要经过网关?
答案是有的,那就是静态路由主动推送。这个功能在 OpenWRT 上可以通过直接在 LUCI 上设置来实现,而在其他 Linux 发行版上可以通过修改 /etc/dnsmasq.conf
来实现。
实现方法
OpenWRT LUCI
如下图所示,打开 接口 – LAN – 修改 – 高级,填入两个 DHCP 选项
121,172.20.1.0/24,172.20.0.3,172.20.2.0/24,172.20.0.3,172.20.70.0/24,172.20.0.3,172.20.50.0/24,172.20.0.3
249,172.20.1.0/24,172.20.0.3,172.20.2.0/24,172.20.0.3,172.20.70.0/24,172.20.0.3,172.20.50.0/24,172.20.0.3
这将配置推送 172.20.1.0/24
段,网关重设为 172.20.0.3
,推送 172.20.2.0/24
段,网关重设为 172.20.0.3
,…, 推送 172.20.50.0/24
段,网关重设为 172.20.0.3
。
其中代码121指的是标准的 RFC Classless Static Route Option,249 是微软私有的无类域间路由推送协议。两者在 功能上一致,后者主要用于支持 Windows 系统(Windows XP和Windows Server 2003只支持DHCP选项249,而其他操作系统可以支持DHCP选项121),因此内容上也应该保持一致。
注意:受 DHCP 包的 255 字节大小限制,最多只能配置有限个静态路由推送。如果你的路由数量超过了限制,请设法缩小掩码缩减路由数量。
Linux DNSMasq
修改 /etc/dnsmasq.conf
dhcp-option=121,172.20.1.0/24,172.20.0.3,172.20.2.0/24,172.20.0.3,172.20.70.0/24,172.20.0.3,172.20.50.0/24,172.20.0.3
dhcp-option=249,172.20.1.0/24,172.20.0.3,172.20.2.0/24,172.20.0.3,172.20.70.0/24,172.20.0.3,172.20.50.0/24,172.20.0.3
效果
配置完毕后保存,然后重新连接电脑网络,命令行输入 ROUTE PRINT | FINDSTR 172.20.
将能看到我们推送的路由:
进行路由跟踪
修改前,流量先经过默认网关 172.20.0.1
再转发到 PVE 172.20.0.3
修改后,发现流量确实不再经过默认网关 172.20.0.1
而是直达 PVE 172.20.0.3
:
局限性
- 受 DHCP 包的 255 字节大小限制,最多只能配置有限个静态路由推送。如果你的路由数量超过了限制,请设法缩小掩码缩减路由数量。
- 已知 Android 不会接受推送的静态路由,因此这个方法 Android 设备没有效果。此外,Android 设备亦不会响应 ICMP Redirect,可以说安卓的网络栈就是纯纯的废物。
- IPv6 不支持此种方法