ifconfig-noexec 救不了你的 SSH 会话:它到底做了什么
它抑制的是 OpenVPN 自己的接口地址配置。它既不保留 SSH 的回应路由,也不关闭所有路由变更,更不补上缺失的地址。
在某个论坛帖子里,ifconfig-noexec被当成“让隧道升起后 SSH 会话继续存活”的修复方案推荐出来。这个推理听着合理,直到你查清这个选项到底碰了什么。它阻止OpenVPN配置隧道接口的地址,而把那些值交给脚本;至于你管理连接的回应包该往哪走,它一个字都没说。反过来相信,只会得到一个没有可用地址的隧道,以及一个照样断掉的 SSH 会话。
这个选项到底委托了什么
默认情况下,客户端会拉起隧道设备,并分配服务器交给它的本端和远端地址。设上ifconfig-noexec之后,这一步就被跳过,协商出来的值被导出到脚本环境,好让别的什么东西去应用。
所有权转移了。它的位置上并没有凭空多出什么。
所以这个选项回答的问题是:谁来配置接口;而它没有回答的问题是:数据包怎么找到回到你这里的那条路。把这两件事分开,否则你会花一整晚改路由,去补偿一个没有地址的接口。
三个相似但职责不同的选项
这一家子容易混淆,因为名字只差一个词,症状又互相重叠。选任何一个之前,先读清楚各自压掉了什么。
| Option | What stops happening |
|---|---|
ifconfig-noexec | OpenVPN's own tunnel-address configuration; values go to scripts instead |
route-noexec | Automatic route addition and removal; route details go to a script |
route-nopull | Server-pushed routes and related options such as DNS are rejected |
这些是可以分别了解的备选方案,不是可以一起粘贴的套餐。压掉地址配置,并不会压掉路由变更、防火墙规则,也不会压掉携带 DNS 的下发选项。被委托的脚本同样可以随意改路由,这是你交出去的判断,而不是避开的问题。
如果厂商客户端包住了引擎,就用它支持的集成方式,而不是把一条底层指令塞进配置文件,再指望那层包装会尊重它。包装层常常在连接时重新生成配置文件,于是手工修改会无声消失。在为一个文件耗掉一整晚之前,先查清客户端把设置放在哪里。这条对表里每一行都成立,不只是你冲着来的那一行。
你本想保护的那条 SSH 会话
一条 SSH 连接有源地址、目标地址和回应路径。在一台刚装上全隧道默认路由的服务器上,发往你公网地址的回应会落进隧道,然后被 VPN 网关丢掉。
隧道接口的地址配置里,没有任何东西能改变这一点。
真正修好它的,是一条更具体的路由:让你的管理地址走隧道之前的网关;或者一条把那股流量导过去的路由策略;再加主机上生效的过滤设置。两个问题有时一起出现,于是一个被误当成了另一个的解药。分开测试:不带这个选项把隧道拉起来,看接口地址和回应路径,再判断两者之中到底是哪个坏了。
被委托的脚本必须接手什么
如果你确实想让另一个主人来配置接口,就把活儿列清楚:应用本端和远端地址、拉起设备、在拆除时恢复或移除地址,并在重连之后再来一遍。一次成功会话里的值不能写死,因为服务器下次可能给出另一对。
客户端导出的环境变量,是这项工作唯一受支持的输入。
env | grep -E '^ifconfig_|^route_'在route-up脚本内部,这些变量是有的;从 cron 任务或手工 shell 里则没有。确认你用的版本挂的是哪个生命周期钩子,也确认这个钩子有足够权限去改接口,因为客户端可能已经降权到普通用户。
要测整个生命周期,而不是一次会话
拉起隧道,检查设备上的地址,然后重连再查一遍。只在第一次能成、第二次就失败的配置,通常意味着被委托的那一步只在首次连接时执行。
然后把两条验收标准放在一起测:经由预定管理路径的新 SSH 连接能建立,被放行的应用能正确走隧道。
隧道没有地址时,一条旧 SSH 会话碰巧还活着,不算成功,而那正是没人接手这项工作时这个选项造成的状态。先查接口地址,再查管理的回应路径,最后查应用。如果三者错了两样,这个选项只是把活儿挪走了,并没有给它一个主人。