两个只差一行的配置,在同一台主机上启动第二个客户端的那一刻就会表现不同。一个带 nobind,接受内核分配的任何本地端口;另一个保留 1194,第二个实例就会因为地址已被占用而退出。这一行决定由谁选择源端口,进而决定该配置能否与机器上的其他任何东西共存。三个问题就能定下来,而第一个问题在你看后两个之前就已经回答了大多数配置。

nobind 实际跳过了什么

默认情况下,客户端在拨号前绑定一个本地套接字,除非配置另有说明,本地端口是 1194。 nobind 去掉这项预留,于是协议栈在连接时分配一个未使用的端口。这是例外而非默认,没有这一行的客户端会占住 1194,正因如此,未固定的第二个实例才会冲突。大多数随附的客户端配置都因此带有这条指令,而示例文件做了某件事,并不等于机制默认如此。

不变的是远端。服务器仍按配置所述监听,配置中的目的端口仍是目的端口。动态源端口只改变你自己套接字的回程地址,对服务器的套接字毫无影响。

它也不隐藏任何东西。你的公网地址取决于路径的转换,数据包仍穿过本地网络,运营该网络的人仍能看到一条流。 nobind 既不是隐私功能,也不是绕过防火墙的手段。

决定它的三个条件

一个问题决定另外两个,所以在动手修改之前先回答它。如果对端向外拨号,其余问题只是在细化一个已经作出的决定。如果它接受入站连接,再怎么调整本地端口也无法让它可达。

这个对端会发起连接吗? 如果它向外拨号,动态源端口无害且通常更可取,因为回应会沿同一条流返回。如果它等待入站连接,动态端口会让它不可达,除非前面有东西发布了该端口。这一个答案就把所有客户端配置与所有服务器配置区分开来。

路径会按源端口过滤吗? 为某个已知端口写死的严格规则要求显式指定本地端口,配置里应记录它满足哪条规则。大多数网络只按目的过滤,所以这个条件比第一个更少见。在适用之处,它优先于动态端口的偏好。

多个实例会共用主机吗? 一个固定端口无法服务其中两个,而重启的实例可能发现 1194 仍处于关闭状态。动态端口消除了这种冲突,其他什么都不用改。如果这个问题你没把握,就假定会,并让内核去选。

固定端口才是正确答案的场合

有些网络同时按源端口和目的过滤,因此运维人员可能写了只放行来自某个已知端口的流量的规则。这时固定本地端口才是对的,配置里应写明它满足哪条规则的注释。为了与服务器端口对称而固定并不是理由,因为这两个数字彼此无关。如果固定只是因为模板里有,就删掉它。

否则固定端口会买来麻烦: 一台机器上的两个客户端不可能同时占住 1194,第二个会失败,错误指向端口而不是配置。快速重启的容器会撞上同一堵墙。修复办法就是随附配置里本来就有的那条指令。

服务器与客户端并不对称

OpenVPN 2.6 手册 把 nobind 与 lport并列,这就是一句话的论证:一个选项说由内核选,另一个说由你选。动态本地端口只对向外拨号的对端有效,因为应答方无法事先知道端口。也正因如此,把客户端配置复制到服务器上,只会得到一个没人能连上的监听者。

在有多块网卡的主机上,地址是与端口分开的决定。绑定特定本地地址和绑定特定端口是两项不同的设置,而有两条上行链路的主机通常会同时固定两者。两项都固定的客户端,白白承受了同样的僵化。

总结与安全无关,而与角色有关:拨号方可以对自己的源保持灵活,应答方不能。两种选择都不改变对端对你身份的了解。这也是为什么这条指令出现在客户端示例中,而几乎从不出现于服务器示例。

验证内核选中的端口

连接之后要读套接字而不是配置文件,因为配置表达意图,套接字才说明实际发生了什么。值得记录的事实是本地端口、远端端点,以及是否还有东西在监听。在 Linux 主机上,这三者都只差一条命令。

ss -unp | grep openvpn
ss -lunp | grep openvpn
sudo lsof -nP -i | grep openvpn

带 nobind 的客户端会显示一个较高的本地端口和配置的远端端口,这是预期的形态。服务器会显示在其配置端口上监听的套接字;如果这个套接字缺失,说明该配置要么不是监听者,要么绑定失败。当流存在但数据包不返回时,先比较所选源端口与路径上的任何端口过滤规则,再修改配置。只改一处,重新连接,然后再次读取套接字。

相关文章