你的数据中心通过一条 Site-to-Site VPN 访问 AWS 上的工作负载,这条 VPN 已经平稳运行了一年。某天夜里,AWS 在例行维护中替换了一个隧道端点,所有到 VPC 的连接随即中断。防火墙上只配置了隧道 1。隧道 2 从创建那天起就一直显示 DOWN。
在大多数图里,Site-to-Site VPN 只是一条线。实际上它是两条 IPsec 隧道、两个 BGP 会话和一份 MTU 预算,故障往往出在这条线隐藏的部分。本文涵盖 IPsec 的组成部分、一个 AWS 示例、静态路由与 BGP 的对比、冗余、MTU 与 MSS、监控,以及什么时候专线更合适。
Site-to-Site VPN 与远程访问 VPN
Site-to-Site VPN 连接两个网络:两端的网关持有隧道,其后的主机不需要任何 VPN 软件。远程访问 VPN 连接的是单个设备,每台笔记本都装客户端,用户需要登录。如果真正的需求是让人访问内部应用,那么零信任架构中的身份感知代理往往比这两者都更合适。
IPsec 的组成部分
IKEv2(RFC 7296)负责认证对端并协商密钥。ESP(RFC 4303)负责加密流量。
| 组成部分 | 作用 | 常见选择 |
|---|---|---|
| IKE SA(阶段 1) | 认证对端并保护 IKE;UDP 500,NAT 之后用 4500 | AES-GCM、SHA-2、DH 组 14、19 或 20;8 小时 |
| Child SA(阶段 2) | 每个方向一个 ESP 安全关联 | AES-GCM;1 小时,提前重新协商 |
| ESP | 加密每个数据包:IP 协议 50,使用 NAT 穿越时为 UDP 4500 | 隧道模式 |
| Dead peer detection | 存活检测,用来清除或重启无响应的隧道 | 30 到 40 秒 |
| 基于路由的隧道 | 路由和 BGP 都能使用的隧道接口 | BGP 必需 |
IKEv2 通常用四条消息(IKE_SA_INIT 和 IKE_AUTH)建立 IKE SA 和第一个 Child SA。IKEv1 已在 2023 年被 RFC 9395 弃用。关于算法,RFC 8247 要求实现必须支持 DH 组 14,并推荐组 19;组 2、5、23 和 24 不应使用,组 22 禁止使用。
每个连接两条隧道:一个 AWS 示例
AWS Site-to-Site VPN 把你的客户网关设备连接到 AWS 一侧的网关。根据 AWS 隧道选项文档,每个连接都有两条隧道,各自有独立的公网 IP,终结在不同的 Availability Zone。
AWS 会因打补丁和硬件退役而替换隧道端点,每次只换一条隧道,所以只使用一条隧道的设备,每当该端点被替换时都可能失去连通。当某条隧道每天中断超过一小时,AWS Health 会每月发送一次通知。
每条隧道都有一个来自 169.254.0.0/16 的内部 /30。AWS 使用第一个可用地址,你的设备使用第二个,BGP 就在两者之间运行。除非把启动操作设为 start(仅 IKEv2),否则由你的设备发起 IKE。无论你的设备按什么顺序发送提议,AWS 都从其允许列表中的最小值开始评估,所以请在两侧都移除 IKEv1、SHA-1 以及 DH 组 2、5 和 22 到 24。
| Virtual private gateway | Transit gateway | |
|---|---|---|
| 连接对象 | 一个 VPC | 多个 VPC、VPN 和 Direct Connect |
| 每条隧道的带宽 | 1.25 Gbps | 1.25 Gbps,使用 Large Bandwidth Tunnels 时为 5 Gbps |
| 跨隧道 ECMP | 不支持 | 支持,需配合 BGP |
| 来自你设备的 BGP 路由数 | 100 | 1,000 |
| 额外费用 | 无 | Transit gateway 费用 |
用代码定义隧道,可以让两条隧道保持一致。在 Terraform 中,隧道 1 如下:
resource "aws_vpn_connection" "dc" {
vpn_gateway_id = aws_vpn_gateway.main.id
customer_gateway_id = aws_customer_gateway.dc.id
type = "ipsec.1"
static_routes_only = false
tunnel1_inside_cidr = "169.254.10.0/30"
tunnel1_ike_versions = ["ikev2"]
tunnel1_phase1_encryption_algorithms = ["AES256-GCM-16"]
tunnel1_phase1_integrity_algorithms = ["SHA2-384"]
tunnel1_phase1_dh_group_numbers = [20]
tunnel1_phase2_encryption_algorithms = ["AES256-GCM-16"]
tunnel1_phase2_dh_group_numbers = [20]
tunnel1_dpd_timeout_seconds = 30
tunnel1_dpd_timeout_action = "restart"
tunnel1_startup_action = "start"
# tunnel2_*: the same values with 169.254.10.4/30
}
静态路由还是 BGP
静态路由在连接上列出你的前缀,故障切换则交给设备的健康检查。使用 BGP 时,每条隧道运行一个 eBGP 会话,隧道一旦断开,会话中断,其路由随即被撤销。只要设备支持,AWS 就推荐用 BGP,而 ECMP 必须用 BGP。有四条规则:
- 使用互不相同的私有 ASN。 AWS 一侧默认是 64512。给你的站点分配自己的私有 ASN:64512 到 65534,或 4200000000 到 4294967294(RFC 6996)。
- 通告汇总路由。 Virtual private gateway 最多接受来自你设备的 100 条路由,这是固定上限。
- 绝不要让 CIDR 重叠。 VPC 的本地路由优先于任何 VPN 路由,即使后者更具体。请在各站点之间统一规划地址空间,或在一侧做 NAT。
- 了解选路的决胜顺序。 对同一个前缀,virtual private gateway 优先选 Direct Connect,然后是静态 VPN 路由,再是 BGP 路由;接着是最短的 AS 路径,最后是最低的 MED。
没有 ECMP 时,AWS 每次只让回程流量走一条隧道,并用 MED 标记。AWS 路由优先级指南的建议是允许非对称路由,并保持 AS 路径等长。如果你的有状态防火墙无法应对,就在隧道 2 上做 AS 路径前置并降低其 local preference;不过 AWS 出口路径一旦变化,就可能中断流。AWS 的示例配置使用 10 秒的 keepalive 和 30 秒的 hold time,而不是 RFC 4271 建议的 90 秒。
冗余设计
两条隧道能覆盖 AWS 一侧的故障。它们仍然共用你的设备、你的 ISP 和你的站点。
| 设计 | 隧道数 | 能承受 | 不能承受 |
|---|---|---|---|
| 一台设备,一个 ISP | 2 | AWS 端点维护 | 设备或 ISP 故障 |
| 两台设备,一个 ISP | 4 | 设备故障或打补丁 | ISP 中断 |
| 两台设备,两个 ISP | 4 | 设备或 ISP 故障 | 整个站点丢失 |
| 两个连接,Transit gateway ECMP | 4 条或更多 | 同上,带宽更大 | 单个流超过一条隧道的上限 |
有两台设备时,每台都有自己的 VPN 连接,并且都通告相同的前缀。ECMP 通过哈希把每个流分配到一条隧道,所以四条隧道合计约 5 Gbps,但单个 TCP 连接仍然最高只有 1.25 Gbps,而且有状态防火墙可能需要源 NAT 来保证对称。站点很多时,transit gateway 会成为中心辐射型网络的中心。
MTU 与 MSS 钳制
每个经过隧道的数据包都要带上新的 IP 头和 ESP 开销。AWS 最多支持 1,446 字节的 MTU 和 1,406 字节的 TCP MSS,不支持 Path MTU Discovery,也不支持巨型帧。确切数值取决于你的算法,依据 AWS 客户网关最佳实践如下:
| 加密与完整性 | NAT-T | 隧道 MTU | TCP MSS(IPv4) |
|---|---|---|---|
| AES-GCM-16 | 关 | 1446 | 1406 |
| AES-GCM-16 | 开 | 1438 | 1398 |
| AES-CBC,SHA-1 或 SHA2-256 | 关 | 1438 | 1398 |
| AES-CBC,SHA-1 或 SHA2-256 | 开 | 1422 | 1382 |
| AES-CBC,SHA2-512 | 开 | 1406 | 1366 |
设置隧道 MTU,并在两个方向上都钳制 TCP SYN 包的 MSS,因为双方各自通告自己的值。在 Linux 网关上:
ip link set dev vti1 mtu 1446
iptables -t mangle -A FORWARD -o vti1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1406
iptables -t mangle -A FORWARD -i vti1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1406
数值不对时的典型症状是:ping 和 SSH 正常,但文件复制会卡住。AWS 设备要求页面建议使用 1,399 字节,这个值也能工作,只是会浪费几个字节。
监控隧道
- 隧道状态。 CloudWatch 为每条隧道发布 TunnelState;对 BGP 连接,1 表示会话已建立。任何一条隧道低于 1 时就告警。TunnelDataIn 和 TunnelDataOut 显示哪条隧道在承载流量。
- 日志。 Site-to-Site VPN 日志会记录 IKE 状态、DPD 事件、BGP 状态和路由变化。
- 你的一侧。 按隧道监控 BGP 状态和收到的前缀。会话已建立但前缀为零,仍然是故障。
隧道起不来时,按层逐项检查:IKE SA、IPsec SA、对 AWS 内部地址的 ping,然后是 BGP。
什么时候迁移到 Direct Connect
| Site-to-Site VPN | Direct Connect | |
|---|---|---|
| 路径 | 公共互联网,已加密 | Direct Connect 站点上的私有线路 |
| 带宽 | 每条隧道 1.25 Gbps,使用 Large Bandwidth Tunnels 时为 5 Gbps | 托管型 50 Mbps 到 25 Gbps,专用型 1 到 400 Gbps |
| SLA | 每个连接 99.95% | 采用最高弹性模型时最高 99.99% |
| 加密 | 始终是 IPsec | 默认无;支持的专用端口可用 MACsec,或在上层叠加 IPsec |
当流量长期稳定在吉比特级、延迟很重要,或互联网出口费用高于一个端口的费用时,就该迁移。自 2026 年 9 月起,10 Gbps 和 100 Gbps 的专用连接可以使用包含同一档位内出站数据传输的统一费率。请把 VPN 留作备份:virtual private gateway 优先选择 Direct Connect 路由,所以只有线路故障时,流量才会走隧道。灾难恢复架构图讲的就是这类规划。
Site-to-Site VPN 图
图表内容
- On-premises data center · 10.20.0.0/16 · AS 65010
- Server LAN
- ERP database
- File server
- Edge firewall (customer gateway)
- VPC · eu-west-1
- Virtual private gateway · AS 64512
- Tunnel 1 endpoint
- Tunnel 2 endpoint
- Private subnet · eu-west-1a
- App instance
- Private subnet · eu-west-1b
- to 10.50.0.0/16
- Tunnel 1 · inside 169.254.10.0/30 · BGP .2 ↔ .1
- Tunnel 2 · inside 169.254.10.4/30 · BGP .6 ↔ .5
- 10.20.0.0/16
这张图的读法如下:
- 左侧是数据中心:AS 65010 中的 10.20.0.0/16。LAN 把发往 VPC 的流量送到边缘防火墙,也就是客户网关设备。
- 两条隧道通向 virtual private gateway 的两个端点,各有自己的内部 /30 和 BGP 会话。两条都处于启用状态,由 AWS 选择回程隧道。
- 右侧是 VPC:10.50.0.0/16,在两个 Availability Zone 中有私有子网,并有一条传播到 10.20.0.0/16 的路由。
- Markdown 块列出了两条隧道上必须一致的设置。
- 底部的注释说明了两条隧道能覆盖什么(端点替换)和不能覆盖什么(一台防火墙,一个 ISP)。
把 Site-to-Site VPN 图画清楚
- 给两端都加标签,写上 CIDR、ASN 和公网 IP。大多数 VPN 工单都从其中之一开始。
- 画出两条隧道,标明各自的内部 /30 和 BGP 对端,并说明哪条是首选以及原因。
- 把共用设置放进一个框里:IKE 版本、算法、DH 组、生存期、MTU 和 MSS。
- 标出单点故障,例如只有一台设备或一个 ISP。
- 不要画预共享密钥、ISP 内部细节和主机列表。
办公室一侧见网络拓扑图;子网和路由表见 AWS VPC 图。
在 Archboard 中构建
- 用 Google 或 GitHub 登录并创建一个图表。
- 为数据中心添加一个来自基础包的框架,用它的 CIDR 和 ASN 命名。在其中添加一个子网,里面放两个服务器节点和一个防火墙,全部来自网络包。
- 添加一个来自网络包的 VPC。在其中添加一个用于 virtual private gateway 的框架,里面放两个路由器节点,再添加两个私有子网节点,每个里面放一个来自云包的计算实例节点。
- 从防火墙到各端点画出隧道,两端都带箭头,并标上内部 /30 和 BGP 对端。添加从 LAN 到防火墙、从网关到子网的连线。
- 在两条隧道之间添加一个来自基础包的 Markdown 块,用来写共用设置,再添加文本注释。
如果 VPN 是用 Terraform 定义的,免费的 Terraform 转图表工具可以给你一个初稿;另见网络图。
这个示例共用 14 个图表节点,在 Free 套餐的限制之内。
常见问题
Site-to-Site VPN 图应该展示什么? 两个网络及其 CIDR、每个网关的公网 IP 和 ASN、每条隧道的内部地址、路由,以及双方必须一致的设置。
为什么 AWS Site-to-Site VPN 有两条隧道? 每个连接都有两条隧道,通向不同 Availability Zone 中的端点。AWS 每次只维护一条,所以两条都配置好之后,流量会转移而不是中断。
IPsec 上应该用静态路由还是 BGP? 只要设备支持,就用 BGP。它会自动撤销故障隧道的路由,而且 ECMP 需要它。静态路由适用于不支持 BGP 的设备。
AWS VPN 应该使用多大的 MTU 和 MSS? 使用 AES-GCM 且没有 NAT 穿越时,最大为 1,446 和 1,406 字节。CBC 加密和 NAT-T 需要使用 AWS 表中更小的值。
什么时候应该用 Direct Connect 而不是 VPN? 当流量长期稳定在吉比特级、延迟必须可预测,或者你需要最高 99.99% 的 SLA 时。请把 VPN 留作加密备份。