There are days when VPNs remind you that they don’t care how confident you feel.
This was one of those days.
I was working on a remote-access IPsec VPN with FortiClient (IKEv2) on a FortiGate 100F running FortiOS 7.4.4. On paper, everything looked fine. Phase1 up. Phase2 defined. Crypto proposals matched. Firewall rules in place.
And yet…
FortiClient kept saying: “The VPN server did not respond.”
No tunnel. No traffic. No joy.
This post is a practical walkthrough of what went wrong, what the logs were actually telling us, and why recreating the tunnel cleanly via CLI fixed everything — plus how to properly secure it using user groups and policies instead of only a PSK.
The First Red Flag: “It Should Work”
The most dangerous phrase in IT.
IKEv2 negotiations were starting. NAT detection was fine. Mode-config was assigning an IP. But the tunnel kept collapsing right after authentication.
When we enabled debug:
diagnose debug application ike -1
diagnose debug enable
The key message kept showing up:
traffic selectors unacceptable
failed to match peer selectors
That message is FortiGate politely saying:
“I don’t like how this tunnel was built… but I won’t tell you exactly why.”
The Hidden Problem: Configuration Drift
This VPN had been:
- Created partially from GUI
- Modified multiple times
- Touched across upgrades
- Tweaked with old Phase2 selectors
Classic configuration drift.
At this point, the best troubleshooting tool wasn’t another debug command.
It was Ctrl + Alt + Delete (for the tunnel).
Decision Time: Rebuild It Clean
Instead of patching around the problem, we did what usually works best with FortiGate VPNs:
👉 Delete and recreate the tunnel cleanly using CLI only.
No GUI leftovers. No legacy settings. No half-matched selectors.
And that’s when everything changed.
The Clean IKEv2 IPsec Tunnel (CLI)
Phase1 – IKEv2 with EAP Authentication
config vpn ipsec phase1-interface
edit "RA-IKEv2-PSK"
set interface "wan1"
set ike-version 2
set peertype any
set net-device disable
set mode-cfg enable
set proposal aes256-sha256
set dhgrp 14
set authmethod psk
set psksecret <your-psk>
set eap enable
set authusrgrp "IPSec_Users"
set ipv4-start-ip 10.156.10.10
set ipv4-end-ip 10.156.10.50
set dns-server1 8.8.8.8
set dns-server2 8.8.4.4
next
end
This is the key shift:
- EAP + user group establishes user identity
- PSK establishes tunnel trust
Phase2 – Keep It Simple
config vpn ipsec phase2-interface
edit "RA-IKEv2-PSK-P2"
set phase1name "RA-IKEv2-PSK"
set proposal aes256-sha256
set pfs disable
set src-subnet 0.0.0.0 0.0.0.0
set dst-subnet 0.0.0.0 0.0.0.0
next
end
Let mode-config and firewall policies do the heavy lifting.
The Moment of Truth: The Tunnel Comes Up
This time, the logs looked very different:
authentication succeeded
assigned IPv4 address 10.156.10.10
IPsec SA established
tunnel up event
FortiClient connected instantly.
Same laptop. Same ISP. Same FortiGate.
Only the configuration changed.
How the Firewall Knows Who You Are
A common question:
“If the tunnel uses a PSK, how does FortiGate know which user I am?”
Short answer:
It doesn’t — unless you enable EAP.
With EAP enabled:
- PSK establishes the tunnel
- FortiClient prompts for username/password
- FortiGate authenticates the user
- The user is mapped to local groups
- Policies are enforced per group
This is where real security starts.
One VPN, Multiple Roles (Best Practice)
We used this model:
Authentication Group
- IPSec_Users → who is allowed to connect
Authorization Groups
- VPN-Admins
- VPN-Support
Users belong to:
- IPSec_Users and one (or more) role groups
One tunnel. Clean separation. No tunnel sprawl.
Creating the RDP Policy for VPN-Admins
Now comes the most important part: access control.
Let’s assume:
- VPN interface: RA-IKEv2-PSK
- Internal servers network: 10.10.0.0/16
- Only VPN-Admins should have RDP access
Address Object (Servers Network)
config firewall address
edit "Internal-Servers"
set subnet 10.10.0.0 255.255.0.0
next
end
Firewall Policy – VPN-Admins RDP Access
config firewall policy
edit 0
set name "VPN-Admins_RDP"
set srcintf "RA-IKEv2-PSK"
set dstintf "internal"
set srcaddr "all"
set dstaddr "Internal-Servers"
set action accept
set schedule "always"
set service "RDP"
set groups "VPN-Admins"
set logtraffic all
next
end
What this policy does:
- Allows only VPN-Admins
- Coming from the VPN tunnel
- To access internal servers
- Using RDP only
- With full logging
No admin rights are implied. No trust is assumed.
Access is explicit.
Why This Design Works
This setup:
- Scales without adding tunnels
- Makes audits easier
- Aligns with Zero Trust principles
- Supports MFA later without redesign
- Keeps VPNs simple and policies strict
And most importantly…
It works reliably.
Final Takeaway
When IPsec VPN behaves irrationally:
- Don’t fight legacy config
- Don’t stack fixes on top of fixes
- Rebuild it clean
FortiGate VPNs are extremely solid — when you respect their logic.
Sometimes the fix isn’t another debug command.
It’s starting over, the right way.
Comments