端口转发与 VPN 访问:数据包实际去了哪里
端口转发只改写目的地址就到此为止;VPN 则先把数据包包起来。看看两者各自改变哪一层,以及这对 HTTPS 意味着什么。
两种设计,同一个 HTTPS 应用,数据包在两者中走的路径不同。端口转发改变数据包被送达的位置,其余部分原样不动。VPN 先把该数据包装进另一个数据包,因此应用的监听端看到的源地址不同,最大有效载荷也更小。人们争论的加密在两种情况下都存在,因为应用仍然是 HTTPS;不同的是谁能够建立连接,以及中间的网络能观察到什么。这一区别解决了大多数实际问题。
DNAT 规则只改写目的地址就到此为止
在 Linux 网关上,发布一个服务意味着 nat 表 PREROUTING 链中的一条规则,或 nftables 中的等价规则。规则匹配公网地址和端口,然后把目的地址改写为应用的私有地址。源地址、源端口和载荷都不受影响,conntrack 记录映射,使返回的应答在出去时被反向改写。这一行为就是 RFC 3022 中描述的传统地址转换模型。
sudo iptables -t nat -A PREROUTING -d 203.0.113.10 -p tcp --dport 443 \
-j DNAT --to-destination 10.20.30.40:443
sudo iptables -t nat -L PREROUTING -n -v
sudo conntrack -L -p tcp --dport 443
应用的监听端永远不会知道连接是通过转换到达的。它看到客户端的真实源地址,这对访问日志和速率限制很有用,并且因为 conntrack 反转映射而向私有地址应答。这条路径上没有任何解密或重新加密:TLS 仍然运行在客户端和应用自己的证书之间。
这条规则也决定了你之后会遇到的故障模式。如果网关转发,但应用主机没有 回到客户端的路由,应答会带着错误的源地址发出,握手就会卡住。如果第二条规则先匹配,顺序决定结果,而 iptables -t nat -L -n -v 会显示计数器,证明是哪条规则拿走了数据包。
隧道在监听端看到之前先把数据包包起来
VPN 根本不发布应用。客户端构造一个外层数据包,目的地址是网关的公网地址,把内层数据包加密在里面,网关解密并把内层数据包路由到私有目的。使用 WireGuard 时外层传输是 UDP,通常在高位端口;使用 OpenVPN 走 TCP 443 时,外层数据包在观察路径的人看来就像 TLS。
在隧道内,内层数据包保留私有地址:客户端的隧道地址,比如 10.8.0.6,以及位于 10.20.30.40 的应用。因此监听端看到的源来自隧道地址池,每个客户端共用那个网关作为下一跳。VPN 背后的访问日志常常显示网关而不是用户,原因正在于此,除非网关保留了原始源地址。
封装要占用报头空间,而这是机制层面上唯一有可测量后果的差异。外层 IP 报头加上 UDP 再加上 WireGuard 自己的报头,会吃掉路径的 MTU,所以大包必须分片,或者内层 TCP 栈必须收紧 MSS。在转发路径上能正常工作的传输,遇到中间设备丢弃本应告知更小 MTU 的 ICMP 时,可能在隧道上卡住。
ip route get 10.20.30.40
ping -M do -s 1400 10.20.30.40
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
暴露面由入口决定,而不是由加密算法决定
两种设计都终止在同一个 TLS 监听端,因此都继承同一张证书、同样的协议版本和同一个应用登录。变化的是谁被允许发起握手。使用公网端口转发时,任何能到达 203.0.113.10:443 的主机,在应用授权被检查之前,就已经得到 TCP 握手和 TLS ClientHello。只通过隧道访问时,监听端只能从网关路由进隧道的地址到达,陌生人的 SYN 在网关策略处就被丢弃。
这一区别关乎可达性,而不是机密性。被转发的 HTTPS 服务并不是明文,VPN 也不能免除应用认证:隧道准入回答的是设备能否向这个网络发送数据包,而文件应用回答的是用户能否读取文档。把两者混为一谈,就会得到一条授予整个局域网的 VPN 和一个只用共享密码的应用。
要分别检查监听端和策略,因为两者都可能比你想象的更宽:
sudo ss -ltnp 'sport = :443'
sudo nft list ruleset
openssl s_client -connect 203.0.113.10:443 -servername files.example.com </dev/null
如果 ss 显示监听端绑定在 0.0.0.0 上,那么应用可以从路由和防火墙策略允许的任何地方到达,端口转发只是入口之一。绑定到私有地址,或者在防火墙中限制源地址范围,是与选择 VPN 不同的决定,而正是这个决定真正缩小了暴露面。
测量路径,而不是标签
当有人声称转发更快时,诚实的比较要保持其他条件不变:同一个客户端、同一个接入网络、同一个文件、同样的 TLS 配置、同一个应用主机。每条路径跑两次传输,记录总时间、失败次数和响应性,而不是一个无关的测速结果。
curl -sS -o /dev/null -w '%{time_connect} %{time_appconnect} %{time_total}\n' \
https://files.example.com/report.pdf
mtr -rwc 20 203.0.113.10
mtr -rwc 20 10.20.30.40
这些数字把连接建立与传输时间分开,这一点很重要,因为两条路径通常在往返时延和 MTU 上不同,而不是在加密开销上不同。两种设计中 TLS 工作都发生在端点,隧道则增加封装、不同的路由,可能还有更繁忙的网关。如果隧道路径更长,或者它的网关负载更高,差异属于路径,而不属于“加密”这个词。
选择服务真正需要的入口策略,然后判断测出的差异是否值得改变它。公网端口转发适合面向开放互联网的服务,并配合源地址限制、及时更新的 TLS 和前置监控。只通过隧道访问适合用户已经登记的内部工具,前提是网关路由和应用权限都比整个局域网更窄。
在宣布设计完成之前,确认四件事:监听端绑定在哪个地址、哪条规则或路由放行数据包、从客户端真实地址出发的返回路径是否正常、大载荷能否通过 MTU。每一项在上文都有对应命令,而且没有任何一项能用“安全”二字或带宽图表回答。