对许多 VPN 服务器来说,一块物理网卡就够了,但它也不是放之四海皆准的设计。加密连接到达这块网卡,VPN 进程将其解密,随后内层流量经由一个虚拟接口离开,再抵达本地服务或被路由的 LAN。这能否成立取决于三个条件:目的地在哪里、LAN 是否有回到客户端地址池的回程路径,以及一条共享的物理链路是否提供了你所声称的隔离。回答完这三点,网卡数量自然就定了。

决定它的三个条件

第一个条件是目的地。VPN 主机自身的服务只能经由隧道接口到达,而 LAN 上的主机则需要转发和回程路径。第二个条件就是这条回程路径,因为 LAN 设备必须知道如何到达客户端地址池,或者靠一条路由,或者靠服务器上的地址转换。

第三个条件是隔离。一块网卡意味着每个数据包无论是否加密都共用一条链路,通常也共用同一条策略链,因此依赖独立硬件的隔离主张,单靠一个接口是无法兑现的。这是关于路径的事实,与操作系统如何配置无关。你仍然可以过滤隧道流量,但不能声称拥有一道并不存在的边界。

这三点都与机箱上有几个端口无关。它们关乎路由、地址归属,以及这套设计在多大程度上依赖物理分隔。

当物理区域、独立上行链路、吞吐量或带外恢复通道构成正当理由时,两块网卡仍是合理的选择。这些都是具体需求,值得在任何人为硬件下单之前写清楚。

当服务运行在 VPN 主机上

最简单的情形根本不需要转发。守护进程在隧道接口上接收客户端的数据包并交给本地套接字,应答沿同一接口返回。对主机而言,客户端地址池里的地址就是真实的本地地址。

仍有两件事必须正确:服务必须监听在隧道能够到达的地址上,主机防火墙必须接受从隧道接口进来的流量。两者都能在下面的命令里看到。

ss -lntup | grep -E "5432|8080"
ip -brief addr show
ip route get 10.8.0.6 from 10.8.0.1

把服务只绑定在公网地址上,或误把隧道接口过滤掉,都会产生一种连接:能到达主机,然后死掉。它看起来像 VPN 故障,实际上通常是套接字或防火墙的决定。

当目的地位于 LAN 上

单网卡设计在这里落下了难缠的名声。服务器必须把客户端的数据包转发到 LAN 方向,而 LAN 设备必须把应答送回客户端地址池。要么你在 LAN 上以路由的方式承载这个地址池,要么在服务器上做源地址转换,让应答回到服务器本身。

两种答案都站得住,失败方式却不同。回程路由让目标仍能看到客户端的原始地址,这对日志有利,对假设 LAN 地址的防火墙规则不利。地址转换让 LAN 保持简单,同时向目标隐藏客户端身份。

sysctl net.ipv4.ip_forward
nft list ruleset | grep -A4 'chain forward'
ip route show table main | grep 10.8.0

不对称路径是典型症状:客户端的请求到了,应答从另一台路由器出去,连接在两端都没有报错的情况下超时。在对隧道下任何结论之前,先在两侧抓包。

为什么别名不会造出第二个区域

在同一块网卡上加第二个地址,或者建一个 dummy 接口来模仿第二个端口,改变的东西很少。数据包仍然从同一条物理链路、同一个交换机端口、通常还是同一条防火墙链出去,因此两者之间并不存在新的边界。那是配置上的便利,不是网段隔离。把它当作区域边界,正是隔离主张只活在纸面上的方式。

独立的区域需要路径上存在真正的分隔,而这正是第二块网卡能满足的要求。如果某条规则依赖“面向 VPN 的流量永不与面向 LAN 的流量共享广播域”,那么无论主机怎么配地址,一根网线都无法给出这个性质。

如果某个产品为特定模式记录了多接口拓扑,请遵循该产品的文档,而不是自己发明绕行办法。厂商也会在版本之间改变受支持的拓扑,这也是应当读当前指南、而不是旧向导截图的原因之一。

对照你允许的流量检查布局

列出服务器需要承载的流量类别:客户端到主机、客户端到 LAN、主机到 LAN,以及加密的外层连接。每一类都有源、目的和接口,布局必须同时满足这四类。只处理其中三类的设计,通常就是制造工单的那一个。

然后确认实际的接口和实际的抓包,而不是设计文档里的示意图。下面的命令会打印这两种视图。

ip -brief addr
ip route
tcpdump -ni any udp port 51820 -c 5
tcpdump -ni tun0 -c 5

如果外侧抓包显示加密流量,内侧抓包在隧道接口上显示已解密的流量,而物理网卡同时承载两者,那么一块网卡就完成了工作。如果内侧抓包是空的,问题出在隧道或转发规则上,而不是网卡数量。依据这两次抓包和路由表来定拓扑,下一次改动才有可比的基准。

相关文章