公开的 SaaS 页面可以对所有人开放,而页面背后的管理操作会拒绝一切 VPN 之外的人。让这套机制生效的不是隐藏菜单,也不是另设的登录页;它是对送达请求的网络路径的校验。地址证据一旦弄错,校验要么把真正的管理员挡在外面,要么放进任何会敲一个请求头的人。先从源站实际收到什么说起。

隧道的另一端,源站实际收到什么

当浏览器通过同时承载互联网流量的 VPN 访问公开站点时,网关会在连接离开之前完成地址转换。SaaS 看到的是网关的公共出口地址,通常是一个地址或一小段范围,而 永远看不到笔记本的隧道地址。所以把 10.90.0.42 列进允许清单会失败,而把整个 RFC 1918 列进去失败得更响:后者会放进所有能到达你的私有网络。唯一值得设条件的地址,是你的组织在出口处真正拥有的那个地址。

curl -s https://ifconfig.me
dig +short admin.example.com

拆分隧道会悄悄打破这个假设。如果 VPN 只承载办公网私有路由,发往公开管理主机名的请求就会走本地运营商出去,源站看到的是一个住宅地址。连着的 VPN 图标并不能证明这个特定目的地走了隧道,所以要测的是目的地,而不是隧道。

如果出口地址因用户而异,先停下来把路由修好,再写任何策略。只匹配部分管理员的条件比没有条件更糟,因为它会把问题藏到出事为止。

只信任会重写地址的那层代理

多数公开站点位于 CDN 或反向代理之后,所以源站的套接字地址属于那层前端,而不属于访客。前端通常把原始地址放进一个请求头转发,而 这个请求头在源站只接受已知代理时才可信,否则就是攻击者可控的。要显式配置可信来源清单,并让源站无法从其他任何地方访问。少了这后半句,攻击者绕过代理直接发送请求头就行。

set_real_ip_from 192.0.2.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
curl -H 'X-Forwarded-For: 198.51.100.27' https://origin.example.com/admin

同样的道理适用于 PROXY 协议:只有当监听套接字绑定在代理可达、别的都不可达的接口上时,它才可信。缺少地址上下文时必须让受保护的校验失败,而不是落进默认放行。缺失的请求头不是可信路径的证据。

把条件挂到每一个受保护操作上

校验要放在每个受保护操作都会经过的授权边界上,而不是放在渲染菜单的那个页面里。路由组、中间件或策略层都可以;按处理器各复制一份则不行,因为下个季度有人新加的处理器不会带上它。

user = requireAuthenticatedSession()
requirePermission(user, "admin")
requireVpnEgress(verifiedClientAddress(request))
performProtectedOperation(user, request)

同一条边界还要覆盖 JSON API、导出、签名下载链接和 WebSocket 握手,因为这些都不需要先请求 HTML 页面。VPN 开着时签发的下载链接,除非下载端点重新校验,否则之后一直有效。长会话也需要重新评估规则,否则一次已认证的请求就成了永久豁免。默认拒绝是唯一能扛住人员更替的设置。

共享缓存是绕过校验的另一条路。已经持有受保护响应的缓存,可以不经源站就直接把它发出去,所以要把管理类响应标记为私有,并挡在共享存储之外。如果缓存必须提供这些响应,访问校验就得跑在发送之前,这通常意味着它根本不能是共享缓存。

把你刚堵上的绕过路径都测一遍

要练矩阵,而不是只练顺利路径:管理员走 VPN、同一管理员不走 VPN、非管理员走 VPN,以及伪造的地址头。再加上直连源站的请求和命中缓存的请求,因为跳过前端的正是这两种。

curl -sI https://admin.example.com/export.csv
curl -s -H 'X-Forwarded-For: 198.51.100.27' https://origin.example.com/admin
curl -s https://admin.example.com/api/me -o /dev/null -w '%{http_code}\n'

每个请求都应返回策略承诺的状态,日志应记下用了哪一份地址证据。IPv6 要单独覆盖,因为双栈源站看到的源地址族可能和你测的不一样。让普通客户操作在 VPN 之外照常可用,否则第一次有客户投诉,改动就会被回滚。跑之前先把每一行的预期结果写下来,这样意外通过才看得见。

出口地址证明的是一条被允许的网络路径,不是某个人,也不是某台受管设备。把它作为认证与权限旁边的一个条件保留,管理区就会保持狭窄,而不至于把整个产品变成只服务 VPN 的产品。这种分离本身就是设计,不是它的局限。

相关文章