在办公室局域网里,内部名称瞬间就有应答。VPN 一上线它就停止工作,应用报告超时,而隧道本身毫无怨言地转发流量。变化的是解析器,而这个解析器对私有地址有自己的看法。

重绑定防护的存在是为了拦住一种特定的把戏。一个被刻意发布的私有名称,看起来足够相似,于是防御被触发。

先读应答,再读策略

向 VPN 真正下发的那个解析器查询该名称,而不是你在家用的笔记本所依赖的那个。把应答与你预期的记录作比较,并记下应答是空的、被拒绝的,还是塞满了没人规划过的公网地址。

各种症状彼此重叠,所以决定诊断的是应答的形状。NXDOMAIN 是记录缺失,REFUSED 是访问规则,内部名称返回公网地址是策略或 split-DNS 的错误,而客户端无法使用的正确私有地址则是完全不同的问题。连接被拒或请求卡住本身什么都证明不了,所以这类工单里的第一条命令应该是查询,而不是重启。在改动任何东西之前先把应答记下来。

防御实际挡住的是什么

DNS 重绑定靠的是在客户端已经信任某个名称之后,改变它解析到的地址。页面从攻击者控制的名称加载,应答翻转为私有地址,浏览器被骗去与本机网络上它绝不会接受直连的某个东西通信。防御的做法是:当解析器从未被要求服务某个私有命名空间时,拒绝指向私有地址空间的应答。这种不对称正是整个攻击手法。

dnsmasq 恰好记录了这一行为,也记录了按域名设置的例外。它的手册页把 rebind-domain-ok 描述为指定可以合法返回此类地址的域名的方式。请把它读成一个信号:预期的修法是范围受限的放行,而不是全局开关。

把例外收窄到命名空间

先修命名空间,再谈例外。确认失败的名称属于组织控制的域名,并且该记录是被刻意维护的。仅仅形似某个熟悉局域网段的意外地址值得怀疑,而不是开例外,所以在写下任何放行之前先核对区的归属。

# ask the resolver the VPN pushed, and show the full answer
dig +noall +answer db.corp.example @10.40.0.1
dig +short db.corp.example @10.40.0.1

# dnsmasq: what does the running configuration already allow?
grep -R 'rebind' /etc/dnsmasq.d /etc/dnsmasq.conf

然后加上覆盖目标名称的最窄放行:在 VPN 客户端所查询的解析器配置里,一个域名,或一个被委派的子域。把该解析器上所有名称的防护一并关掉,会同时剥掉全部名称的防御,包括从来不需要它的那些。

Split DNS 属于同一个决定。如果私有命名空间只该由内部解析器应答,就把它发布在那里,并停止把它泄漏给公共解析器,这样例外覆盖的是一条路径,而不是每条路径。

重新测试资源与防御

再次查询,然后连接服务,看客户端看到什么。正确的私有应答加上可用的会话,说明例外已经落地。正确的应答却配上卡住的会话,说明下一个嫌疑人是路由或服务身份。

# the internal name and the public control should behave differently
dig +short db.corp.example @10.40.0.1
dig +short www.example.com @10.40.0.1

# and the service itself, with the certificate it presents
curl -sS -o /dev/null -w '%{http_code}\n' https://db.corp.example/health

也通过同一个解析器测试一个公网名称。对于例外之外的名称,防护仍应表现正常;如果这项检查失败,说明改动比预期更宽。全程不要动证书校验,因为解析正确的名称仍必须与服务出示的证书匹配。

把被拒绝的应答、域名、解析器以及谁拥有该策略记进工单。正是这份记录,把一次神秘的内部故障变成某个人可以复核的配置变更。

相关文章