Technical Tip: Using LibreSwan for a site-to-site IPsec tunnel
Description
This article describes how to setup a site-to-site (s2s) tunnel with LibreSwan and a FortiGate.
Scope
FortiGate.
Solution
See the LibreSwan official documentation.
LibreSwan is an open source implementation that can help to built up an IPsec tunnel between a node and the FortiGate.
In this example the Pre-Shared-Key (PSK) and IKEv2 are used.
Depending on the system the whole configuration is found in /etc/ipsec.conf but the configuration should be similar.
Usually it is a modular configuration, indicated by the content of the configuration file ipsec.conf as:
include /etc/ipsec.d/*.conf
In parallel there is a secrets file containing the PSK:
/etc/ipsec.secrets, which in turn on a modular system contains
include /etc/ipsec.d/*.secrets
Connection definition is needed for each remote network to access.
A LibreSwan connection definition does not use the terms 'source' or 'destination'.
Instead, to define the two ends of the VPN as 'left' and 'right'.
The software determines for itself which definition applies to its end of the tunnel. But usually, it refers to:
left = local
And:
right = remote site
In this example the VPN configuration is called 'office':
cat /etc/ipsec.d/office.conf # config setup # conn office rekey=yes rightid=@FGTpeer <<< The ‘@’ means to match the peer ID exactly. left=<local-public-IP> leftsubnet=172.16.0.0/16 right=<remote-public-IP> rightsubnet=192.168.48.0/24 ikelifetime=28800s authby=secret (secret = PSK, as opposed to “rsasig” for certificate authentication) type=tunnel auto=start ike=aes_gcm256-sha2 esp=aes_gcm256-null ikev2=insist fragmentation=yes #perfect forward secrecy (default yes) #pfs=no #optionally enable compression compress=yes
For more information and possible settings, see the ipsec.conf man page.
Note that NAT traversal by default is automatically detected, in earlier versions of OpenSwan / LibreSwan / StrongSwan it has to be manually set (as nat_traversal=yes).
As above, PSKs is stored in the secrets file.
Put the definition file in this location with an appropriate name, typically the same filename as the configuration with the .secrets ending.
Note:
This file contains sensitive information and is readable in clear text, so it is accessible only to any user.
Certificate based authentication can circumvent this circumstance.
Example.
cat /etc/ipsec.d/office.secrets fgt.office.forti.lab %any : PSK "ThisSh0uldBeH4rdT()Guess"
Entries in the secrets file can take several forms:
: PSK "pre_shared_key" <----- OK for typical remote user with one key. 1.23.45.67: PSK "pre_shared_key" <----- Specify remote gateway only. 1.23.45.67 10.10.10.100: PSK "pre_shared_key" <----- Specify remote and local IPs.
The typical remote user who has only one VPN connection using a PSK, can reliably use the secrets file definition that does not specify IP addresses.
The definition that specifies only the remote gateway address does not always work.
It is possible to get an error message that no PSK was found for the connection.
The definition that specifies both local and remote gateway addresses is useful only if a local IP address has been fixed.
Starting and stopping the VPN.
If the auto=start option is used in the connection definition, the VPN is established when the IPsec service starts.
Otherwise, it is not necessary to use the IPsec command to start and stop the VPN.
The service is started with, depending on the use of a SysVinit compatible system.
/etc/init.d/ipsec start
Or a systemd compatible system:
systemctl start ipsec.service
The startup messages will show if there are problems with the installation or syntactic problems with the configuration files.
To start the VPN.
/usr/sbin/ipsec auto --add office /usr/sbin/ipsec auto --up office
To stop the VPN.
/usr/sbin/ipsec auto --down office /usr/sbin/ipsec auto --delete office
To view the VPN status:
/usr/sbin/ipsec auto --status
Example output.
/usr/sbin/ipsec auto --status 000 using kernel interface: netkey 000 interface lo/lo [::1]:500 000 interface lo/lo 127.0.0.1:4500 000 interface lo/lo 127.0.0.1:500 000 interface eth0/eth0 <office-IP>:4500 000 interface eth0/eth0 <office-IP>:500 000 000 000 fips mode=disabled; 000 SElinux=disabled 000 seccomp=disabled 000 000 config setup options: 000 000 configdir=/etc, configfile=/etc/ipsec.conf, secrets=/etc/ipsec.secrets, ipsecdir=/etc/ipsec.d 000 nssdir=/etc/ipsec.d, dumpdir=/run/pluto, statsbin=unset 000 sbindir=/usr/sbin, libexecdir=/usr/libexec/ipsec 000 pluto_version=3.32, pluto_vendorid=OE-Libreswan-3.32, audit-log=yes 000 nhelpers=-1, uniqueids=yes, dnssec-enable=no, perpeerlog=no, logappend=yes, logip=yes, shuntlifetime=900s, xfrmlifetime=30s 000 ddos-cookies-threshold=50000, ddos-max-halfopen=25000, ddos-mode=auto 000 ikeport=500, ikebuf=0, msg_errqueue=yes, strictcrlpolicy=no, crlcheckinterval=0, listen=<any>, nflog-all=0 000 ocsp-enable=no, ocsp-strict=no, ocsp-timeout=2, ocsp-uri=<unset> 000 ocsp-trust-name=<unset> 000 ocsp-cache-size=1000, ocsp-cache-min-age=3600, ocsp-cache-max-age=86400, ocsp-method=get 000 global-redirect=no, global-redirect-to=<unset> 000 secctx-attr-type=<unsupported> 000 debug: 000 000 nat-traversal=yes, keep-alive=20, nat-ikeport=4500 000 virtual-private (%priv): 000 000 Kernel algorithms supported: 000 000 algorithm ESP encrypt: name=3DES_CBC, keysizemin=192, keysizemax=192 000 algorithm ESP encrypt: name=AES_CBC, keysizemin=128, keysizemax=256 000 algorithm ESP encrypt: name=AES_CCM_12, keysizemin=128, keysizemax=256 000 algorithm ESP encrypt: name=AES_CCM_16, keysizemin=128, keysizemax=256 <truncated> 000 algorithm IKE DH Key Exchange: name=DH21, bits=1056 000 algorithm IKE DH Key Exchange: name=DH31, bits=256 000 000 stats db_ops: {curr_cnt, total_cnt, maxsz} :context={0,0,0} trans={0,0,0} attrs={0,0,0} 000 000 Connection list: 000 000 "office": 172.16.0.0/16===<office-IP>...<FortiGate-IP>[@FGTpeer]===192.168.48.0/24; erouted; eroute owner: #28 000 "office": oriented; my_ip=unset; their_ip=unset; my_updown=ipsec _updown; 000 "office": xauth us:none, xauth them:none, my_username=[any]; their_username=[any] 000 "office": our auth:secret, their auth:secret 000 "office": modecfg info: us:none, them:none, modecfg policy:push, dns:unset, domains:unset, banner:unset, cat:unset; 000 "office": policy_label:unset; 000 "office": ike_life: 28800s; ipsec_life: 28800s; replay_window: 32; rekey_margin: 540s; rekey_fuzz: 100%; keyingtries: 0; 000 "office": retransmit-interval: 500ms; retransmit-timeout: 60s; 000 "office": initial-contact:no; cisco-unity:no; fake-strongswan:no; send-vendorid:no; send-no-esp-tfc:no; 000 "office": policy: PSK+ENCRYPT+TUNNEL+PFS+UP+IKEV2_ALLOW+SAREF_TRACK+IKE_FRAG_ALLOW+ESN_NO; 000 "office": v2-auth-hash-policy: none; 000 "office": conn_prio: 0,32; interface: eth0; metric: 0; mtu: unset; sa_prio:auto; sa_tfc:none; 000 "office": nflog-group: unset; mark: unset; vti-iface:unset; vti-routing:no; vti-shared:no; nic-offload:auto; 000 "office": our idtype: ID_IPV4_ADDR; our id=<office-IP>; their idtype: ID_FQDN; their id=@FGTpeer 000 "office": dpd: action:hold; delay:0; timeout:0; nat-t: encaps:auto; nat_keepalive:yes; ikev1_natt:both 000 "office": newest ISAKMP SA: #29; newest IPsec SA: #28; 000 "office": IKE algorithms: AES_GCM_16_256-HMAC_SHA2_256-MODP2048+MODP3072+MODP4096+MODP8192+DH19+DH20+DH21+DH31 000 "office": IKEv2 algorithm newest: AES_GCM_16_256-HMAC_SHA2_256-DH21 000 "office": ESP algorithms: AES_GCM_16_256-NONE 000 "office": ESP algorithm newest: AES_GCM_16_256-NONE; pfsgroup=<Phase1> 000 000 Total IPsec connections: loaded 1, active 1
Logging can be seen in the systems syslog location, typically in /var/log/. The tag this is logged with is 'pluto', which is the daemon's name, started with the system, as described in the beginning of the article.
The appropriate configuration on the FortiGate looks like.
config vpn ipsec phase1-interface edit "OfficeTunnel" set interface "wan" set ike-version 2 set keylife 28800 set peertype any set net-device enable set proposal aes256gcm-prfsha256 set localid "FGTpeer" set dhgrp 21 set remote-gw <office-IP> set psksecret ENC ommitted next end config vpn ipsec phase2-interface edit "Office_IP_range" set phase1name "OfficeTunnel" set proposal aes256gcm chacha20poly1305 set dhgrp 21 set auto-negotiate enable set keylifeseconds 28800 set src-subnet 192.168.48.0 255.255.255.0 set dst-subnet 172.16.0.0 255.255.0.0 next end
Debug on FortiGate :
diagnose debug app ike -1 diagnose debug enable
To stop debug:
diagnose debug disable
ike 1: comes <office-IP>:500->192.168.48.25:500,ifindex=37.... ike 1: IKEv2 exchange=SA_INIT_RESPONSE id=408dfcfbffbb2e21/f2f4e9170d373412 len=308 ike 1: in 408DFCFBFFBB2E21F2F4E9170D3734122120222000000000000001342200002800000024010100030300000C01000014800E0100030000080200000500000008040000152800B805795F5E3F2B0000001C00004005640E733C1C272C4BA7C8A2563CC5622952C03FCE ike 1:OfficeTunnel:5219: initiator received SA_INIT response ike 1:OfficeTunnel:5219: processing notify type FRAGMENTATION_SUPPORTED ike 1:OfficeTunnel:5219: processing notify type NAT_DETECTION_SOURCE_IP ike 1:OfficeTunnel:5219: processing NAT-D payload ike 1:OfficeTunnel:5219: NAT not detected ike 1:OfficeTunnel:5219: process NAT-D ike 1:OfficeTunnel:5219: processing notify type NAT_DETECTION_DESTINATION_IP ike 1:OfficeTunnel:5219: processing NAT-D payload ike 1:OfficeTunnel:5219: NAT detected: ME ike 1:OfficeTunnel:5219: process NAT-D ike 1:OfficeTunnel:5219: incoming proposal: ike 1:OfficeTunnel:5219: proposal id = 1: ike 1:OfficeTunnel:5219: protocol = IKEv2: ike 1:OfficeTunnel:5219: encapsulation = IKEv2/none ike 1:OfficeTunnel:5219: type=ENCR, val=AES_GCM_16 (key_len = 256) ike 1:OfficeTunnel:5219: type=PRF, val=PRF_HMAC_SHA2_256 ike 1:OfficeTunnel:5219: type=DH_GROUP, val=ECP521. ike 1:OfficeTunnel:5219: matched proposal id 1 ike 1:OfficeTunnel:5219: proposal id = 1: ike 1:OfficeTunnel:5219: protocol = IKEv2: ike 1:OfficeTunnel:5219: encapsulation = IKEv2/none ike 1:OfficeTunnel:5219: type=ENCR, val=AES_GCM_16 (key_len = 256) ike 1:OfficeTunnel:5219: type=INTEGR, val=NONE ike 1:OfficeTunnel:5219: type=PRF, val=PRF_HMAC_SHA2_256 ike 1:OfficeTunnel:5219: type=DH_GROUP, val=ECP521. ike 1:OfficeTunnel:5219: lifetime=28800 ike 1:OfficeTunnel:5219: IKE SA 408dfcfbffbb2e21/f2f4e9170d373412 SK_ei 36:ACFB467A50189C0613BDCA4BE8CF8E2CAF8172C3ED17629FD0336486D61EC1DF27E001A2 ike 1:OfficeTunnel:5219: IKE SA 408dfcfbffbb2e21/f2f4e9170d373412 SK_er 36:9549ADBE1B1240A52D4CDA99822CE22F00810DCFE0374936F00A2BDE7186FD890C6ECED8 ike 1:OfficeTunnel:5219: initiator preparing AUTH msg ike 1:OfficeTunnel:5219: sending INITIAL-CONTACT ike 1:OfficeTunnel:5219: enc 2900000C020000006D61696C27000008000040002900002802000000997B91377FABAB01000000070000100000FFFF5BCC2CE15BCC2CE10000001801000000070000100000FFFF00000000FFFFFFFF080706050403020108 ike 1:OfficeTunnel:5219: detected NAT ike 1:OfficeTunnel:5219: NAT-T float port 4500 ike 1:9ef430ca12bf6dce/0000000000000000:5220: responder received SA_INIT msg ike 1:9ef430ca12bf6dce/0000000000000000:5220: received notify type FRAGMENTATION_SUPPORTED ike 1:9ef430ca12bf6dce/0000000000000000:5220: received notify type NAT_DETECTION_SOURCE_IP ike 1:9ef430ca12bf6dce/0000000000000000:5220: received notify type NAT_DETECTION_DESTINATION_IP ike 1:9ef430ca12bf6dce/0000000000000000:5220: incoming proposal: ike 1:9ef430ca12bf6dce/0000000000000000:5220: proposal id = 1: ike 1:9ef430ca12bf6dce/0000000000000000:5220: protocol = IKEv2: ike 1:9ef430ca12bf6dce/0000000000000000:5220: encapsulation = IKEv2/none ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=ENCR, val=AES_GCM_16 (key_len = 256) ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=PRF, val=PRF_HMAC_SHA2_256 ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=DH_GROUP, val=CURVE25519. ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=DH_GROUP, val=ECP521. ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=DH_GROUP, val=ECP384. ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=DH_GROUP, val=ECP256. ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=DH_GROUP, val=MODP8192. ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=DH_GROUP, val=MODP4096. ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=DH_GROUP, val=MODP3072. ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=DH_GROUP, val=MODP2048. ike 1:9ef430ca12bf6dce/0000000000000000:5220: matched proposal id 1 ike 1:9ef430ca12bf6dce/0000000000000000:5220: proposal id = 1: ike 1:9ef430ca12bf6dce/0000000000000000:5220: protocol = IKEv2: ike 1:9ef430ca12bf6dce/0000000000000000:5220: encapsulation = IKEv2/none ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=ENCR, val=AES_GCM_16 (key_len = 256) ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=INTEGR, val=NONE ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=PRF, val=PRF_HMAC_SHA2_256 ike 1:9ef430ca12bf6dce/0000000000000000:5220: type=DH_GROUP, val=ECP521. ike 1:9ef430ca12bf6dce/0000000000000000:5220: lifetime=28800 ike 1:9ef430ca12bf6dce/0000000000000000:5220: SA proposal chosen, matched gateway OfficeTunnel ike 1: found OfficeTunnel 192.168.48.25 37 -> <office-IP>:500 ike 1:OfficeTunnel:5220: processing notify type NAT_DETECTION_SOURCE_IP ike 1:OfficeTunnel:5220: processing NAT-D payload ike 1:OfficeTunnel:5220: NAT not detected ike 1:OfficeTunnel:5220: process NAT-D ike 1:OfficeTunnel:5220: processing notify type NAT_DETECTION_DESTINATION_IP ike 1:OfficeTunnel:5220: processing NAT-D payload ike 1:OfficeTunnel:5220: NAT detected: ME ike 1:OfficeTunnel:5220: process NAT-D ike 1:OfficeTunnel:5220: processing notify type FRAGMENTATION_SUPPORTED ike 1:OfficeTunnel:5220: mismatched DH group in KE payload, selected 21, received 14 ike 1:OfficeTunnel:5220: sending INVALID_KE notify ike 1:OfficeTunnel:5220: out 9ef430ca12bf6dce00000000000000002920222000000000000000260000000A000000110015 ike 1:OfficeTunnel:5220: sent IKE msg (INVALID_KE_PAYLOAD): 192.168.48.25:500-><office-IP>:500, len=38, id=9ef430ca12bf6dce/0000000000000000 ike 1:OfficeTunnel:5219: initiator received AUTH msg ike 1:OfficeTunnel:5219: peer identifier IPV4_ADDR <office-IP> ike 1:OfficeTunnel:5219: auth verify done ike 1:OfficeTunnel:5219: initiator AUTH continuation ike 1:OfficeTunnel:5219: authentication succeeded ike 1:OfficeTunnel:5219: established IKE SA 408dfcfbffbb2e21/f2f4e9170d373412 ike 1:OfficeTunnel: set oper up
If internet breakout is needed through the LibreSwan server, the following configurations needs to be made:
On the server:
Configuration file needs to be edited:
Replace leftsubnet=172.16.0.0/16 with leftsubnet=0.0.0.0/0 in /etc/ipsec.d/office.conf.
Configure the kernel to enable packet forwarding by adding the appropriate system variables in /etc/sysctl.conf.
$ sudo vim /etc/sysctl.conf
Look for the following line and uncomment it and set its value as shown:
net.ipv4.ip_forward = 1
Load the new settings by running the following command:
$ sudo sysctl -p
The following iptables rule needs to be configured:
iptables -t nat -A POSTROUTING -s 192.168.48.0/24 -o eth0 -j MASQUERADE
On the FortiGate:
Leave only src-subnet. By default, if no dst-subnet is mentioned, FortiOS will use the default value of 0.0.0.0/0.
config vpn ipsec phase2-interface edit "Office_IP_range" set phase1name "OfficeTunnel" set proposal aes256gcm chacha20poly1305 set dhgrp 21 set auto-negotiate enable set keylifeseconds 28800 set src-subnet 192.168.48.0 255.255.255.0 next
Add a default route that uses the tunnel interface as next-hop and configure a corresponding firewall policy that excepts the traffic
