OpenVPN 使用 TCP 而非 UDP

OpenVPN 使用 TCP 而非 UDP

我已成功在 Debian(Raspberry Pi 型号 b+)上设置 OpenVPN 服务器。将协议设置为 TCP 后,它的工作方式完全符合预期(互联网通过 VPN 路由,访问本地网络机器),但是当我将协议设置为 UDP(我认为这对提高速度是有利的)时,我发现我可以 ping 任何主机(IP 地址或域名),我可以 telnet 和 ssh(再次是 ip 地址或域),但当我尝试在浏览器中打开页面时,它似乎建立了初始连接,但从未加载。

您是否知道为什么网页浏览对于 UDP 模式来说会出现问题?

我已经设置了 UFW 来管理 iptables,其主要配置行已添加到before.rules

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# Allow traffic from OpenVPN client to eth0
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
COMMIT

由于 TCP 一切正常,UDP 也几乎正常,所以我认为问题不在于防火墙/iptables,但我也可能是错的。

我的 openvpn 服务器配置是

local 192.168.0.31
dev tun
proto tcp
port 1194
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig 10.8.0.1 10.8.0.2
push "route 10.8.0.31 255.255.255.255"
push "route 10.8.0.0 255.255.255.0"
push "route 192.168.0.31 255.255.255.0"
push "dhcp-option DNS 192.168.0.1"
push "redirect-gateway def1"
push "explicit-exit-notify 3"
client-to-client
duplicate-cn
keepalive 10 120
tls-auth ta.key 0
cipher AES-128-CBC
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn-status.log 20
log /var/log/openvpn.log
verb 1

有人知道为什么可能会出现问题吗?

答案1

这些特定症状(使用 VPN)是相当常见的症状,表明您的路径 MTU 存在问题。

MTU 基础知识

路径 MTU(最大传输单元)是互联网(或任何其他网络)上两个设备之间可以传输的最大数据包。路径上的每条链路都有自己的 MTU,可能与其他链路匹配,也可能不匹配。总路径 MTU 是整个路径上的最低 MTU。

如果您的计算机尝试发送大于路径 MTU 的数据包,数据包会在超出的跳数处被丢弃,数据将永远不会到达。在运行良好的网络中,您的计算机应该会收到错误响应,并知道自动调整 MTU 和/或对后续数据包进行分段。在运行不良的网络中,它可能会被默默丢弃。

路径 MTU(自动)发现是用于自动检测您与 VPN 服务器之间的 MTU 的机制,但是在行为不良的网络上,TCP 比 UDP 更强大,因为 TCP 要求明确的反馈,可以告诉您哪些数据包未到达。


它对 VPN 链接采取这种行为的原因是 VPN 封装头减少了隧道连接的 MTU,并且 UDP 不提供有关丢弃数据包的反馈。

例如,如果您的实际 PMTU 为 1400 字节,则通过 VPN 发送 1400 字节数据包可能需要 1432 字节。通过 TCP 连接,如果您尝试发送 1432 字节数据包,TCP 可以判断它未到达,并将其分段,然后将其作为 1400 字节数据包和第二个 32 字节数据包再次发送(尽管如此,这是一个粗略的简化)。使用 UDP,它会被默默丢弃。然而,在两个都情况下,发送任何小于 1400 字节的数据包都会成功。

这就是 SSH 和 telnet 可以工作而网页浏览却不行的原因。您的 VPN 已将您的 MTU 降低到默认值以下,但您的操作系统尚未意识到这一点,因为错误消息未正确返回或 PMTU 自动发现不起作用。但由于 SSH、telnet 和 ping 都使用非常小的数据包(通常小于 100 字节),如果您的 MTU 从 1400 减少到 1368(1400 - 32),这并不重要,因为它们仍然比限制小得多。SSH 和 telnet 通常一次发送一个字节到一行,外加数据包头。Ping 数据包通常最多 64 字节外加数据包头,同样比任何合理的 MTU(1400+)小得多

Web 浏览最初之所以会连接,是因为 DNS、TCP SYN/ACK 数据包和 HTTP 请求通常都远小于 1400 字节,但是一旦网站尝试发送实际的网页,它就会使用全尺寸数据包,然后在传输过程中被悄悄丢弃。


解决问题

有一种简单(作弊)的方法,还有一种需要弄清楚问题到底是什么的方法。

作弊方法是手动将 MTU 调低很多 - 例如调低至 1000,这样即使 VPN 的 MTU 降低,所有内容也能容纳进去。这本身就是一个不错的测试,可以查看 MTU 是否是问题所在。

更好的方法是找出问题所在,然后解决它。MTU 自动发现问题可能是由于糟糕的服务器或 ISP 引起的,对此您无能为力,或者是本地防火墙/配置问题,您可以修复这些问题。可能是您的 OpenVPN 路由和防火墙规则不允许 ICMP 错误消息返回到您的机器。

一种折中方法是找出真正的最大 MTU 并手动设置 - 您可以从 1000 字节等较小的值开始,然后逐步向上找到可行的最高值。基本上,使用 UDP 连接您的 VPN,然后使用命令通过 VPN ping 某些东西ping -f <server address> -l <packet size>,并向上增加数据包大小,直到它停止工作 - 出现超时或错误。

相关内容