FortiGate
FortiGate Next Generation Firewall utilizes purpose-built security processors and threat intelligence security services from FortiGuard labs to deliver top-rated protection and high performance, including encrypted traffic.
lfrancelj
Staff
Staff
Article
This article describes how to setup a site-to-site (s2s) tunnel with LibreSwan and a FortiGate.

LibreSwan documentation.
https://libreswan.org/

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 to refer as 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 your 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 daemons 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
    next
end
Debug on FortiGate looks like.
# diag debug app ike -1
# diag debug enable

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

Contributors