同一个服务器配置文件启动两次,第二个进程就会因 1194 端口“地址已被占用”而退出。常见的情况是,诊断性的启动自己制造了冲突,而原来的实例仍在完好地为客户端服务。这类报告中有很大一部分都属于这种情形,值得在重启任何东西之前先认出来。这也是解决起来最省事的版本。

这个错误描述的只是一次本地绑定,仅此而已。它不能证明服务商封了端口、客户端发错了密码,或者证书链坏了。

读懂那条确切的绑定错误

这一类里有两个错误,含义并不相同,混为一谈会把你引到错误的层面。“地址已被占用”是说另一个 socket 占着你请求的端点。“地址不可用”则是说你请求的地址在这台主机上还不存在,那是就绪问题,不是重复。

systemctl status openvpn-server@lab --no-pager
journalctl -u openvpn-server@lab -n 20 --no-pager

在改动任何东西之前,先把错误文本复制下来,包括它提到的地址和端口。等待接口出现的那种服务会反复记录第二个错误,等地址存在后便能成功绑定;而记录第一个错误的服务,在重复被解决之前永远不会成功。记下你看到的是哪一种,不花任何代价,还省去一次白费的接口排查。

盘点 socket,而不是端口

端口号是一份不完整的清单。端点是传输、地址族、本地地址和端口的组合, 全都位于同一个网络命名空间里。同一号码上的 UDP 监听者和 TCP 监听者是不同的 socket,而不同命名空间里同一号码上的两个进程永远不会碰面。

ss -lunp | grep -F ':1194'
ss -ltnp | grep -F ':1194'
ss -lunp 'sport = :1194'

先运行配置文件真正使用的传输。然后去看本地地址那一列,而不只是号码:通配绑定覆盖所有本地地址,所以第二个进程哪怕只要一个具体地址,也可能与它冲突,尽管打印出来的字符串并不相同。socket 复用选项和平台规则决定确切结果,所以这应当是一次观察,而不是一条套用到所有部署上的规则。

查明是哪个进程占着它

数字端点加上进程信息,在权限允许时能确认属主;你需要的是属主,不是程序名。两个 OpenVPN 进程可以跑不同的配置文件,而持有监听者的那个,可能恰恰是你最想不到的。

sudo ss -lunp 'sport = :1194'
sudo fuser -v -n udp 1194

把查到的结果与服务管理器、容器运行时或上一次测试残留的终端进程对照。拿不到进程详情,并不能证明 socket 无人拥有;通常只说明查询权限不够。同样,只列 TCP 也排除不了 UDP 的冲突,所以要检查错误里点名的那种传输。单看进程名永远说明不了加载的是哪个配置文件,而 真正决定端点的是配置文件。

一个属主,还是两个设计好的实例

如果部署只打算有一台服务器,就保留一个生命周期属主,去读那个实例的日志或配置好的记录,而不是再启动一份副本来盯着它。确实需要受控的前台运行时,要有意识地停掉被管理的实例,并在动手之前把它正在服务的客户端算进去。

如果本来就要两个实例,那就给它们不同的监听者和各不相同的一切:地址池、虚拟接口、路由策略和配置归属。只换端口,区分的仅仅是 socket,两台服务器仍会争夺同一个地址池和同一批路由。

有三条捷径值得点名,因为它们出现在每一个关于这个错误的讨论里。不要杀掉一个看起来像罪魁祸首的任意 PID。不要为了消掉提示就打开 socket 共享。也不要把服务器配置改成客户端式的非绑定配置,因为那会让绑定错误消失,却让服务器以比原冲突更难诊断的方式变得不可达。

换端口只有在新的监听者属于获批设计时才是正当答案,而那必须连同转发规则和客户端端点一起改。如果这些没有更新,你只是把冲突挪到了没人找得到的地方。

先验证绑定,再谈其他

在限定范围的修正之后,确认目标实例处于活动状态、它的监听者出现在你预期的传输上,并且客户端能够连接。绑定成功只完成了本地 socket 这一段;它并不能证明认证,也不能证明隧道建立之后的流量。

ss -lunp 'sport = :1194'
systemctl is-active openvpn-server@lab
journalctl -u openvpn-server@lab -f

如果 socket 在,而客户端仍然失败,剩下的问题就在下游,绑定错误已成为历史。这种区分正是先读确切消息的全部意义:一个错误、一层、一个属主。这样去读,下一个症状就会从一个已知状态出发,而不是从猜测出发。

相关文章