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 规则,防止后续变更引入降级路径。