FortiGate Azure 重新协商密钥:peer SA 提案与本地策略不匹配
一条正常工作的 IKEv2 隧道,仍可能拒绝替换用的 CHILD SA。请比较续期真正协商的提案,而不是第一次 ping 所用的那个。
隧道起来了,流量也通了,后来日志里出现 peer SA proposal not match local policy。大多数人把这一行当成两份配置从来没有匹配过的证据。它通常意味着更具体的事:它们只在第一条 CHILD SA 上匹配,到第一次续期就不再匹配,因为第一条关联从未需要后续关联所做的那次交换。正是这个区别决定了你应该去哪里找。
第一条 CHILD SA 继承,后续的才协商
在 IKEv2 中,初始 CHILD SA 在 IKE_AUTH 期间创建,其密钥由 IKE SA 的密钥材料派生。那一刻并不存在单独的 Diffie-Hellman 交换,所以对端无法接受的 PFS 组根本还没有被检验。隧道看起来健康,是因为你后来会失败的那项要求从未被测过。
CHILD_SA 重新协商密钥是另一套消息序列。配置了 PFS 时,两端会执行一次新的密钥交换,必须就双方都接受的组达成一致,同时还要就新关联的 ESP 提案达成一致。不一致正是在这一刻变得可见,这也是错误信息指向提案而不是路由的原因。
所以“昨天还好好的”并不能说明提案本身,它只说明最初的交换成功了,而这你早就知道。
读失败的交换,而不是第一次 ping
在改动任何东西之前,先从两端收集成功的 IKE 认证、初始 CHILD SA 和失败的替换过程。然后精确命名这次操作:IKE SA 重新协商密钥、IKE 重新认证、CHILD SA 重新协商密钥是三件不同的事,日常沟通中“阶段 2”把它们全都涵盖了。
请针对失败的那条连接比较下表中的字段,而不是针对整条隧道。
| 层 | 要比较的值 |
|---|---|
| IKE | 版本、加密与完整性校验或 PRF 组合、DH 组 |
| IPsec / CHILD | ESP 加密与完整性、预期使用的 PFS 组或密钥交换组 |
| 受保护的流量 | 本地与远端选择器,以及任何基于策略的选择器设置 |
在 FortiGate 上打开该隧道的 phase-2 提案、PFS 设置和已接受的 DH 组。读取实际加载的值,而不是根据早先建立的连接去推断。GUI 页面的截图比运行中的配置更弱,因为升级之后两者可能不一致。把改动过的部分导出,并随工单留存。
Azure 的默认策略仍然是一条策略
连接上没挂自定义策略,并不意味着 Azure 不施加任何策略。连接会回退到网关的默认提案集合,它可能比你 FortiGate 提供得更宽或更窄。 如果两个集合在 IKE 上重叠,但在带 PFS 的 ESP 上不重叠,你就会得到一模一样的失败模式。
这个只读视图显示实际挂上的策略,而且不会泄露任何机密:
Get-AzVirtualNetworkGatewayConnection -Name 'Branch' -ResourceGroupName 'NetworkRG' |
Select-Object Name, ConnectionStatus, IpsecPolicies请使用真实的资源名称。需要显式策略时,把它设置在连接资源上。它不是网关级的开关,也不会悄悄作用在同一网关的其他隧道上。
在门户中,该连接的 Configuration 页面就是自定义 IPsec/IKE 策略所在的位置。Microsoft 的 自定义策略指南 列出了支持的参数和 SKU 要求。Azure 每条连接只取一套完整组合,所以你要同时指定 IKE 字段和 IPsec 字段,而不是一个个来。
PFS 是一项要求,不是一个可以随手拨动的开关
如果你的安全基线要求 PFS,解决办法是两端对端都接受的组,并通过匹配的策略表达出来。为了让报错消失而关掉 PFS,改变的是你原本想保留的安全属性,而且它通常会在之后以另一种不匹配的形式重新出现。
Azure 特有的一个陷阱:为 ESP 选择 GCM 时,加密与完整性选择必须指定同一个 GCM 算法和同样的密钥长度。把 GCM 密码与单独的完整性算法混在一起,会产生服务端拒绝的组合;在你仔细读策略之前,这看起来就像对端不匹配。
选择两端都支持、并且你的要求所允许的最强组合,然后写进变更记录。下一个人会拿这份记录去对照,而不是凭对一条曾经可用的隧道的记忆。把 PFS 组和 ESP 提案写进去,而不只是策略名称。日后有人问审计为什么失败、或者重新协商密钥为什么慢,这一行能同时回答两个问题。
验证那次失败的交换
安排变更时要留好回退路径,因为编辑策略可能中断你正想修复的隧道。流量恢复后,等待或主动触发一次 CHILD_SA 续期,确认新关联以预期的 PFS 组建立,然后再确认应用流量在其上继续传输。
有两个假线索值得点明。SA 生存期是本地规格,所以两端取值不同很正常,改它只会改变问题出现的时间。DPD 检测的是对端是否存活;调高它的超时并不会让 ESP 或 PFS 的选择对齐。
记录协商结果以及变更后的下一个事件。如果连接现在在 IKE 认证完成之前就失败,那你看的是刚编辑过的 IKE 设置,而不是最初的 CHILD 续期失败。