IPsec VPN 加固实战:IKEv2 配置指南

IPsec VPN 是企业远程接入与站点互联的主流方案,但默认配置常保留弱加密套件、启用 IKEv1 与野蛮模式,存在被降级协商和离线爆破的风险。本文给出基于 strongSwan 的 IPsec VPN 加固完整配置方案,包含 IKEv2 强制启用、AES-GCM 与 PFS 套件收敛、证书双向认证、DPD 存活检测、防火墙端口收敛与验证命令,适用于 Linux 网关搭建远程接入或隧道互联的生产环境。

适用场景

  • 需要为远程办公员工提供加密接入,替代明文或弱加密的 PPTP/L2TP 方案
  • 多机房、多云之间的站点到站点(Site-to-Site)隧道互联
  • 合规要求禁用 IKEv1、弱哈希(MD5/SHA1)与静态预共享密钥
  • 已部署 IPsec 但需要收敛加密套件、消除降级协商风险
  • 需要审计隧道加密强度并留存协商日志

前置条件

  • 一台具备公网固定 IP 的 Linux 网关(Debian 12 / Ubuntu 22.04 / CentOS 7+)
  • 已开放 UDP 500 与 UDP 4500 端口,或已规划自定义端口
  • 一个可解析的域名(用于证书 SAN,如 vpn.example.com)
  • root 权限,可修改内核转发参数与防火墙规则
  • 规划好客户端地址池(如 10.10.10.0/24)与内网网段(如 10.10.0.0/24)
# Debian / Ubuntu
apt-get update && apt-get install -y strongswan strongswan-pki \
  libcharon-extra-plugins libstrongswan-extra-plugins
# CentOS / RHEL(需 EPEL)
yum install -y epel-release && yum install -y strongswan
# 验证版本,建议 5.9 以上(swanctl 配置语法)
swanctl --version && ipsec --version

原理说明

IPsec 的加固核心在于两阶段协商的算法收敛。IKE 阶段(Phase 1)负责双方身份认证并生成 IKE SA,ESP 阶段(Phase 2)负责生成实际保护数据的子 SA。若任选一端允许 RSA-MD5、3DES 或 modp1024,攻击者即可尝试降级协商,把连接拖回可离线爆破的弱套件。

关键加固点如下:

  • 强制 IKEv2:IKEv1 的野蛮模式存在 ID 明文暴露与 PSK 离线爆破问题,直接禁用,只保留 IKEv2。
  • 算法白名单:IKE 与 ESP 均只允许 AES-GCM 与 SHA2 系列,DH 组不低于 modp2048 或 ecp256。
  • PFS(完全前向保密):ESP 阶段必须带独立 DH 组,否则 IKE SA 私钥泄露可回溯解密全部历史流量。
  • 证书双向认证:用 pubkey 替代 PSK,配合 CA 签发,避免共享密钥扩散。
  • DPD 死对端检测:及时回收被劫持或掉线的 SA,防止隧道悬挂。

操作步骤

1. 用 pki 生成 CA 与服务端证书

mkdir -p /etc/swanctl/x509 /etc/swanctl/x509ca /etc/swanctl/private
cd /etc/swanctl
# 生成 CA 私钥与自签根证书(有效期 10 年)
pki --gen --type rsa --size 4096 --outform pem > private/ca.key.pem
pki --self --ca --lifetime 3650 --in private/ca.key.pem \
  --dn "C=CN, O=Example, CN=Example VPN CA" --outform pem > x509ca/ca.crt.pem
# 生成服务端私钥与证书(SAN 必须与客户端填写的地址一致)
pki --gen --type rsa --size 4096 --outform pem > private/server.key.pem
pki --pub --in private/server.key.pem --type rsa | \
  pki --issue --lifetime 1825 --cacert x509ca/ca.crt.pem \
  --cakey private/ca.key.pem --dn "C=CN, O=Example, CN=vpn.example.com" \
  --san vpn.example.com --flag serverAuth --outform pem > x509/server.crt.pem
chmod 600 private/*.pem
# 把 CA 证书分发给客户端,用于校验服务端身份
ls -l x509/server.crt.pem x509ca/ca.crt.pem

2. 编写服务端 swanctl 配置

编辑 /etc/swanctl/conf.d/ikev2-vpn.conf,算法只保留 AES-GCM + SHA2,DH 组固定 ecp384:

connections {
  ikev2-vpn {
    local_addrs  = 203.0.113.10
    pools        = vpn-pool
    version      = 2
    proposals    = aes256gcm16-prfsha384-ecp384
    rekey_time   = 4h
    reauth_time  = 0
    dpd_delay    = 30s
    dpd_timeout  = 90s
    send_cert    = always
    unique       = replace
    local  { auth = pubkey  certs = server.crt.pem  id = vpn.example.com }
    remote { auth = pubkey }
    children {
      net {
        local_ts      = 10.10.0.0/24
        remote_ts     = 10.10.10.0/24
        esp_proposals = aes256gcm16-prfsha384-ecp384
        start_action  = trap
      }
    }
  }
}
pools {
  vpn-pool {
    addrs = 10.10.10.0/24
    dns   = 223.5.5.5, 119.29.29.29
  }
}
secrets {
  rsa-srv { file = server.key.pem }
}

3. 启用内核转发与地址转换

# 开启 IPv4 转发与外发流量 NAT(客户端访问公网)
sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.d/99-ipsec.conf
iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
# 放行 IKE 与 NAT-T 端口,其余入站按需收敛
iptables -A INPUT -p udp --dport 500  -j ACCEPT
iptables -A INPUT -p udp --dport 4500 -j ACCEPT
iptables -A INPUT -p esp -j ACCEPT

4. 签发客户端证书并下发

远程接入场景应一人一证,禁止多人共用同一证书,便于离职后按证书吊销。每名员工生成独立密钥与证书,私钥不出本地:

# 为员工 alice 签发客户端证书(可加多行 --san 或用 --san-policy 限制)
pki --gen --type rsa --size 4096 --outform pem > private/alice.key.pem
pki --pub --in private/alice.key.pem --type rsa | \
  pki --issue --lifetime 365 --cacert x509ca/ca.crt.pem \
  --cakey private/ca.key.pem --dn "C=CN, O=Example, CN=alice" \
  --san alice --flag clientAuth --outform pem > x509/alice.crt.pem
# 客户端需要拿到:CA 根证书、本人证书、本人私钥(私钥不经邮件传输)
ls -l x509/alice.crt.pem private/alice.key.pem x509ca/ca.crt.pem

如需按身份限制可访问网段,可在服务端用 remote { id = alice } 配合独立的 children 分支,把不同员工分流到不同 local_ts,实现最小可达范围。

5. 启动并检查协商状态

systemctl enable --now strongswan
swanctl --load-all          # 加载证书、连接与密钥
swanctl --list-conns        # 查看连接已就绪
swanctl --list-sas          # 客户端接入后查看已建立的 SA

配置验证

  • swanctl --list-sas 输出中 ESP 加密套件应为 aes256gcm16-prfsha384-ecp384,若出现 sha1 或 modp1024 说明存在旧配置残留。
  • 用 ipsec statusall 确认 IKEv2 与 ESTABLISHED 状态,并通过 state 字段观察重协商。
  • 从客户端执行 ping 10.10.0.1 与 ip route,确认路由已注入且走隧道。
  • 抓包核对:tcpdump -ni eth0 udp port 500 or udp port 4500,确认握手全程未出现 IKEv1 载荷。
  • 断网演练:断开客户端网络后,服务端应在 90s 内回收 SA,swanctl --list-sas 不再残留。

常见问题(FAQ)

Q1:客户端提示 no matching proposal / NO_PROPOSAL_CHOSEN 怎么办?

这是算法不匹配。先查日志:journalctl -u strongswan -n 100 或 swanctl --log。常见原因是客户端仍带 aes128-sha1-modp1024。解决方式是两端使用完全一致的 proposals 字符串,并在服务端日志确认最终选中的套件,切勿为兼容旧客户端而放开 SHA1。

Q2:为什么隧道不通但 SA 显示已建立?

多为路由或 NAT 问题。检查三点:一是 local_ts/remote_ts 网段是否与客户端实际内网一致;二是服务端是否已开启 ip_forward;三是客户端是否遗漏了 NAT 后的 nat_traversal = yes。用 ip xfrm state 可确认 ESP 是否真正在转发。

Q3:如何进一步防止 IKE 端口被扫描与爆破?

将服务端口改为非标(如 4500 之外的 UDP 端口)并同步客户端配置;同时用 iptables 限制来源 IP 段,只允许已知出口访问。IPsec 已用证书认证,无需再依赖 PSK,但端口收敛仍能显著降低噪音。

Q4:员工离职后如何立即切断其隧道权限?

两步走:一是在服务端删除或注释该身份对应的连接分支并执行 swanctl --terminate --ike <id> 立即断开现有 SA;二是把其证书序列号加入 CRL,或在 CA 侧用 pki --crl 生成吊销列表并配置服务端加载 CRL,防止其用旧证书重新接入。仅删除配置文件而不吊销证书,无法阻止再次握手。

Q5:服务端日志里如何快速确认没有降级协商?

用 journalctl -u strongswan | grep -i "selected proposal" 过滤历史协商记录,逐条核对选中的套件是否为 aes256gcm16-prfsha384-ecp384。若出现其他套件,说明有客户端未被更新到统一配置,必须定位并替换,否则加固形同虚设。

加固检查清单

  • IKE 版本仅保留 v2,version = 2 且未启用 aggressive。
  • IKE 与 ESP 的 proposals 全部为 AES-GCM + SHA2,DH 不低于 ecp256/modp2048。
  • ESP 阶段带独立 DH,PFS 生效,无静态密钥复用。
  • 认证方式为 pubkey,证书由自建 CA 签发且 SAN 与访问地址一致。
  • DPD 已启用,断连后 90s 内回收 SA。
  • UDP 500/4500 仅对必要来源开放,其余入站默认拒绝。
  • 证书有效期不超过 1 年,且已配置吊销流程与 CRL。

总结

IPsec VPN 的安全强度取决于最弱的那一个算法,而非最强项。本文通过强制 IKEv2、收敛至 AES-GCM + ecp384、启用证书双向认证与 PFS、配合 DPD 与端口收敛,把协商面压到最小。落地后务必用 swanctl --list-sas 与抓包双重验证实际选中的套件,并定期复查内核转发与 NAT 规则,防止后续变更引入降级路径。