这条规则听起来很精确:在专用配置文件上允许本地流量,在公用配置文件上只允许 VPN 流量。其实并非如此,因为网络配置文件只决定哪套防火墙规则生效,并不说明哪个适配器承载了数据包。把配置文件名称当作路径要求,正是让受限出口设计看起来已经完成、实际却未完成的错误。

先把流量写下来,再决定哪种机制能真正约束每一条流量。那份流量清单是唯一能经受下一次规则变更的东西。

类别选择的是规则,不是路由

当 Windows 把网络归类为公用或专用时,防火墙会应用为该配置文件配置的那套规则。分类跟随适配器所加入的网络,而规则集决定在该网络上允许什么。这些事实都不取决于某个应用的流量是否走了隧道。正是这种相互独立构成了全部难点。

路径的选择由路由完成,取决于接口跃点数和隧道安装的前缀。因此,配置文件可能被标记为公用,而某个应用的连接却走物理路径,防火墙仍会报告应用了公用规则集。

所以,限定在配置文件上的规则不可能意味着只走隧道。这两个属性由不同组件决定,一个不能替代另一个。

FlowWhat decides itWhat a rule can enforce
VPN client to its endpointRouting plus the outer transportAllow the client process before the tunnel exists
Application to an internet hostInterface metric and prefix lengthBlock the process unless the tunnel interface is up
Application to a LAN hostLocal subnet routeAllow one destination, not the whole category

显式阻止优先于范围更窄的允许

Microsoft 的防火墙规则指南区分了针对默认阻止操作的允许例外,以及与允许相冲突的显式阻止。显式阻止在这种冲突中胜出,出站规则也遵循同样的优先级。

因此,那种加一条全部阻止的规则、再指望放在它上面的窄范围允许的流行做法,并不会得到作者预期的结果。Windows 防火墙不会按管理员指定的规则顺序来解决冲突。阻止直接生效,发起连接的应用报告超时。那条看起来像例外的规则从未参与其中。

受支持的形式是默认拒绝策略加上经批准的允许规则,其中每条允许都足够精确地指明程序、服务或目标,以便接受审查。这样的设计经得起审计,因为每个例外都可见,而且没有一个依赖创建顺序。

两条互相矛盾的规则比一条规则更糟,因为由此产生的行为既正确又无法解释。

让出站策略只有一个负责人

受支持的 VPN 客户端本身已经维护自己的阻止行为和自己的终结点例外。再叠加互不协调的手工规则,可能让该客户端被困在安装所需的隧道之外,或者留下一条无人察觉的第二条路径。

写规则之前先确定出站策略归谁所有:客户端自身的配置、受管理的防火墙策略,还是带负责人的书面本地例外清单。然后调和各层,而不是不断堆叠实验直到某处连通。具名负责人也是两层不一致时该去询问的人。

改动任何东西之前先保留一条恢复通道。一台被锁在自己管理路径之外的远程机器,比你正在堵上的策略缺口更糟。恢复规则提前写下来更容易解释,在没人喜欢的时刻出问题时也更容易找到。

测试四种结果,而不是读标签

策略的好坏取决于它能区分多少种情形,所以把配置文件标签当作起点而不是结果。四种结果能说明它是否有效:预期的 LAN 请求成功,被覆盖的互联网请求成功,被禁止的直接请求失败,隧道故障情形按设计表现而不是悄悄回退。把这四个结果写在规则变更旁边。四个具名情形的测试计划短到每次都能执行,又具体到会大声失败。

Get-NetConnectionProfile | Select-Object Name,NetworkCategory,InterfaceAlias
Get-NetFirewallProfile | Select-Object Name,DefaultOutboundAction
Get-NetFirewallRule -Direction Outbound -Enabled True | Where-Object Action -eq Block |
  Select-Object DisplayName,Profile

第一条命令显示每个已连接网络是如何分类的,这往往并不是写规则的人所假设的那样。第二条显示每个配置文件的默认操作,第三条列出已启用的出站阻止,包括那些会悄悄覆盖较窄允许的规则。

网络变更后重新运行这四种情形,因为机器加入另一个网络时配置文件可能被重新分类。配置文件标签一致并不能证明路径就是你想要的那条。

相关文章