干过AWS网络架构的人应该都有同感:物理机房里的防火墙双机热备,靠的是VRRP和VIP漂移,但把FortiGate搬上AWS之后,这套老思路基本行不通。AWS不给你二层组播,也不让你随便飘一个虚拟IP,单跑一台FortiGate实例,只要底层AZ抖动一下、实例被Stop,整个出口就断了。所以在AWS上给FortiGate配置HA,是云网络改造里绕不开的刚需场景。
这篇文章我会把FortiGate在AWS环境里做HA的完整流程讲清楚,包括为什么必须换思路、AWS侧要提前准备哪些资源和权限、FGCP集群怎么搭、SDN Connector怎么让路由自动切换,以及我在真实项目里踩过的坑。适合正在做AWS云上网络架构、准备把下一代防火墙高可用真正落地的同行参考。
1. 为什么FortiGate上了AWS,HA不能照搬物理机房的思路
1.1 物理机房的双机热备在云上为什么失灵
在物理机房做防火墙HA,通常是两台设备堆叠或者主备部署,靠VRRP之类的协议共享一个VIP。主设备挂掉,备设备通过心跳感知到之后,立刻把VIP抢过来,同时发出免费ARP,让交换机把流量引到新主设备。整个过程依赖二层组播、共享MAC、免费ARP这几个老伙计。
到了AWS就麻烦了。AWS VPC是一个被SDN虚拟化过的网络环境,默认不支持组播,你没法用VRRP的心跳组播形式发现对端。就算你把两台FortiGate放在同一个子网里,也没法让一个VIP在两台设备的ENI之间“飘”,因为AWS的ENI和IP绑定太死,不响应免费ARP那套逻辑。更现实的问题是,业务流量怎么从外部走到防火墙、防火墙怎么把流量转发到内网,这中间靠的全是VPC路由表、弹性公网IP、安全组这些云原生的东西,根本不认识你的VIP。
所以,FortiGate在AWS上做HA,核心不是“让VIP飘起来”,而是要让云网络的路由和公网地址自动跟随主备状态切换。想明白这一点,后面配置就不容易走偏。
1.2 AWS上做HA的两种主流路线
我接触到的AWS环境里,FortiGate HA主要有两种落地方案,各自的目标和使用场景不太一样。
路线A:FGCP + SDN Connector 的原生HA方案
FGCP(FortiGate Cluster Protocol)是FortiGate自带的集群协议,支持Active-Passive和Active-Active模式。在AWS上,FGCP可以通过单播方式运行,主备之间通过心跳端口互相探测,同时会同步会话表、配置、路由表等信息。SDN Connector是FortiGate和AWS API之间的桥梁,当发生主备切换时,FortiGate会通过SDN Connector调用AWS API,自动修改VPC路由表、重新绑定弹性公网IP。
这种方案最大的好处是切换速度快,业务影响小。因为会话表是同步的,主设备挂了,备设备上已经有全部活跃会话,切过去之后大部分连接都不会断。企业里的生产业务如果对连续性要求高,一般会选这个方案。
路线B:云原生脚本自动化方案
用CloudWatch监控FortiGate实例的健康状态,一旦发现主实例异常,就通过Lambda函数调用AWS API,把路由表目标从主实例ENI切换到备实例ENI,再把EIP重新绑定过去。这种方案成本低,不依赖FGCP的会话同步,但切换速度慢一些,而且已经建立的TCP连接大概率会断开,需要客户端重新发起连接。适合对成本敏感、业务容忍短时中断的场景。
两种路线的区别可以看这张表:
| 对比项 | FGCP + SDN Connector | 云原生脚本自动化 |
|---|---|---|
| 切换速度 | 秒级,会话保持 | 分钟级,可能丢连接 |
| 会话保持 | 支持,session-pickup | 不支持 |
| 复杂度 | 中等,需要配FGCP和SDN | 较低,主要是IAM和Lambda |
| 成本 | 需要两台带HA授权实例 | 普通两台实例即可 |
| 适合场景 | 生产核心业务、金融交易 | 开发测试、非关键业务 |
1.3 我推荐用FGCP + SDN Connector的原因
如果条件允许,我几乎都会选FGCP + SDN Connector这个方案。原因很直接:用户感觉不到切换,运维才不会有压力。
我之前在一个电商项目里,一开始图省事用了脚本自动化方案,结果赶上大促前一台实例被系统底层维护触发重启,流量断了将近三分钟,监控告警直接打爆,业务那边电话都追过来了。后来切到FGCP方案,同样做了一次主实例停止演练,客户端的长连接基本没断,只有几次重试,业务侧几乎无感。从那次以后,我对生产环境里的HA基本只有一个标准:切了跟没切一样。
当然,FGCP方案对配置细节要求更高,不是你点两下就能起来的。后面几节我会把AWS侧的准备工作和FortiGate上的配置一步一步讲透。
2. 动手前先把AWS侧的网络骨架搭好
2.1 VPC和子网规划:给HA留出足够空间
FortiGate在AWS上的HA,理论上最少需要两个可用区,主备各占一个。如果只部署在一个可用区,那只能防实例故障,防不了可用区整体故障,不能算真正的高可用。
我习惯的规划方式是这样的,假设VPC网段是10.60.0.0/16:
| 子网 | 网段 | 可用区 | 用途 |
|---|---|---|---|
| public-subnet-a | 10.60.1.0/24 | us-east-1a | 主FortiGate外部接口 |
| public-subnet-b | 10.60.2.0/24 | us-east-1b | 备FortiGate外部接口 |
| private-subnet-a | 10.60.10.0/24 | us-east-1a | 主FortiGate内部接口 |
| private-subnet-b | 10.60.20.0/24 | us-east-1b | 备FortiGate内部接口 |
| mgmt-subnet-a | 10.60.100.0/24 | us-east-1a | 主FortiGate管理接口 |
| mgmt-subnet-b | 10.60.200.0/24 | us-east-1b | 备FortiGate管理接口 |
| hb-subnet | 10.60.30.0/24 | 可用区A/B均可 | 主备心跳互通 |
这里有几个关键点:
- 外部接口、内部接口、管理接口最好分开子网。这样安全组和路由策略能做得更干净,也方便后续排障。尤其是管理面,如果和业务面混在一起,一不小心就把管理端口暴露到公网,风险很大。
- 心跳子网非常关键。FGCP的心跳流量非常敏感,延迟太高会导致主备频繁震荡。如果你把两台实例放在不同可用区,心跳子网建议选择两个可用区之间的专线子网,或者用一个延迟尽可能低的子网段。如果条件允许,把主备放在同一个可用区的机架内做第一层HA,再通过其他手段做跨可用区容灾,心跳会稳很多。
- 每个业务子网的路由表要预留好。内部接口所在的私有子网,默认路由要指向FortiGate的ENI;当主备切换时,这条默认路由会在SDN Connector的帮助下自动改指向。
2.2 IAM角色:把“改路由、绑EIP”的权限交给FortiGate
这是整个方案里最容易忽略的一步。很多人在FortiGate上配好了FGCP,却发现故障切换之后路由表纹丝不动,查了半天,最后发现是IAM角色权限不够。
FortiGate要通过SDN Connector操作AWS资源,需要一个IAM角色,并且在启动EC2实例时把这个角色绑定到实例上。角色的信任关系要允许EC2服务代入,权限策略至少要包含以下Action:
- ec2:DescribeInstances
- ec2:DescribeInstanceStatus
- ec2:DescribeRouteTables
- ec2:CreateRoute
- ec2:DeleteRoute
- ec2:ReplaceRoute
- ec2:DescribeAddresses
- ec2:AssociateAddress
- ec2:DisassociateAddress
- ec2:DescribeNetworkInterfaces
- ec2:DescribeSubnets
- ec2:DescribeTags
我常用的是一个最小权限策略,写出来给大家参考:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "ec2:DescribeInstanceStatus", "ec2:DescribeRouteTables", "ec2:DescribeAddresses", "ec2:DescribeNetworkInterfaces", "ec2:DescribeSubnets", "ec2:DescribeTags", "ec2:CreateRoute", "ec2:DeleteRoute", "ec2:ReplaceRoute", "ec2:AssociateAddress", "ec2:DisassociateAddress" ], "Resource": "*" } ] }注意:这里Resource用了通配符,如果你们公司安全审计比较严格,可以把Resource限定到具体的VPC、路由表和ENI上,效果一样,但更安全。
我还建议给这个角色起一个一眼能看懂的名字,比如FortiGate-HA-Role。后面启动实例的时候,在“高级设置”里把IAM角色选上,FortiGate实例启动后就能通过实例元数据服务拿到临时凭证,不需要在设备里硬编码Access Key和Secret Key。这样不仅安全,还省去了定期换密钥的麻烦。
2.3 安全组放通清单:别让心跳和业务流量被拦
安全组是AWS上最容易被忽视的“隐形墙”。你FortiGate配置得再对,安全组没放通,心跳包发不过去,主备永远组不成集群。
我建议给FortiGate的外部接口、内部接口、心跳接口分别创建不同的安全组,不要一个安全组通吃,这样方便控制也方便审计。
| 安全组 | 方向 | 源/目的 | 协议端口 | 用途 |
|---|---|---|---|---|
| SG-FGT-Ext | 入站 | 0.0.0.0/0 | 业务端口(如TCP 443、TCP 80) | 公网访问业务 |
| SG-FGT-Ext | 入站 | 管理网段 | TCP 22、TCP 443 | 管理SSH和Web界面 |
| SG-FGT-Int | 入站 | VPC内私有网段 | 业务所需端口 | 内网流量转发 |
| SG-FGT-HB | 入站 | 主备心跳接口IP | TCP 703 | FGCP心跳 |
| SG-FGT-HB | 入站 | 主备心跳接口IP | TCP 5199 | 会话同步(某些版本) |
心跳端口这里特别说明一下。FGCP在AWS上使用单播模式时,心跳流量走的是TCP 703端口。如果你发现两台设备的心跳状态一直起不来,先别怀疑配置,用nc或者telnet从一台设备试连另一台的703端口,大概率是安全组把端口挡了。另外,部分FortiGate版本在做会话同步时还会用到TCP 5199端口,保险起见两个端口都放通。
提示:安全组的源IP建议精确到心跳接口的私有IP,不要用0.0.0.0/0。因为心跳接口属于管理面,暴露给整个VPC风险太大。
3. FortiGate HA核心配置实操
3.1 启动两台FortiGate实例,关键参数别选错
AWS Marketplace里有FortiGate的官方镜像,分PAYG(按量付费)和BYOL(自带许可)两种。做HA的话,我建议两台实例选同一个机型、同一个镜像版本,避免因固件版本不一致导致的主备同步异常。
启动实例时,有几个参数需要特别留意:
- IAM角色:在高级设置里选择前面创建的FortiGate-HA-Role。
- 实例类型:建议根据业务吞吐量选,生产环境至少c5.large起步,别用t2/t3突发型跑生产流量,丢包会教你做人。
- 网络选择:把实例放进提前规划好的子网,主设备放AZ-A的public-subnet-a,备设备放AZ-B的public-subnet-b。
- 网卡数量:FortiGate在AWS上一般会用多网卡,分别对应外部、内部、心跳。建议启动时就把ENI规划好,比如port1绑定外部子网,port2绑定心跳子网,port3绑定内部子网。
- 关闭“实例终止保护”:这个不是必须,但某些环境下如果开启了终止保护,自动化脚本在故障切换时可能无法正常停止旧实例,导致EIP无法解绑。
两台实例启动后,通过管理接口登录FortiGate,先把接口IP配上。这里我给一个常见的主备规划示例:
| 角色 | 可用区 | port1(外部) | port2(心跳) | port3(内部) |
|---|---|---|---|---|
| 主 | us-east-1a | 10.60.1.10/24 | 10.60.30.10/24 | 10.60.10.10/24 |
| 备 | us-east-1b | 10.60.2.10/24 | 10.60.30.20/24 | 10.60.20.10/24 |
接口配置用CLI或者Web界面都行,配完记得ping通对端心跳IP,确保网络层是通的。
3.2 用FGCP把两台设备拉成主备集群
网络通了之后,就可以在FortiGate上配置FGCP了。这里我用CLI演示,逻辑比Web界面更清晰。
在主设备上执行:
config system ha set mode a-p set group-id 1 set group-name "fortigate-aws-ha" set hbdev "port2" 50 set session-pickup enable set session-pickup-connectionless enable set unicast enable set unicast-peer 10.60.30.20 set override disable set priority 200 end在备设备上执行:
config system ha set mode a-p set group-id 1 set group-name "fortigate-aws-ha" set hbdev "port2" 50 set session-pickup enable set session-pickup-connectionless enable set unicast enable set unicast-peer 10.60.30.10 set override disable set priority 100 end几个参数解释一下:
- mode a-p:Active-Passive模式,主设备干活,备设备随时准备接管。
- hbdev port2 50:指定心跳接口为port2,50是心跳间隔权重,值越小优先级越高,可以理解为探测频率的权重配置。
- unicast enable:AWS不支持组播,必须开启单播模式。
- unicast-peer:指定对端心跳接口IP,主备互指。
- session-pickup enable:开启会话同步,这是业务无感切换的关键。
- priority:优先级高的会成为主设备。我把主设备设为200,备设备设为100。
配置完之后,在主设备上执行:
get system ha status能看到类似下面的输出,说明集群已经建立:
HA Health Status: OK Model: FortiGate-VM64 Mode: HA A-P Group Name: fortigate-aws-ha Group ID: 1 Priority: 200 HA State: primary如果HA State显示的是standalone,说明备设备没有成功加入集群,需要回头检查心跳端口和安全组。
3.3 用SDN Connector打通路由自动切换
FGCP集群起来之后,主备之间的会话同步已经工作了,但还有一个关键问题没解决:AWS路由表不会自己动。主设备挂了,备设备就算抢到了主角色,VPC路由表还是指向旧主设备的ENI,流量照样进不去。
这时候就要配置SDN Connector,让FortiGate在发生主备切换时自动调用AWS API改路由。
在FortiGate上配置SDN Connector:
config system sdn-connector edit "aws-connector" set type aws set region "us-east-1" set external-account-id "123456789012" set ha-status enable set update-interface "port1" "port3" next end这里的external-account-id是你的AWS账号ID,ha-status enable是告诉FortiGate,这个SDN Connector要和HA状态联动,发生切换时执行资源更新动作。update-interface指定哪几个接口参与资源更新,一般把外部接口和内部接口都加进去。
如果你的FortiGate实例没有绑定IAM角色,也可以用Access Key和Secret Key认证,但我前面说过,强烈建议用IAM角色。
接下来,还需要在FortiGate上配置路由策略,让SDN Connector知道哪些路由表需要管理。这一步在Web界面里是在“系统管理 > 网络 > SDN”里配置,关联好VPC和子网之后,FortiGate会自动发现对应的路由表。
配置完成后,可以在FortiGate上执行:
diagnose sdn-connector status确认SDN Connector和AWS API的连通性、权限是否正常。
注意:SDN Connector需要能发现你在AWS上创建的路由表。如果你把外部接口和内部接口放在不同的路由域,要确保fortigate的SDN Connector配置里把“所有相关路由表”都纳入管理,否则切换时可能会漏掉某一段路由。
3.4 验证高可用:从check到真实故障演练
集群配置完了,SDN Connector也通了,接下来最重要的事情是验证。
先做静态检查。在主设备上执行:
diagnose ha status应该能看到类似下面的信息:
Primary: 10.60.30.10, priority 200 Secondary: 10.60.30.20, priority 100再检查会话同步是否正常:
diagnose sys session stat确认主设备上的活跃会话能够被备设备学习到。如果会话同步没开启,你会发现备设备的session表几乎是空的,这种状态切过去,所有连接全部断。
静态检查通过后,一定要做一次真实故障演练。我是这么操作的:
- 找一台内网测试机,持续ping FortiGate的内部接口IP。
- 在AWS控制台里,手动停止主FortiGate实例。注意选择“停止”而不是“终止”,终止会影响后续恢复。
- 观察ping的丢包情况,以及备设备是否在几秒钟内接管主角色:
get system ha status - 检查VPC私有子网的路由表,确认默认路由的目标已经从旧主设备的ENI切到了新主设备的ENI。
- 如果有EIP绑在外部接口,检查EIP是否已经重新关联到新的主ENI。
如果你前面配置全部正确,整个过程应该非常顺滑。内网测试机的ping只会丢几个包,甚至完全不丢。如果发现了长时间中断,优先检查SDN Connector的状态、IAM权限、路由表更新是否成功。
4. 常见问题与排查实战
4.1 我在AWS上配FortiGate HA踩过的坑
我把这几年在AWS上配FortiGate HA遇到过的问题整理成一个速查表,每一行都是真实踩过的坑,不是网上抄来的:
| 现象 | 可能原因 | 排查与解决 |
|---|---|---|
| 备机心跳起不来,HA状态一直是standalone | 安全组没放通TCP 703 | 检查SG-FGT-HB安全组,telnet对端703端口测试 |
| 主备切换后路由表没更新 | SDN Connector权限不足 | 检查IAM角色是否包含ec2:ReplaceRoute、DeleteRoute |
| 切换后内网能通,但公网访问不通 | EIP没有跟随切到新主节点 | 在SDN Connector配置里检查external-ip关联,或手动重新绑定EIP |
| 主备配置不一致,经常被覆盖 | 固件版本不一致 | 统一两台实例的FortiOS版本和补丁级别 |
| 切换时有大量会话断开 | session-pickup没开或会话同步异常 | 确认session-pickup enable,检查TCP 5199端口 |
| 备设备上看到设备角色是primary,但云上路由没动 | SDN Connector没启用ha-status | 检查set ha-status enable配置 |
| 心跳频繁震荡,主备角色反复切换 | 心跳延迟过高或心跳接口流量过大 | 把心跳放到独立子网,避免和业务流量混跑 |
这里面最坑的是第三个:EIP没有跟随切换。很多人配置的时候,SDN Connector只关注了路由表,忽略了EIP的重新绑定。业务方反馈公网访问不了,你再去看EIP,还挂在已经停止的旧实例上。所以我在生产环境里,通常会把外部接口直接分配一个静态EIP,并且确认SDN Connector配置里对EIP关联的资源类型做了适配。
4.2 排查命令和日志定位技巧
如果你是在配HA过程中出了问题,下面几个命令能帮你快速定位,比在Web界面里四处点快得多:
# 查看HA整体状态 get system ha status # 查看HA详细诊断信息 diagnose ha status # 查看心跳接口收发包情况 diagnose netlink interface list port2 # 抓取心跳接口的FGCP报文 diagnose sniffer packet port2 'tcp port 703' 4 # 查看SDN Connector与AWS API通信状态 diagnose sdn-connector status # 查看HA相关的实时日志 diagnose debug application ha -1 diagnose debug enable如果心跳接口一直有收包但HA状态不对,我会先看sniffer抓包结果里是不是有FGCP的Hello报文。如果只有单方向的报文,说明另一端的发送有问题,要么安全组挡住了,要么unicast-peer配错了。
如果SDN Connector状态显示为down,优先查IAM角色的权限是不是给全了。AWS的权限策略有时候会因为通配符写得太窄,导致某个API没被允许,FortiGate的日志里会明确告诉你哪个API调用被拒绝了,照着加上就行。
4.3 大家常问的端口映射到底在哪做
聊完HA,我顺便回复一下经常在后台被问到的问题:FortiGate上的端口映射在哪里设置,特别是以前用50B这类小盒子的时候,总有人翻半天菜单找不到。
端口映射在FortiGate里分两步走,先做DNAT,再做放行策略。
第一步,在“Policy & Objects > Virtual IPs”里新建一个Virtual IP。把外部接口IP和公网端口映射到内网服务器的私有IP和端口。比如你想让公网访问内网一台10.60.10.50的Web服务器,外部端口8080映射到内网80,就在Virtual IP里填:
| 字段 | 值 |
|---|---|
| Name | web-dnat |
| Interface | port1(外部接口) |
| External IP | 公网EIP地址 |
| Mapped IP | 10.60.10.50 |
| Port Forward | 启用 |
| External Port | 8080 |
| Mapped Port | 80 |
第二步,在“Policy & Objects > Firewall Policy”里新建一条策略,源地址填公网或任意,目的地址选择刚才创建的web-dnat虚拟IP,服务选择HTTP,动作选ACCEPT,然后启用NAT。
这两步做完,公网访问EIP:8080就能转发到内网10.60.10.50:80。这个逻辑在50B、FortiGate VM、AWS上的虚拟实例完全一样,区别只是老设备登录IP一般是192.168.1.99,新云端实例是你自己分配的管理IP。
提示:做完端口映射如果还是不通,先别急着改配置,回头看两件事:一是安全组是否放行了外部端口,二是FortiGate有没有启用对应策略的日志,打开日志看drop计数最直接。
结尾再分享一点个人经验
在AWS上配FortiGate HA,最重要的不是敲命令那一瞬间,而是配完之后敢不敢做一次真正的破坏性测试。我见过太多团队,配置完看到HA状态是OK就觉得万事大吉,结果第一次真实故障才发现,路由表压根没切、EIP没跟着走、会话全断。所以我给自己定了一个规矩:任何HA方案交付前,必须做一次实例停止演练,而且要在业务低峰期,用真实流量验证。
另外,云端HA比物理机房HA多了一个看不见的风险——你依赖的AWS API本身也有调用频率限制。SDN Connector切换时需要执行多个API调用,如果IAM权限里的限流策略设置得过严,或者API调用并发过高,可能切换会变慢甚至失败。我的建议是给SDN Connector涉及的API调用留足余量,别把这类自动化操作和业务接口的配额混在一起评估。
最后一个小技巧:把两台FortiGate的HA状态接到你的监控系统里,不只是看主设备活着没,还要盯备设备的健康状态。很多时候备机已经悄悄掉群了,主设备还不知道,直到真正需要它顶上时才暴露问题。我在实际运维中吃过这个亏,后来加了两个监控项,一个看HA集群成员数,一个看备机的会话同步延迟,从此再没出过“以为有HA、其实没有HA”的尴尬。