Files
Knowledge/sunyard/7 信安/SSL VPN/听说你觉得VPN简单?手撸一遍_IPsec.md

180 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
个人博客:www.fuzoupyy.work
前两天有个刚做网络的小兄弟问我:“现在不都流行SSL VPN或者[WireGuard](https://zhida.zhihu.com/search?content_id=266937248&content_type=Article&match_order=1&q=WireGuard&zhida_source=entity)了吗?[IPsec](https://zhida.zhihu.com/search?content_id=266937248&content_type=Article&match_order=1&q=IPsec&zhida_source=entity)这种‘老古董’是不是没必要学了?”
我当时差点一口老血喷屏幕上。
兄弟,你这就好比在说,现在开自动挡的车多了,手动挡的原理就不重要了?IPsec这玩意儿,就像是网络世界的“重型装甲车”,它是笨重,配置是繁琐,但在Site-to-Site(站点对站点)的连接上,它依然是无可撼动的霸主。你看看现在的公有云,AWS也好,阿里云也罢,跟IDC做专线互联备份的时候,哪个推荐的不是IPsec?
别看WireGuard现在火得一塌糊涂,真到了复杂的企业级环境,还得是IPsec坐镇。
今天咱们就来扒一扒IPsec的底裤,顺便教大家用开源神器[StrongSwan](https://zhida.zhihu.com/search?content_id=266937248&content_type=Article&match_order=1&q=StrongSwan&zhida_source=entity)搭建一套企业级的VPN。
### **为什么IPsec让人头大?**
咱们先不谈配置,先聊聊为什么这玩意儿难懂。
绝大多数人晕菜,是因为被IKE、[ISAKMP](https://zhida.zhihu.com/search?content_id=266937248&content_type=Article&match_order=1&q=ISAKMP&zhida_source=entity)、[ESP](https://zhida.zhihu.com/search?content_id=266937248&content_type=Article&match_order=1&q=ESP&zhida_source=entity)、[AH](https://zhida.zhihu.com/search?content_id=266937248&content_type=Article&match_order=1&q=AH&zhida_source=entity)、Phase 1、Phase 2这些缩写给绕晕了。
其实,你把IPsec想象成**“押镖”**。
你要把一车黄金(数据包)从北京运到上海。路上有土匪(黑客),你不能直接运。
**第一种方式:AH(Authentication Header)** 这就像是在车厢上贴了个封条,上面盖了皇帝的印(签名)。到了上海,一看封条没坏,就知道东西没被换过,也是朝廷发出来的。 **但是!** 封条只能保证东西没被换,**它不加密**。黄金还是黄金,土匪在路边能看个精光。而且,最坑爹的是,AH会对整个IP头做签名。大家都知道现在网络到处都是NAT(地址转换),路由器一改IP地址,签名就这就对不上了,封条就“碎”了。所以,**在现在的网络环境里,AH基本就是个废柴,很少用。**
**第二种方式:ESP(Encapsulating Security Payload)** 这个厉害了。它不仅贴封条,还把黄金装进了保险箱(加密)。土匪截了车,只能看到一个铁箱子,里面是啥完全不知道。 ESP最骚的操作是“隧道模式”。它不光把数据加密,它还把原来的车牌(原IP头)也给拆下来扔进保险箱,然后在外面挂个新车牌(新IP头)。这就是为什么我们在隧道里抓包,只能看到两个网关之间的公网IP在通信,完全看不到内网IP。
### **那个让人抓狂的协商过程:IKE**
真正让人掉头发的,是IKE(Internet Key Exchange)。
你想啊,两个网关(路由器或服务器)素不相识,怎么建立信任?怎么商量用什么密码?直接在公网上喊:“喂!密码是123456!”那不找死吗?
所以得谈判。这个谈判过程就是IKE。
**第一阶段(Phase 1):建立管理连接** 这就像两个外交官见面,先得在一个绝对安全的屋子里坐下来。 他们要确认对方身份(Pre-Shared Key预共享密钥,或者证书),然后商量:“咱俩待会怎么聊天?用什么加密算法?” 这一步要是通了,就建立了一个叫**ISAKMP SA**的东西。你可以理解为,外交官的保密电话接通了。
这里有个大坑。Phase 1有两种模式:**主模式(Main Mode)**和**野蛮模式(Aggressive Mode)**。 名字听着挺唬人。主模式慢,一来一回6个包,但是安全,它会隐藏身份信息。野蛮模式快,3个包搞定,但是它会把身份ID明文广播出去。 以前为了快,很多老设备喜欢用野蛮模式,现在为了安全,大家基本都切回主模式了。
**第二阶段(Phase 2):建立数据连接** 外交官电话通了(Phase 1成功),现在开始聊正事:怎么运黄金。 这时候商量的才是真正用来加密用户数据的密钥(IPsec SA)。 这就是所谓的“快速模式”(Quick Mode)。
这也是为什么你看日志的时候,经常看到Phase 1过了,Phase 2报错。通常是因为两边的“感兴趣流”(Subnet,也就是你要通的内网网段)没对上。左边说我要通192.168.1.0/24,右边配置写的是192.168.2.0/24,聊不到一块去,崩了。
### **[NAT-T](https://zhida.zhihu.com/search?content_id=266937248&content_type=Article&match_order=1&q=NAT-T&zhida_source=entity):穿越NAT的救命稻草**
刚才说了,AH过不了NAT。其实ESP过NAT也费劲。 因为NAT路由器会修改端口号,而IPsec设计之初是基于IP层的,没端口号这概念(ESP协议号是50)。
为了解决这个问题,聪明的工程师搞了个**NAT-T(NAT Traversal)**。 简单说,就是把ESP数据包再包一层UDP头部,通常是用UDP 4500端口。这样NAT路由器一看:“哦,是UDP啊,改端口我会!” 于是,IPsec就能在NAT环境里活下来了。
**敲黑板:** 如果你的VPN服务器在防火墙后面,记得防火墙除了开**UDP 500**(IKE协商用),还得开**UDP 4500**(NAT穿透用)。好多人配半天不通,就是因为4500端口没开。
---
### **实战:用StrongSwan搭建从阿里云到本地IDC的隧道**
理论扯多了容易困,咱们来点实操。 Linux下做IPsec,以前有Openswan、Libreswan,但现在**StrongSwan**是绝对的一哥。它对IKEv2的支持最好,配置也相对“阳间”一点(虽然也没好到哪去)。
假设场景:
- **阿里云(左边 Left):**
- 公网IP:1.1.1.1
- 内网段:172.16.0.0/16
- **本地IDC(右边 Right):**
- 公网IP:2.2.2.2
- 内网段:192.168.10.0/24
系统咱们就用[CentOS 7](https://zhida.zhihu.com/search?content_id=266937248&content_type=Article&match_order=1&q=CentOS+7&zhida_source=entity)或者[Ubuntu 20.04](https://zhida.zhihu.com/search?content_id=266937248&content_type=Article&match_order=1&q=Ubuntu+20.04&zhida_source=entity),都差不多。
**1. 安装StrongSwan** 这就不用我教了吧? `yum install strongswan` 或者 `apt install strongswan`。
**2. 开启内核转发(这点最容易忘!)** 很多人配好了VPN,发现ping不通内网,查了一圈发现是Linux没开启路由转发。 编辑 `/etc/sysctl.conf`:
```bash
net.ipv4.ip_forward = 1
# 如果有IPv6也顺手开了
net.ipv6.conf.all.forwarding = 1
```
执行 `sysctl -p` 生效。
**3. 配置 ipsec.conf** 这是核心配置文件。虽然StrongSwan出了新的 `swanctl.conf` 格式,但为了照顾老玩家的习惯,咱们还是用经典的 `ipsec.conf`。
阿里云那台机器(1.1.1.1)的配置 `/etc/strongswan/ipsec.conf`:
```bash
config setup
# 开启调试日志,排错的时候很有用,平时可以关了
charondebug="ike 2, knl 2, cfg 2"
uniqueids=no
​
conn ali-to-idc
authby=secret # 使用预共享密钥认证
auto=start # 服务启动时自动连接
type=tunnel # 隧道模式
keyexchange=ikev2 # 强烈建议用IKEv2,比v1快且稳
# 左边(本机/阿里云)配置
left=1.1.1.1 # 本机公网IP
leftid=1.1.1.1 # 标识ID,通常和IP一样
leftsubnet=172.16.0.0/16 # 本机要暴露给对端的内网段
# 右边(远端/IDC)配置
right=2.2.2.2
rightid=2.2.2.2
rightsubnet=192.168.10.0/24
# 加密算法(这个得两边商量好,必须一模一样!)
ike=aes256-sha256-modp1024!
esp=aes256-sha256!
# 存活检测
dpddelay=30s
dpdtimeout=120s
dpdaction=restart
```
**本地IDC那台机器的配置,基本就是反过来。** 把 `left` 换成 2.2.2.2,`right` 换成 1.1.1.1,subnet也对调一下。
这里有个细节:**`left` 不一定非得写公网IP。** 如果你的服务器是在NAT后面(比如AWS EC2,或者家里路由器后面的虚拟机),`left` 其实应该写内网IP,然后 `leftid` 写公网IP。这块逻辑如果没理顺,StrongSwan根本起不来。
**4. 配置密码 ipsec.secrets** 这个文件简单,就是存密码的。两边得一样。
```bash
# 格式:IP1 IP2 : PSK "你的超强密码"
1.1.1.1 2.2.2.2 : PSK "YoyouIsHandsome2025"
```
记得这个文件权限要设成600,不然StrongSwan会报错说不安全。
**5. 启动与排错** 启动:`systemctl start strongswan` 查看状态:`strongswan statusall`
如果一切顺利,你会看到类似 `Security Associations (1 up, 0 connecting)` 的字样,那就是通了!
### **要是通不了怎么办?(运维的日常崩溃)**
这时候就显出真本事了。 要是状态里显示 `CONNECTING` 然后一直卡着,或者直接 `0 up`,千万别慌。
**第一招:看日志。** `tail -f /var/log/syslog` 或者 `/var/log/messages`。 如果你看到 `NO_PROPOSAL_CHOSEN`,这绝对是两边加密算法没对齐。比如一边配了AES128,另一边是AES256;或者一边是SHA1,另一边是SHA256。仔细检查 `ike=` 和 `esp=` 这两行。
**第二招:检查防火墙。** 再强调一遍,UDP 500 和 UDP 4500。 还有,云厂商的安全组!阿里云的安全组入方向开了吗?
**第三招:MSS(最大报文段长度)问题。** 这是个隐形杀手。 VPN加上了ESP头,包变大了。如果原来是1500字节,加上头就超了,会被分片或者丢弃。 现象就是:**ping是通的,但SSH连不上,或者网页打不开。** 这时候需要在防火墙(iptables)里做个手脚,把MSS改小点:
```bash
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
```
或者暴力点,直接设成1300:
```bash
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1300
```
这招下去,90%的“怪病”都能好。
### **总结**
说实话,配置IPsec VPN是一件挺枯燥的事,配置文件里哪怕多了一个空格,或者少了一个感叹号,都能让你查半天。
但这就是运维的价值所在啊。 当那条隧道打通,两边内网的数据像流水一样无缝传输的时候,那种成就感,真的是WireGuard这种“傻瓜式”工具给不了的(虽然我也很爱WireGuard,哈哈)。
而且,搞懂了IPsec,你再去看SD-WAN,看云专线,其实底层逻辑都是通的。
我知道这篇内容有点硬,可能大家得消化一会儿。建议收藏起来,下次被VPN折磨的时候,拿出来对一对配置,说不定就救了你的命。
技术这东西,没有什么捷径,就是一遍遍试错试出来的。
如果你在配置过程中遇到了奇葩的报错,或者对加密算法的选择有疑问,欢迎在评论区留言,咱一起探讨探讨。