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:

  1. PSK establishes the tunnel
  2. FortiClient prompts for username/password
  3. FortiGate authenticates the user
  4. The user is mapped to local groups
  5. 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.