OpenVPN 的 script-security 级别 0 到 3,以及每一级解锁什么
每个 script-security 级别都会扩大配置文件可执行的范围:先是管理辅助程序,然后是用户脚本,最后是环境中的密码。读一读这些指令。
把配置文件导入桌面客户端,第一个报错往往是一行客户端拒绝执行的指令:它不愿运行的脚本钩子,或它认为过于宽松的 script-security 值。把数字调高,对话框就消失了。可它也扩大了该配置文件在你机器上可执行的范围——为了关掉一条警告而给出这种授权,实在奇怪。顺着导入一路追到那条指令,决定就变得具体了。
从导入对话框到指令
配置文件是带指令的文本文件,客户端在隧道建立之前就会读取它们。像 up、down 或 tls-verify 这样的指令,指定一个外部程序,OpenVPN 应在某个确定时刻运行它。OpenVPN 是否愿意运行它,是另一项名为 script-security 的设置,配置文件通常也会设定它。
所以这条警告与加密或证书无关。它讲的是一个配置文件要求客户端在主机上执行某些东西,以及客户端在检查当前权限级别是否允许这一请求。
在这一阶段,两种不同的失败看起来很相似。请求客户端不会授予的级别,会产生拒绝。请求客户端会授予的级别、但脚本缺失,则会产生运行时失败,两者在支持论坛里常被混为一谈。一个是权限问题,另一个是打包问题。
每一级究竟打开了什么
级别 0 完全禁止外部程序调用:对于无需帮助即可自行配置接口的客户端,这自洽;对于需要调用操作系统的客户端,则不自洽。级别 1 是默认值,允许接口与路由配置所需的内置可执行文件。两个级别都不会运行用户提供的任何东西。
| Level | What OpenVPN may execute | What it exposes |
|---|---|---|
| 0 | No external programs at all | Interface and route setup must not depend on helpers |
| 1 (default) | Built-in helpers such as ip, ifconfig, route or netsh | Privileged commands the platform already ships |
| 2 | Built-in helpers plus user-defined scripts | Whatever the named script does with the client's privileges |
| 3 | Everything above, plus passwords in environment variables | Credentials visible to child processes and their logs |
级别 2 才是有意思的边界,因为它允许用户自定义脚本。从那一刻起,客户端的权限作用于你可能从未读过的代码,在你没有选择的时刻被调用,环境里还带着连接细节。级别 3 更进一步,允许通过环境变量传递密码,所以手册称它可能不安全。
这些数字都不是强度设置。级别 3 的配置文件并没有比级别 1 更好的加密;它只是有更大的执行面,而隧道本身完全相同。
决定这个配置文件值得什么
先问脚本是干什么的,再问它需要哪一级。推送 DNS 设置、或在连接后修复路由的钩子,是运行某些东西的正当理由。在临时目录里调用陌生二进制的钩子,则是停下来的理由。
脚本的路径与脚本本身同样重要。相对路径按客户端所用的目录解析,而可写目录会把一次性导入变成常驻的执行位置。用户无法修改的目录里的绝对路径,才是应当优先选择的形态。
脚本还会继承客户端的环境,凭据和连接元数据就住在那里。正是这种继承,让级别 3 与记录自身环境的脚本搭配时变得危险;也正因如此,把启用了脚本的客户端导出的诊断转储贴进工单之前,值得再看一眼。分享之前先清掉环境。
grep -nE 'script-security|^up |^down |tls-verify' client.ovpn只改一处,然后也盯住断开那一段
如果配置文件确实需要脚本,就只改级别,并且只针对那个配置文件。在前台以详细输出运行客户端,让脚本自身的错误显现出来,而不是被服务管理器吞掉。
openvpn --config client.ovpn --script-security 2 --verb 3
ip route show default
测试整个生命周期,而不只是连接。失败的下线钩子会让路由仍指向一条死隧道,结果机器看似在线却哪儿也到不了。在宣布改动完成之前,重连一次、断开一次,并在每次之后检查路由表。
保留原始配置文件的副本。如果某平台的客户端没有实现同样的脚本模型,那么为了导入成功而删掉指令,可能一并删掉隧道所需的 DNS 或路由集成;结果连接认证完美,却什么都解析不了。
值得记录的结论很窄:哪个脚本、在哪条路径、以哪一级授予、用于哪个配置文件。配置文件里的其余部分保持不变,而这是一句审阅者可以核对的话。