strongSwan IPsec Configuration via UCI
Linux Charon IPsec daemon can be configured through /etc/config/ipsec.
Note: this has been updated to the swanctl-based configuration, and is current as of 5.9.5 packaging. For previous versions, use the Wiki's page history functionality.
Sections
ipsec
| Type | Name | Type | Required | Default | Description |
|---|---|---|---|---|---|
| option | zone | string | no | vpn | Firewall zone. Has to match the defined firewall zone |
| list | interface | string | yes | (none) | Interface that accept VPN traffic (empty for all interfaces, multiple lines for several interfaces) |
| option | debug | number | no | 0 | Trace level: 0 is least verbose, 4 is most - logs visible from output of logread -f |
remote
Contains tunnel definition.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| enabled | boolean | yes | (none) | Configuration is enabled or not |
| gateway | ipaddr | yes | (none) | IP address or FQDN name of the tunnel remote endpoint, or permitted subnets that peers can initiate this configuration from (analogue to local_leftip) |
| local_gateway | ipaddr | no | (none) | IP address or FQDN of the tunnel local endpoint |
| local_sourceip | ipaddr | no | (none) | Virtual IP(s) to request in IKEv2 configuration payloads requests, or in IKEv1 mode config (enables sending them/initiating it instead of quick mode) |
| local_ip | ipaddr | no | (none) | Local address(es) to use in IKE negotiation when initiating; for responding, enumerates addresses we can negotiate from (and may by subnets or CIDRs) |
| local_identifier | string | no | (none) | Local identifier for IKE (phase 1) |
| remote_identifier | string | no | (none) | Remote identifier for IKE (phase 1) |
| authentication_method | string | yes | (none) | IKE authentication (phase 1). Only allowed value ath the moment is psk |
| pre_shared_key | string | no | (none) | The preshared key for the tunnel if authentication is psk |
| crypto_proposal | list | yes | (none) | List of IKE (phase 1) proposals to use for authentication (see below) |
| tunnel | list | yes | (none) | Name of ESP/AH (phase 2) section (see below) |
| keyingtries | integer | no | 3 | Number of retransmissions to attempt during initial negotiation |
| dpddelay | interval | no | 30s | Liveness interval for IKE |
| encap | boolean | no | false | Force UDP encapsulation of ESP packets to work around blocking of ESP packets. |
| inactivity | interval | no | (none) | Interval before closing an inactive CHILD_SA |
| fragmentation | string | no | yes | Use IKE fragmentation (maybe “yes”, “accept”, “force”, or “no”) |
| mobike | string | no | yes | Enable MOBIKE on IKEv2 |
| local_cert | string | no | (none) | List of cert pathnames to use for authentication |
| local_key | string | no | (none) | List of private key pathnames to use with above certificates |
| remote_ca_certs | list | no | (none) | List of names of CA certificates that need to lie in remote peer's certificate's path of trust |
| rekeytime | interval | no | (none) | IKEv2 interval to refresh keying material; also used to compute lifetime |
| overtime | interval | no | (none) | Limit on time to complete rekeying/reauthentication (defaults to 10% of rekeytime) |
| send_cert | string | no | ifasked | Send certificate payloads when using certificate authentication. (“always”, “ifasked”, “never”) |
| send_certreq | boolean | no | no | Send certificate request payloads to offer trusted root CA certificates to the peer. |
| keyexchange | string | no | ikev2 | Version of IKE to negotiation (“ikev1”, “ikev2”, or “ike” for both) |
crypto_proposal
Definition of encryption proposals. Derived from strongSwan cipher suites
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| encryption_algorithm | string | yes | (none) | Encryption method (aes128, aes192, aes256, 3des) |
| hash_algorithm | string | yes | (none) | Hash algorithm (md5, sha1, sha2, ...) not permitted when an AEAD algorithm is used |
| dh_group | string | yes | (none) | Diffie-Hellman exponentiation (modp768, modp1024, ...) |
| prf_algorithm | string | no | (none) | Pseudo-Random Functions to use with IKE (prfmd5, prfsha1, prfsha256, ...); not applicable to ESP |
tunnel
Contains network defintion per tunnel.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| local_subnet | list | yes | (none) | Local network(s) one per line |
| remote_subnet | list | yes | (none) | Remote network(s) one per line |
| local_nat | subnet | no | (none) | NAT range for tunnels with overlapping IP addresses |
| crypto_proposal | list | yes | (none) | List of ESP (phase two) proposals |
| startaction | string | no | route | Action on initial configuration load (none, start, route) |
| updown | string | no | (none) | Path to script to run on CHILD_SA up/down events |
| lifetime | interval | no | (none) | Maximum duration of the CHILD_SA before closing (defaults to 110% of rekeytime) |
| rekeytime | interval | no | (none) | Duration of the CHILD_SA before rekeying |
| dpdaction | string | no | (none) | Action done when DPD timeout occurs (may be “none”, “clear”, “hold”, “restart”, “trap”, or “start”) |
| closeaction | string | no | route | Action done when CHILD_SA is closed (may be “add”, “route”, “start”, “none”, or “trap”) |
| if_id | string | no | (none) | XFRM interface ID set on input and output interfaces (should be coordinated with “ifid” values in route entries on “xfrm” interfaces) |
| priority | string | no | (none) | Priority of the CHILD_SA |
| ipcomp | bool | no | false | Enable ipcomp compression |
| hw_offload | bool | no | false | Enable H/W offload |
mschapv2_secrets
Contains EAP secrets for authentication.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| id | string | yes | (none) | EAP ID (i.e. Username) |
| secret | string | yes | (none) | EAP Secret (i.e. Password) |
Example site-to-site
For a road-warrior setup, see IPsec Modern IKEv2 Road-Warrior Configuration
Local configuration for /etc/config/ipsec:
config 'ipsec' # useful so traffic isn't sourced from internal addresses, # which would then requiring NATting and port 4500, etc. list 'interface' 'wan' option 'zone' 'vpn' config 'remote' 'acme' option 'enabled' '1' # address of wan device option 'local_ip' '6.6.6.6' # peer has routable DHCP'd address which changes option 'gateway' 'any' option 'authentication_method' 'pubkey' option 'local_identifier' 'C=US, O=Acme Corporation, CN=headquarters' option 'remote_identifier' 'C=US, O=Acme Corporation, CN=soho' option 'local_cert' 'headquarters.crt' option 'local_key' 'headquarters.key' option 'rekeytime' '4h' option 'keyingtries' '0' option 'mobike' '0' option 'fragmentation' '1' list 'remote_ca_certs' 'acme.crt' # hardening, require remote to be signed by acme.crt list 'crypto_proposal' 'ike_proposal' list 'tunnel' 'tun_soho' config 'crypto_proposal' 'ike_proposal' option 'encryption_algorithm' 'aes256gcm' # no hash_algorithm allowed with AEAD option 'dh_group' 'modp3072' option prf_algorithm 'prfsha512' # we don't specify subnets because we're going to use XFRM-interfaced based routes instead config 'tunnel' 'tun_soho' list 'local_subnet' '0.0.0.0/0' list 'remote_subnet' '0.0.0.0/0' option 'if_id' '357' option 'rekeytime' '1h' # other end is behind NAT or we'd use 'route' to initiate option 'startaction' 'none' option 'closeaction' 'none' list 'crypto_proposal' 'esp_proposal' config 'crypto_proposal' 'esp_proposal' option 'encryption_algorithm' 'aes256gcm' # no hash_algorithm with allowed with AEAD option 'dh_group' 'modp3072'
and to support XFRM-based interfaces with associated routing, we put the following into /etc/config/network:
config 'interface' 'xfrm0' option 'ifid' '357' option 'tunlink' 'wan' option 'mtu' '1438' option 'zone' 'vpn' option 'proto' 'xfrm' # useful if you want to run Bonjour/mDNS across VPN tunnels option 'multicast' 'true' config 'interface' 'xfrm0_s' option 'ifname' '@xfrm0' option 'proto' 'static' option 'ipaddr' '192.168.254.1/30' config 'route' option 'interface' 'xfrm0' option 'target' '192.168.10.0/24' option 'source' '192.168.1.1'
Lastly, /etc/config/firewall requires:
config 'zone' option 'name' 'vpn' option 'network' 'xfrm0' option 'input' 'ACCEPT' option 'output' 'ACCEPT' option 'forward' 'ACCEPT' option 'mtu_fix' '1' config 'forwarding' option 'src' 'lan' option 'dest' 'vpn' config 'forwarding' option 'src' 'vpn' option 'dest' 'lan' config 'rule' option 'name' 'Allow-IPSec-ESP' option 'src' 'wan' option 'proto' 'esp' option 'family' 'ipv4' option 'target' 'ACCEPT' config 'rule' option 'name' 'Allow-ISP-ISAKMP' option 'src' 'wan' option 'src_port' '500' option 'dest_port' '500' option 'proto' 'udp' option 'family' 'ipv4' option 'target' 'ACCEPT'
Lastly generate the certificates for both ends on the hub:
root@HQ:~# gencerts -s US acme.com "Acme Corporation" headquarters soho Generated as headquarters-certs.tar.gz Generated as soho-certs.tar.gz root@HQ:~# tar ztvf headquarters-certs.tar.gz -r--r--r-- 0/0 1870 2021-06-17 19:01:38 swanctl/x509ca/acme.crt -r--r--r-- 0/0 1923 2021-06-17 19:01:53 swanctl/x509/headquarters.crt -r-------- 0/0 3243 2021-06-17 19:01:53 swanctl/private/headquarters.key root@HQ:~# tar ztvf soho-certs.tar.gz -r--r--r-- 0/0 1870 2021-06-17 19:01:38 swanctl/x509ca/acme.crt -r--r--r-- 0/0 1903 2021-06-17 19:02:04 swanctl/x509/soho.crt -r-------- 0/0 3243 2021-06-17 19:02:04 swanctl/private/soho.key root@HQ:~#
Note that the filenames in headquarters.tar.gz correspond to local_cert, local_key, and remote_ca_cert above. Similarly, the certificate's subject corresponds to the local_identifier:
root@HQ:~# openssl x509 -in /etc/swanctl/x509/headquarters.crt -noout -subject subject=C = US, O = Acme Corporation, CN = headquarters root@OpenWrt2:~#
As these files are present on the headquarters firewall already, you can remove headquarters.tar.gz. You can also remove:
/etc/swanctl/x509/soho.crt /etc/swanctl/private/soho.key
as these are only needed on the remote end (SoHo).
Now copy the soho-certs.tar.gz file over to the SoHo router, and unpack it with:
root@SoHo:~# tar -zxf soho-certs.tar.gz -C /etc
Lastly, configure /etc/config/ipsec on the SoHo router:
config 'ipsec' option 'zone' 'vpn' listen 'interface' 'wan' config 'remote' 'headquarters' option 'enabled' '1' option 'local_ip' '%any' option 'gateway' '6.6.6.6' option 'local_identifier' 'C=US, O=Acme Corporation, CN=soho' option 'remote_identifier' 'C=US, O=Acme Corporation, CN=headquarters' option 'authentication_method' 'pubkey' option 'fragmentation' '1' option 'local_cert' 'soho.crt' option 'local_key' 'soho.key' option 'rekeytime' '4h' option 'keyingtries' '0' option 'mobike' 0 list 'remote_ca_certs' 'acme.crt' # hardening, require remote to be signed by acme.crt list 'crypto_proposal' 'ike_proposal' list 'tunnel' 'tun_headquarters' config 'crypto_proposal' 'ike_proposal' option 'encryption_algorithm' 'aes256gcm128' # no hash_algorithm allowed with AEAD option 'dh_group' 'modp3072' option 'prf_algorithm' 'prfsha512' config tunnel 'tun_headquarters' list 'local_subnet' '0.0.0.0/0' list 'remote_subnet' '0.0.0.0/0' option 'if_id' '308' option 'rekeytime' '1h' option 'startaction' 'trap' option 'closeaction' 'none' option 'dpdaction' 'restart' list 'crypto_proposal' 'esp_proposal' config 'crypto_proposal' 'esp_proposal' option 'encryption_algorithm' 'aes256gcm128' # no hash_algorithm allowed with AEAD option 'dh_group' 'modp3072'
Now modify /etc/config/firewall as above, and /etc/config/network as:
config 'interface' 'xfrm0' option 'ifid' '308' option 'tunlink' 'wan' option 'mtu' '1438' option 'zone' 'vpn' option 'proto' 'xfrm' # useful if you want to run Bonjour/mDNS across VPN tunnels option 'multicast' 'true' config 'interface' 'xfrm0_s' option 'ifname' '@xfrm0' option 'proto' 'static' option 'ipaddr' '192.168.254.2/30' config 'route' option 'interface' 'xfrm0' option 'target' '192.168.1.0/24' # assuming lan has the address 192.168.10.1/24 option 'source' '192.168.10.1'
And when this is all done, on both ends do:
root@HQ:~# /etc/init.d/swanctl enable root@HQ:~# /etc/init.d/swanctl restart