Architecture. The authentication flow uses mutual certificate validation: Ubuntu (StrongSwan) FortiGate AD / CA.
Sends ubuntu-client.pem ──────► Validates against CA_Cert_1
Receives VPN-LOCAL cert ◄────── Signed by AD CA
Validates with CA_Cert_1 ──────► OK
══ IKEv2 Tunnel ESTABLISHED ══
Step 1. Install StrongSwan on Ubuntu.
sudo apt update && sudo apt upgrade -y
sudo apt install -y strongswan strongswan-pki libstrongswan-extra-plugins libstrongswan-standard-plugins libcharon-extra-plugins libcharon-extauth-plugins strongswan-swanctl openssl ldap-utils
Step 2. Export and Import the AD CA Certificate.
Export from FortiGate GUI. Navigate to System -> Certificates -> CA Certificates. Download the AD CA certificate, it will download as .cer. Check the format on Ubuntu:
file CA_Cert_1.cer
Expected output: CA_Cert_1.cer: PEM certificate.
If already PEM, no conversion needed. Step 3. Install on Ubuntu.
Copy directly (already PEM format).
sudo cp CA_Cert_1.cer /etc/ipsec.d/cacerts/CA_Cert_1.pem
sudo chmod 644 /etc/ipsec.d/cacerts/CA_Cert_1.pem
To verify:
openssl x509 -in /etc/ipsec.d/cacerts/CA_Cert_1.pem -text -noout | grep -E "Subject:|Issuer:|Not After"
Note: If the file is DER format instead of PEM, convert with: openssl x509 -inform DER -in CA_Cert_1.cer -out CA_Cert_1.pem.
Generate FortiGate VPN Certificate (Signed by AD CA).
The FortiGate must present a certificate signed by the AD CA — do NOT use Fortinet_Factory, as Ubuntu cannot validate its chain.
Generate CSR on FortiGate:
Parameter Value
Certificate Name VPN-LOCAL
ID Type IP
IP 172.16.20.111 ( Fortigate WAN IP)
Key Type RSA - 2048 bits
Sign with AD CA (via certsrv). On the AD server, open a browser and access: http://127.0.0.1/certsrv. Select Request a certificate -> Advanced certificate request. Paste the CSR content. Select the template: Web Server. Download the signed certificate in Base 64 format.
Import the signed certificate into FortiGate. Navigate to System -> Certificates -> Local Certificates -> Import. Upload the signed .cer file. Configure Phase 1 to use VPN-LOCAL as the certificate. Note: Do not use Fortinet_Factory for the VPN certificate. Its chain (fortinet-ca2 > fortinet-subca2001) is not publicly resolvable, and Ubuntu will reject it with 'no trusted RSA public key found'.
Step 4. Generate Ubuntu Client Certificate.
Generate key and CSR on Ubuntu. Create and access the directory vpn-cert:
mkdir ~/vpn-cert && cd ~/vpn-cert
Generate private key:
openssl genrsa -out ubuntu-client.key 2048
Generate CSR:
openssl req -new -key ubuntu-client.key -out ubuntu-client.csr -subj "/CN=ubuntu/O=wellscompany/C=US"
View CSR to copy:
cat ubuntu-client.csr
Note: The warning 'Can't load .rnd into RNG' is harmless — the CSR is generated successfully. Confirm with: ls -la ~/vpn-cert/.
Create a custom CA template on AD (required).
The default Web Server and User templates do not preserve the CSR Subject. A custom template is required: Open certtmpl.msc on the AD server 'Right-click' Web Server template -> Duplicate template. General tab: Name = VPN-Client. Subject Name tab: select Supply in the request. Extensions tab -> Application Policies: add Client Authentication. Security tab: add user with Enroll permission Select OK and publish the template: On AD PowerShell (as Administrator):
Add-CATemplate -Name "VPN-Client"
Type Y to confirm.
Note: Using the Web Server or User template will result in the certificate Subject being overwritten with the logged-in AD user's data instead of the CSR Subject (CN=ubuntu).
Sign CSR with VPN-Client template.
Transfer ubuntu-client.csr to the AD server. Access http://127.0.0.1/certsrv on the AD server. Select Request a certificate -> Advanced certificate request. Paste the CSR content. Select template: VPN-Client. Download in Base 64 format, save as ubuntu-client.cer. Transfer back to Ubuntu and verify:
Expected Subject: C=US, O=wellscompany, CN=ubuntu.
openssl x509 -in ubuntu-client.cer -text -noout | grep -E "Subject:|Issuer:|Not After"
Install the client certificate on Ubuntu.
cd ~/vpn-cert
sudo cp ubuntu-client.cer /etc/ipsec.d/certs/ubuntu-client.pem
sudo cp ubuntu-client.key /etc/ipsec.d/private/ubuntu-client.key
sudo chmod 644 /etc/ipsec.d/certs/ubuntu-client.pem
sudo chmod 600 /etc/ipsec.d/private/ubuntu-client.key
Confirm files are in place:
ls -la /etc/ipsec.d/certs/ubuntu-client.pem
ls -la /etc/ipsec.d/private/ubuntu-client.key
ls -la /etc/ipsec.d/cacerts/
Step 5. Configure FortiGate IPsec Tunnel. Phase 1 (IKEv2 + Certificate). Navigate to VPN -> IPsec Tunnels -> Create New -> Custom, or configure via CLI:
config vpn ipsec phase1-interface
edit "VPN_CERT"
set type dynamic
set interface "port1"
set ike-version 2
set authmethod signature
set peertype peergrp
set net-device disable
set mode-cfg enable
set proposal aes256-sha256-modp2048
set dhgrp 14
set eap disable
set dpd on-idle
set dpd-retryinterval 60
set certificate "VPN-LOCAL"
set peergrp "grp-authcert"
set assign-ip-from name
set ipv4-name "SSLVPN_TUNNEL_ADDR1"
set ipv4-netmask 255.255.255.0
set dpd-retryinterval 60
next
end
Note: Key settings: authmethod=signature (certificate auth), peertype=any (accept any valid cert), eap=disable (not using EAP/MSCHAPv2).
Configure User Peer and Peer Group (required).
These two configurations tell FortiGate which CA to use when validating the client certificate. Without them, certificate authentication will fail. Create a user peer referencing the AD CA:
config user peer
edit "authcert-peer"
set ca "CA_Cert_1"
next
end
Create a peer group with that peer as a member:
config user peergrp
edit "grp-authcert"
set member "authcert-peer"
next
end
Reference the peer group in Phase 1:
config vpn ipsec phase1-interface
edit "VPN_CERT"
set peertype peergrp
set peergrp "grp-authcert"
next
end
Note: This is the most critical FortiGate configuration for certificate auth. The user peer maps the client certificate to the AD CA (CA_Cert_1). Without this, FortiGate cannot validate which CA signed the client certificate.
Verify AD CA is imported on FortiGate.
Navigate to System -> Certificates -> CA Certificates. Confirm that wellscompany-WELLS-ADSERVER-CA is listed. If missing, import CA_Cert_1.pem via: System -> Certificates -> CA Certificates -> Import.
Parameter Value
Encryption AES256/SHA256
PFS DH Group 14
Lifetime (s) 43200
Firewall Policy:
Parameter Value
incoming Interface VPN_CERT (VPN tunnel)
Outgoing Interface LAN Interface
Source ALL
Destination ALL
Action ACCEPT
NAT Disable
Step 6. Configure StrongSwan on Ubuntu: edit /etc/ipsec.conf.
config setup
charondebug="ike 2, knl 2, cfg 2, net 2, esp 2, dmn 2, mgr 2"
strictcrlpolicy=no
conn vpn-fortigate
keyexchange=ikev2
right=172.16.20.111
rightid=%any
rightauth=pubkey
rightsubnet=0.0.0.0/0
left=%config
leftauth=pubkey
leftid="C=US, O=wellscompany, CN=ubuntu"
leftcert=ubuntu-client.pem
leftsourceip=%config
ike=aes256-sha256-modp2048!
esp=aes256-sha256!
auto=add
dpdaction=clear
dpddelay=30s
dpdtimeout=120s
strictcrlpolicy=no prevents connection failures when Ubuntu cannot reach the AD CRL distribution point via LDAP.: edit /etc/ipsec.secrets.
# Reference the client private key
: RSA ubuntu-client.key
The /etc/ipsec.secrets file must have permission 600. Run: sudo chmod 600 /etc/ipsec.secrets
Step 7. Connect and Verify.
Restart StrongSwan:
sudo ipsec restart
Bring up the tunnel:
sudo ipsec up vpn-fortigate
Expected output:
initiating IKE_SA vpn-fortigate[1] to 172.16.20.111.
authentication of 'CN=172.16.20.111' with RSA signature successful
IKE_SA vpn-fortigate[1] established
CHILD_SA vpn-fortigate{1} established
connection 'vpn-fortigate' established successfully
Note: Connection confirmed: ESTABLISHED 172.16.20.115[C=US, O=wellscompany, CN=ubuntu]...172.16.20.111[CN=172.16.20.111] — IP assigned: 10.212.134.200/32.
Step 8. Useful diagnostic commands.
Live logs:
sudo journalctl -u strongswan-starter -f
Check loaded connections:
sudo ipsec status
sudo ipsec statusall
Verify certificate:
openssl x509 -in /etc/ipsec.d/certs/ubuntu-client.pem -text -noout | grep -E "Subject:|Issuer:|Not After"
Test AD LDAP auth from FortiGate CLI:
diagnose test authserver ldap Wells-ADSERVER wells Password123
Check FortiGate Phase 1 config:
show vpn ipsec phase1-interface LDAPS
Tear down tunnel:
sudo ipsec down vpn-fortigate
Related article:
Technical Tip: How to export root CA from Certificate Authority Server and import to FortiGate |