把两个客户端组放在不同子网上看起来像隔离,其实不是。地址描述的是数据包表面上来自哪里,而许可是由转发它的组件做出的决定。回答这个问题的是配置而不是掩码,所以在写任何规则之前,先确定由哪个组件转发对等流量。

子网是标签,不是规则

为每个组分一个地址池,只会给你可读的地址,别的什么也没有。接受额外路由的客户端获得了可达性,而可达性不等于授权。通信许可存在于转发决定中,这个决定可能位于守护进程里,也可能位于内核里,取决于服务器的配置方式。

地址归属才让前缀可以作为分组选择器。每个通过认证的身份都必须映射到可预测的地址或范围,而一旦多台设备共用一份凭据和一次分配,这种映射就会失效。在依赖源前缀之前先解决身份与并发问题,因为靠猜测哪台机器在呼叫的策略,会在最糟的时刻给错误的一方授权。

选择承载对等流量的路径

当守护进程在自己的进程内转发对等数据包时,这些数据包永远不会到达主机的转发钩子,因此内核规则看不到它们。关闭这种内部转发,内核就成为转发点,普通转发规则在那里生效。

# peer forwarding inside the daemon: enforce with per-group policy instead of FORWARD rules
client-to-client
# kernel forwarding path: remove the line above, then filter in the forward chain

卸载的数据通道和产品托管的服务器会发布各自的执行模型,所以要确认你运行的是哪一种,而不是假定社区版本的行为。值得避免的失败,是在评审中看起来正确、运行时却从未被查询的规则。

先写矩阵,再写规则

短矩阵比整套规则更容易评审,它也是实现必须满足的契约:同组对等方允许,跨组对等方拒绝,两个组都允许访问某个指定的共享服务,其余一律拒绝。在打开防火墙编辑器之前,先把这四行写下来。不读规则语法的评审者仍然可以检查矩阵。实现随后只需与这些行保持一致。

SourceDestinationDecision
Group A addressAnother Group A addressAllow
Group A addressA Group B addressDeny
Either groupThe shared internal serviceAllow
Either groupAnything not listedDeny

写的时候把三类目的地分开。VPN 主机上的服务是本地输入,另一台客户端是对等转发,网关后面的机器则是另一条转发路径。一条宽松的规则可能意外地同时授予三者,组策略就这样变成多绕几步的扁平网络。在每一行旁边写上类别,让意图在下次编辑后仍然成立。

把规则放在能存活的地方

在维护防火墙其余部分的同一位置添加这些决定,并放在任何会吞掉它们的放行规则之前。规则顺序是策略的一部分,放在宽泛允许之后的正确规则什么也执行不了。记录修改前后的规则编号。只存在于编辑器、不在运行规则集里的策略只是计划,不是控制。

决定策略变化时已存在的流会怎样,因为变更前打开的会话可能在变更后继续。如果离开的成员必须立即失去访问,规则集需要有办法终止该状态,而不是等连接自行关闭。

通过拥有防火墙其余部分的机制让规则持久化,并在旁边记录矩阵。没有记录的策略会在下一次事件中被人凭记忆重新推导,而且通常是在匆忙之中。

从两侧证明

从每个组的一台客户端测试同组可达性、跨组失败和共享服务。只从一台客户端测一次,只能证明矩阵的一半,而漏掉的那一半通常正是错的那一半。把拒绝方向重复两次,因为缓存会话可能掩盖执行错误。记录你测过哪一对,避免下一个人重复。

如果隧道承载 IPv6,就在同一协议上重复检查,并保留常规的应用层认证。源前缀不是账号,所以通过网络策略并不意味着服务应当信任调用方。

相关文章