不可信的 VPN 是三道独立的边界,而不是一道
远端对端、路径上的运营方,以及你本机上的客户端,是三种不同的威胁。防火墙规则只回答了第一种。
「我不信任这个 VPN」通常是一句话里套着三种说法。该网络上的远端对端可能访问到你主机上的服务,运行隧道的运营方可能观察到流经它的流量,而你安装的客户端软件可能改变这台机器的网络策略。值得纠正的信念是:一条防火墙规则、一台虚拟机,或一次谨慎的操作系统选择就能回答全部三种。每一项措施只回答其中一种。
神话:一种控制覆盖全部风险
常见的假设是:接入不可信网络是一个决定、一种缓解措施。人们挑选自己本就信任的那项控制,套上去,就把风险当作已处理完:防火墙开着、工作区是一次性的、客户端来自有信誉的厂商。
这些控制并不会像假设暗示的那样彼此重叠。主机防火墙限制远端对端能触达什么,却对终止你 TLS 的运营方毫无作用。虚拟机把工作区与主机文件隔开,却对允许在两者之下重配网络栈的客户端组件毫无作用。把每项控制真正划出的边界讲清楚,才是这整套练习。
把三者分开,也会告诉你选择了接受哪一项风险。多数真实决定是缓解一道边界、容忍另一道,只要变更记录写清哪道是哪道,就没问题。
远端对端实际能触达什么
先说正在监听的服务。把隧道接口当作广泛可信,只因为它的数据包是加密到达的,这是常见错误;它会让每一个本地监听者都成为该网络上其他人的候选目标。加密保护的是两端之间的线路;它对另一端对端的意图一无所知。
ss -tulpn sudo nft list ruleset ip -br addr
把服务绑定到它所需的地址,而不是每个接口,并且只放行经批准任务所需的那几种操作。转发、桥接和应用代理要明确保留,因为两个网络接入本身并不构成穿行路径,而一条代理规则当然可以。
经批准的一次性工作区会缩小远端网络能触达的范围,但前提是它的共享配置与这一说法相符。共享文件夹、剪贴板集成、凭据代理和管理通道,都会越过工作区本应划出的那道边界。工作区的标签并不能证明其中哪些是开着的。
NIST 的零信任架构说出了这一切背后的原则:仅凭网络位置并不授予隐式信任。隧道被接纳之后,资源认证仍有工作要做,而「还有谁共享这个网络」这个问题同样如此。
路径上的运营方能看见什么
VPN 把你的流量挪到路径上的另一个位置;它并不增加应用层加密。如果服务商终止了你的 TLS,它就能读到浏览器本来会保护的内容,而任何本地防火墙规则都改变不了这一点。
对真正目的地保持正常的证书校验,并理解解析器与元数据路径,因为一次 DNS 查询能泄露的,往往比它前面的载荷更多。仅元数据一项,你联系过哪些地址、在什么时候,就常常回答了运营方的问题,而完全不必读取内容。这就是「流量已加密」和「流量是私密的」属于两种不同说法的原因。
如果这种可见性对任务不可接受,答案就是换一套经批准的架构,而不是加更多本地过滤。本地过滤无法把一个观察者从它仍坐着的路径上移走。
本机客户端被允许改变什么
这就是人们漏掉的那道边界,也正是它让另外两道变得无关。在 Linux 上,CAP_NET_ADMIN 覆盖接口配置、防火墙管理和其网络环境内的路由变更。持有该能力的软件可以重写你刚写下的策略。
getcap /usr/sbin/openvpn systemd-analyze security vpn-client.service ip netns list
网络命名空间对网络状态是真实的边界,对其他一切则是糟糕的边界:它并不隔离文件系统或凭据存储。把它看作一层,而不是整个问题的容器。
从受维护的来源获取客户端及其配置,审查它申请的权限,并把特权组件置于管理员控制之下。虚拟机可以构成合格评估边界的一部分,却不会变成为在宝贵凭据旁边运行来路不明的安装程序开绿灯。安装程序以你授予的权限运行,而那份权限就是边界。
写下你接受了哪一道边界
用一句话收尾,点名四件事:可信的本地代码、被允许的远端访问、受保护的应用数据,以及仍然存在的那份与运营方的关系。这句话比「一台虚拟机、一个操作系统或一款杀毒软件让敌对网络变得安全」这种笼统说法更值钱。
然后确认那项狭窄操作可用、所需的拒绝仍然成立,包括在隧道断开之后。一道只在隧道升起时存在的边界,并不是你记录下来的那道边界。
没有任何测试能证明所有漏洞都不存在,声称相反结论的评审就是过度承诺。诚实的产出会点名剩余风险,以及接受它的那个人。