Openwrt路由器 配置 chacha20 IKEv2 VPN Server

@vrqq  June 15, 2026

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

后记 HowTo debug

  • 查看XFRM情况 ip xfrm policyip xfrm state
  • 抓包 tcpdump -ni any host 192.168.22.100tcpdump -ni swanctl_xfrm
  • 测试路由配置 ip route get 192.168.22.100 from 192.168.9.1

添加新评论