OpenWrt路由器做内网网关,配置 iOS / MacOS 客户端连入内网。
Keywords:
- AEAD-Chacha20加密,双向证书登录(非用户名密码登录)
- XFRM虚拟网卡(interface)
原理介绍及准备
证书登录
所有人都信任同一个CA证书,每个人持有各自的子证书(由上述CA签发),通过对方子证书上面写的CommonName确定对方身份 用上述CA验证对方子证书是否为真。
使用以下命令准备CA、server和client证书
IPSEC IKEv2 VPN中
- IKEv2 中 登录(IKE) 和 数据传输(ESP) 是两套加密算法。
- 在Openwrt LUCI strongswan界面中只允许配置证书登录,其中:Remote为拨入当前机器的对方身份验证(IKE),Tunnel为TCP/IP加密传输管道(ESP),Encryption是"加密算法策略组"(ESP Proposal打勾说明是ESP策略组,否则是IKE策略组)。
- Tunnel可以理解成,身份验证成功后 由stongswan-app新增了一块虚拟网卡 并修改了本机路由表,路由表里配置的源地址、目标地址就是tunnel里面写的Local/Remote Subnet。
- 后文我们直接改 /etc/config/ipsec 配置文件,它会自动同步到LUCI html界面中。
Strongswan的两种工作模式
- Transport 基于现有路由表 不修改TCP/IP的dst/src包头 只加密包内数据payload
- Tunnel 基于Kernel提供的XFRM模块 可以看作内核给strongswan分配了一块虚拟interface(详见下文“为什么不需要给XFRM网卡指定IP”)。
strongswan XFRM
XFRM是linux kernel中的虚拟网卡组件,为了方便防火墙基于网卡过滤包。简而言之:
- 若不开启XFRM,在openwrt server侧收到的VPN数据包 来源网卡是WAN IP为LAN和IP Pool的 IP地址
- 若开启XFRM并指定XFRM interface ID,则strongswan服务收到的Tunnel数据包,将通过kernel假装从这块网卡出来,再传输进系统。
我们在openwrt LUCI -> Network -> Interface 中新建一个interface
- Protocol: IPsec XFRM
- Name: swanctl_xfrm
- XFRM-ID: 111
- 注意不需要给这块网卡指定IP,也不需要开启DHCP服务,给连入客户端分配IP由下文的swanctl.conf负责
然后再给这块XFRM配置一个Routing:OpenWrt LUCI -> Network -> Routing -> Static IPv4 Routes
- Interface: swanctl_xfrm
- Route type: unicast
- Target: 192.168.22.0/24
为什么不需要给XFRM网卡指定IP
一个外来的TCP/IP数据包流向为 Internet -> firewall -> self_cpu.strongswan -> XFRM(interface) -> firewall -> other_machine_in_lan
- 我们传统的网卡配置 需要指定本机网卡IP,是为了给 当前网卡出去的包 标注SourceIP 以便接收方知晓来源,返回包有去处。
在这里一个远端来的 “TCP/IP包” 的路由过程 用不到这块网卡的IP,例如:
- 当VPN连接建立后 经strongswan解密后,XFRM interface显示 收到远端一个包 src=192.168.22.101 dst=192.168.9.50;
- 该包通过XFRM传出后 直接进入nftable/iptable 做匹配。
- 在LAN内一台主机的192.168.9.50的某个app 收到了这个包并回复给了他,这个回复消息src=192.168.9.50 dst=192.168.22.101
- 该回复消息先到达192.168.9.1 (因为没有直接到达.22.x的路由 故进入.50主机眼中的default gateway)
- 192.168.9.1的nftable做匹配 然后放行,检查路由表,发现该包应从 swanctl_xfrm 送出
- 该回复包进入 swanctl_xfrm 后,由strongswan 收到并加密传输给远端client
- 换个角度思考:传统的网卡指定IP是为了给上游和本机的nftable看 同时下游程序通过listen on IP机制收包,而XFRM网卡的上游 直接通过XFRM绑定到了特定程序了(strongswan)。
Openwrt侧配置
安装依赖包apk add strongswan-full kmod-crypto-aead kmod-crypto-lib-chacha20poly1305 xfrm kmod-nft-xfrm luci-proto-xfrm
- strongswan-full并没有包含 kmod-crypto-aead依赖,故若漏装
kmod-crypto-aead,在运行过程中log会报无法处理这种加密形式
/etc/config/ipsec
config crypto_proposal 'ike_sa'
option encryption_algorithm 'chacha20poly1305'
option dh_group 'curve25519'
option prf_algorithm 'prfsha512'
config crypto_proposal 'esp_sa'
option is_esp '1'
option encryption_algorithm 'chacha20poly1305'
option dh_group 'ecp521'
config tunnel 'hometun'
option startaction 'start'
option closeaction 'none'
option dpdaction 'start'
list crypto_proposal 'esp_sa'
list local_subnet '192.168.9.0/24'
list remote_subnet '192.168.22.0/24'
option if_id '111'
config ipsec
list zone 'lan'
option debug '2'
list listen 'lan'
list listen 'wan_pppoe'
config remote 'certlogin'
option enabled '1'
option authentication_method 'pubkey'
option local_identifier 'ikev2-server-1.vrqq.org'
option remote_identifier '%any'
option local_cert 'server-cert.pem'
option local_key 'server-key.pem'
option ca_cert 'ca.crt'
option send_cert 'always'
option send_certreq 'yes'
option fragmentation 'yes'
option keyingtries '3'
option dpddelay '30s'
option encap 'true'
option keyexchange 'ikev2'
list tunnel 'hometun'
option gateway 'any'
list pools 'primaryipv4'
list crypto_proposal 'ike_sa'
config pools 'primaryipv4'
option addrs '192.168.22.100-192.168.22.199'
list dns '192.168.9.1'
config crypto_proposal 'ike_iosdefault'
option encryption_algorithm 'aes256gcm128'
option dh_group 'ecp256'
option prf_algorithm 'prfsha256'
config crypto_proposal 'esp_iosdefault'
option is_esp '1'
option encryption_algorithm 'aes256gcm128'
option dh_group 'ecp256'Startup/etc/init.d/swanctl start 该程序会生成/var/swanctl/swanctl.conf
iPhone mobileconfig配置(iOS和MacOS通用)
在设置中默认添加的VPN 不会向服务器端协商chacha20有关的加密方式,我们只能通过AppleConfigure生成
- Certificates: 上传p12并写解证书的密码
VPN
- Connection Type: IKEv2
- Server: <your_server_address>
- Remote ID: ikev2-server-1.vrqq.org (注意和strongswan配置一致)
- Local ID: client-1
- Machine Auth: Certificate
- ID Certificate: 选择上面传进去的证书
- Certificate Type: ECDSA384 (注意和ipsec配置保持一致)
- Server Certificate Issuer CN:
CA证书的CommonName - Server Certificate CN: 留空表示不要求CN
- IKE SA Param: Encryption=Chacha20Poly1305, Intergrity=SHA2-512, DHGroup=31 (注意和ipsec配置保持一致,此处的31指的是ecp256)
- DNS Server: 192.168.9.1 (必填)
Reference
- 密码登录的strongswan配置方法: https://blog.vrqq.org/archives/58/
- IPsec 配置备忘 Part1 - IKEv2 基础: https://recursiveg.me/2020/10/ipsec-configurations-part1/
- strongswan与xfrm之间的trap机制: https://www.cnblogs.com/hugetong/p/10271736.html
- IPsec Modern IKEv2 Road-Warrior Configuration: https://openwrt.org/docs/guide-user/services/vpn/strongswan/roadwarrior
后记 HowTo debug
- 查看XFRM情况
ip xfrm policy和ip xfrm state - 抓包
tcpdump -ni any host 192.168.22.100和tcpdump -ni swanctl_xfrm - 测试路由配置
ip route get 192.168.22.100 from 192.168.9.1