共用一台工作站会引出一个单用户笔记本从不需要回答的问题:当一个人认证了隧道,还有谁能使用它?登录标识的是一个主体,而它安装的路由描述的是一个范围,这两者并不是同一个对象。夹在中间的是操作系统、客户端配置,以及私有服务自己提出的要求。比较各个执行点是唯一不用猜测就能回答这个问题的办法。

一次登录,多个范围

认证回答的是谁被允许进入。路由回答的是哪些数据包可以经隧道发出。授权回答的是哪个服务会接受由此产生的连接,而这三者谁都不能推出下一者。

整机隧道是常见的默认做法,也让这个缺口暴露无遗。路由位于内核路由表中,因此任何使用该表的进程都能访问私有网络,包括由从未见过 VPN 对话框的用户启动的进程。这不是隧道的缺陷;这正是系统级路由的含义。私有服务仍然可以拒绝连接,所以 可达性与权限需要分开回答。

在测试前把四个问题写下来,可以避免评审最终只落到其中一个。

边界究竟在哪里

四种安排覆盖了大多数机器:整机隧道、按用户的连接、按应用的允许列表,以及独立的网络命名空间或虚拟机。

每一种把执行点放在不同位置,差异比名称更重要。按用户的连接由配置文件权限执行,而不是由桌面登录界面执行。按应用的允许列表在客户端内部执行,由客户端决定承载什么。命名空间或虚拟机在接口边界执行,因此里面的进程根本看不到主机的路由。机器上有几个登录界面,说明不了其中任何一种安排。

ArrangementEnforced byWho can use the path
Host-wide tunnelThe routing tableAny local process using that table
Per-user connectionProfile permission listOnly the listed accounts
Per-app allowlistThe VPN client itselfOnly the selected applications
Namespace or VMThe interface boundaryOnly processes inside it

逐行阅读这张表可以看出,真正的问题不是有没有隔离,而是隔离在哪一层实现。

比较四个执行点

在 Linux 上,路由表是第一件要查的东西,因为整机隧道会出现在那里,而命名空间不会。以第二个用户身份运行查询,是人们常跳过的一步;答案与以自己身份得到的不同,而这正好解释了报告。

接下来的两项检查看的是策略而不是路由。匹配 UID 的防火墙规则适用于本地产生的流量,因此即使两人共用同一条路由,也能在同一台主机上区分两个用户。带显式权限列表的连接配置文件会在激活时由网络管理器执行。两项检查都不需要改动隧道,所以值得在任何重新设计之前先做。

ip route get 10.40.2.10
sudo -u bob ip route get 10.40.2.10
nmcli connection show vpn-work | grep -i permission
sudo nft list ruleset | grep -n skuid

如果第二次查询显示的是隧道路由,那么边界就不在设计假设的位置。

并发会话规则是另一套控制

网关常常限制一个账户能保持多少个会话,而这个限制与本地用户毫无关系。它限制的是账户,所以第二个人用同一份凭据登录,就可能终止第一个人的隧道。

在假定是本地隔离问题之前,先读懂失败信息。会话上限会在网关上造成断连,而范围问题产生的是能工作、却根本不承载另一个用户流量的隧道。这两种症状指向完全不同的修法。保留客户端的原始消息,因为它通常会点出规则名称。请向配置文件所有者索取已批准的工作流程,而不是绕过限制。

虚拟机不会让任何人豁免于这条规则,它还会带来自己的网络与凭据设计。

测试你真正关心的上下文

先测试预期的用户和应用,再测试一个本应被拒绝的上下文。只证明原密码能用的评审,只测了认证,别的什么都没测。

sudo -u bob curl -sS -m 5 https://intranet.internal/health
wg show
ss -tnp | grep -E ':443|:51820'

在每项结果旁记录执行点:路由表、UID 规则、配置文件权限,或网关的会话策略。这份记录让下一次改动可供评审。它还能避免每次有人发现第二个登录界面时,同一个问题又被重新打开。可达性不是授权,两者也都不是隔离。

相关文章