With many of us still dealing with the COVID-19 pandemic’s work-from-home restrictions, I’ve been asked more and more about secure remote access options. With that in mind, I am going to provide a technical walkthrough of implementing one of the most secure and fastest VPN methods widely available to most organizations: the IKEv2 VPN.

When it comes to remote access, I’ve seen a wide range of implemented solutions: from Windows Remote Desktop (RDP) directly through the firewall (if a firewall is even in place) to SSL VPNs, IKEv1, L2TP, and more. For many organizations, focus is placed on functionality — "Does it work?" and "Can I access my company network?" — versus "Have we balanced security with user functionality based on risk?"

Do you know how remote access is implemented at your organization? Do you know how it is secured?

Let’s move on to the subject of this guide: the IKEv2 VPN.

What are a few reasons you might want to implement an IKEv2 VPN?

  • Supports the mobility (MOBIKE) protocol, which can make a VPN connection more resilient to changing networks (e.g., switching from wired to wireless to cellular)
  • This is the successor to IKEv1 and is widely considered one of the most secure VPN protocols when implemented properly
  • Built-in NAT-Traversal (if desired)
  • Programmed to consume less bandwidth and require less data overhead, resulting in faster performance for remote users
  • Improved reliability and can reconnect quickly in the event of a dropped connection

Sounds pretty good, right? Well, let’s look at a test implementation we developed using FortiGate firewalls and the native Windows 10 VPN client application. When we set out to implement this with FortiGate firewalls, we didn’t find any formal guidance that could walk an administrator through a successful implementation, so we decided to create one.

How to set up IKEv2 VPN

The following are script snippets that you can use to build an IKEv2 VPN on Fortinet FortiGate firewalls. This was tested on FortiOS 6.2 and newer.

//For most users, it is easier to configure the RADIUS server object in the web administrative interface.
config user radius
edit "ExampleRADIUS"
set server "X.X.X.X"
set secret ENC //encrypted value of shared secret
set auth-type ms_chap_v2

config user group
edit "ExampleGroup"
set member "ExampleRADIUS"
//This creates a user group, where the members are the RADIUS server
//setup in the previous segment.

edit "VPN_Range"
set type iprange
set color 3
set start-ip X.X.X.X
//Edit the starting IP for your VPN address range
set end-ip X.X.X.X
//Edit the ending IP for your VPN address range

config vpn ipsec phase1-interface
edit "ExampleVPN"
set type dynamic
set interface "wan1"
set ike-version 2
set authmethod signature
set peertype any
//In our example, we leave this at 'any' as we have a separate working root CA
//that effectively creates a dedicated trust domain for VPN certificates
//You can specific a specific Peer ID, but ensure you read up on requirements, as
//this can add some complexity to certificate management.
set net-device disable
set mode-cfg enable
set ipv4-dns-server1 X.X.X.X
set ipv4-dns-server2 Y.Y.Y.Y
set proposal aes256-sha256 aes128-sha256
//This sets the allowed encryption and hashing methods
set comments "VPN: ExampleVPN"
set dhgrp 14
//This sets the Diffie-Hellman group (DH Group) exchange process to use 2048 bit keys
set eap enable
set eap-identity send-request
set authusrgrp "ExampleGroup"
//In our example we have a RADIUS server setup to proxy authentication requests
set nattraversal disable
//For most organizations, I would recommend enabled NAT Traversal (NAT-T)
//as I've found that most mobile hotspots require it for the VPN to work.
set certificate "CERTIFICATE"
//This is the certificate of the firewall created for this purpose. It must be signed
//by the same CA that signs the endpoint or end-user certificates.
//In our example, we created a working root in AD CS and issued unique
//certificates under this CA for all laptops that would use the VPN
set assign-ip-from name
set ipv4-netmask X.X.X.X
//Set this to your desired subnet mask
set ipv4-split-include "RemoteNetwork"
//This is the address range of the network you are connecting to
set ipv4-name "VPN_Range"
//This is the address range that will be distributed to VPN clients
set dpd-retryinterval 60

config vpn ipsec phase2-interface
edit "ExampleVPN"
set phase1name "ExampleVPN"
set proposal aes128-sha256 aes256-sha256
//This sets the allowed encryption and hashing methods
set pfs enable
//Enables perfect forward secrecy, or simply 'forward secrecy'.
set keepalive enable
set comments "VPN: ExampleVPN"
set keylifeseconds 3600

The above does not include the firewall rules (ACLs) that would be required to allow inbound VPN traffic to reach your network or outbound VPN traffic to reach the internet. You will need to create those rules in order for the VPN to function properly.

A few notes on the FortiGate VPN configuration:

1. Our example leverages certificate-based mutual authentication followed by end-user authentication using EAP. The end-user certificate used a 2nd factor in this example.

2. Our example assumes you have an internal certificate authority (CA) and have:

a. Created a unique certificate for the FortiGate firewall that has been signed by your CA.

b. Created unique certificates for each end-user that will be connecting to the VPN and distributed their certificates properly.

c. A certificate revocation list (CRL) that you maintain, ensuring that any user who shouldn’t have access to the VPN or who has been terminated has their certificate revoked.

3. You elect to use different cipher-suites

4. You may elect to require push-based multi-factor authentication (MFA), although I haven’t found a formally supported method to implement this with the FortiGate firewalls yet.

Configure Windows 10

Now let’s configure the Windows 10 end-user’s machine for our new VPN.

The following is a sample PowerShell script that you can edit and use to create a test IKEv2 VPN on Windows 10. You can copy and paste the below into a text editor or PowerShell ISE and save as a PowerShell script. I found that this works best when running in Windows PowerShell ISE (as an Administrator).

$Name = "ExampleVPN"
$ServerAddress = "X.X.X.X"
# IP Address or FQDN
$TunnelType = "IKEv2"
# Values: PPTP | L2TP | SSTP | IKEv2 | Automatic
#$L2tpPsk = "NotUsedInThisExample"
$AuthenticationMethod = "EAP"
# Values: PAP | CHAP | MSCHAPv2 | EAP
$EncryptionLevel = "Maximum"
# Values: NoEncryption | Optional | Required | Maximum
#$UseWinlogonCredential = $true
$RememberCredential = $true
$RequireConfirmation = $false
$SplitTunneling = $true
#$DnsSuffix = "ExampleCompany.com"
$TestConnection = Get-VPNConnection
$IKEService = Get-Service -Name IKEEXT
$IPsecService = Get-Service -Name PolicyAgent
$IPSecCryptoSetName = "{E5A5D32A-4BCE-4e4d-B07F-4AB1BA7E5FE1}"
$IPSecCryptoSetDislayName = "ExampleCompanyDefault"
$IPsecProposal0 = New-NetIPsecMainModeCryptoProposal -Encryption AES256 -Hash SHA256 -KeyExchange DH14
$IPsecProposal1 = New-NetIPsecMainModeCryptoProposal -Encryption AES128 -Hash SHA256 -KeyExchange DH14

# If PowerShell supports VPN configuration, apply VPN configuration
If ($TestConnection = $Name) {
# Verify IKE and AuthIP IPsec policy is set to automatic start and is started
if ($IKEService.StartType -ne "Automatic"){
Set-Service -Name <style="color: purple;">IKEEXT <style="color: navy;">-StartupType <style="color: purple;">Automatic
if ($IKEService.Status -ne "Running"){
Start-Service -Name IKEEXT
# Verify IPsec Policy Agent service is set to automatic start and is started
if ($IPsecService.StartType -ne "Automatic"){
Set-Service -Name PolicyAgent -StartupType Automatic
if ($IPsecService.Status -ne "Running"){
Start-Service -Name PolicyAgent

# Configure IPsec Key Exchange (Main Mode) settings
$IPSecTest = Get-NetIPsecMainModeCryptoSet -Name $IPSecCryptoSetName
If($IPSecTest.Name -eq $IPSecCryptoSetName){
Set-NetIPsecMainModeCryptoSet -Name $IPSecCryptoSetName -Proposal $IPsecProposal0,$IPsecProposal1 -ForceDiffieHellman $true
New-NetIPsecMainModeCryptoSet -Name $IPSecCryptoSetName -DisplayName $IPSecCryptoSetDislayName -Proposal $IPsecProposal0,$IPsecProposal1 -ForceDiffieHellman $true
# If VPN exists, update VPN settings
if (Get-VpnConnection -Name $Name -AllUserConnection -ErrorAction SilentlyContinue) {
Set-VpnConnection -Name $Name -AllUserConnection -ServerAddress $ServerAddress -TunnelType $TunnelType -EncryptionLevel $EncryptionLevel -AuthenticationMethod $AuthenticationMethod -SplitTunneling $SplitTunneling -Force
# Else, create VPN connection
else {
Add-VpnConnection -Name $Name -AllUserConnection $true -ServerAddress $ServerAddress -TunnelType $TunnelType -EncryptionLevel $EncryptionLevel -AuthenticationMethod $AuthenticationMethod -Force
Set-VpnConnection -Name $Name -AllUserConnection -SplitTunneling $SplitTunneling -RememberCredential $RememberCredential -Force
Set-VpnConnectionIPsecConfiguration -AuthenticationTransformConstants SHA256128 -CipherTransformConstants AES256 -ConnectionName $Name -DHGroup Group14 -EncryptionMethod AES256 -IntegrityCheckMethod SHA256 -PfsGroup PFS2048 -AllUserConnection -Force
return Get-VpnConnection -Name $Name -AllUserConnection
# Else, exit with failure code
else {
return "Client does not support VpnClient cmdlets"
exit 1

In my experience, this VPN method creates one of the best balances of user functionality, speed, and security available for organizations where personnel need the ability to securely access company-network resources while offsite.

Please reach out if you have any questions about how to make this work for your organization or if you would like to discuss how to better secure your remote workforce!