Berik Ashimov // senior.it.engineer
Download CV
POSTS / MIKROTIK

IKEv2 on RouterOS 7: Certificates, Mode-Config, and the Profile/Proposal/Policy Maze

// series · MikroTik RouterOS 7 Guide part 7 of 35
  1. ... 4 earlier
  2. DHCP and DNS on RouterOS 7: The Services Everyone Misconfigures
  3. WireGuard on RouterOS 7: Road Warriors, Site-to-Site, and Allowed-Address Discipline
  4. IKEv2 on RouterOS 7: Certificates, Mode-Config, and the Profile/Proposal/Policy Maze
  5. IPv6 on RouterOS 7 Without Fear: Prefix Delegation, RA, and a Firewall That Holds
  6. CAKE on RouterOS 7: Killing Bufferbloat Without a QoS Degree
  7. ... 26 later
view the full series →

If WireGuard is so much simpler, why bother with IKEv2? Because IKEv2 is the VPN your devices already speak. iOS, macOS, Windows, Android — all ship a native IKEv2 client with OS-level integration: always-on VPN, per-app VPN, MDM deployment. No third-party app, no sideloading on managed devices. For BYOD and corporate fleets, IKEv2 is still the answer.

The problem is that MikroTik’s IPsec menu is a graveyard of abandoned attempts. Six interlocking objects — profile, proposal, peer, identity, policy, mode-config — and the names actively mislead. People set encryption in the profile and wonder why the proposal is ignored, or vice versa. Let’s kill that confusion first, because once the object model clicks, the rest is typing.

The Object Model, Straightened Out

  • Profile (/ip ipsec profile) — Phase 1 crypto: how the IKE control channel itself is encrypted. Parameters: enc-algorithm, hash-algorithm, dh-group. Mismatch here and nothing connects at all.
  • Proposal (/ip ipsec proposal) — Phase 2 crypto: how actual user traffic (the ESP tunnel) is encrypted. Parameters: enc-algorithms, auth-algorithms, pfs-group. Mismatch here and IKE succeeds but no child SA installs — “connected but no traffic.”
  • Peer (/ip ipsec peer) — who we talk to and how the exchange starts: address (or passive=yes to listen), exchange-mode=ike2, and which profile to use.
  • Identity (/ip ipsec identity) — how we authenticate that peer: certificates, EAP, PSK, plus what to hand out (mode-config) and what policies to generate.
  • Policy (/ip ipsec policy) — which traffic enters the tunnel (the traffic selectors). For road warriors you define a template that dynamically generated policies must match.
  • Mode-config (/ip ipsec mode-config) — the DHCP-of-IPsec: IP address, DNS, and split-tunnel networks pushed to clients.

Profile = phase 1, proposal = phase 2. Tattoo it somewhere. Every “IKEv2 won’t connect” thread on the forum is one of those two mismatched against a client’s expectations.

The CA

RouterOS has a built-in CA that’s perfectly adequate for a private VPN (it also speaks SCEP if you have real PKI; and a Let’s Encrypt certificate works too if clients trust it natively). Local CA:

Terminal window
/certificate
add name=ca common-name=ca key-size=2048 days-valid=3650 \
key-usage=key-cert-sign,crl-sign
sign ca ca-crl-host=vpn.example.com
# Server certificate — CN and SAN must match what clients dial
add name=vpn-server common-name=vpn.example.com \
subject-alt-name=DNS:vpn.example.com days-valid=1825 \
key-usage=tls-server
sign vpn-server ca=ca
# One certificate per client
add name=client-berik common-name=berik@example.com days-valid=825 \
key-usage=tls-client
sign client-berik ca=ca

The non-negotiable detail: the server certificate’s SAN must contain the exact hostname (or IP) clients connect to. iOS and Windows both validate it strictly. A mismatch produces the least helpful errors in the business — iOS says “user authentication failed” for what is actually a server certificate problem.

Export the client bundle as PKCS12 (private key + cert + CA in one file, which Apple and Windows both import cleanly):

Terminal window
/certificate export-certificate client-berik type=pkcs12 export-passphrase=CHANGE_ME
/certificate export-certificate ca file-name=ca # CA cert alone, PEM
# files land in /file — download via WinBox or sftp

Server Configuration

Address pool and mode-config first. address-prefix-length=32 hands each client a single address; split-include limits the tunnel to your networks; omit it for full tunnel.

Terminal window
/ip pool
add name=ike2-pool ranges=10.20.40.10-10.20.40.250
/ip ipsec mode-config
add name=ike2-conf address-pool=ike2-pool address-prefix-length=32 \
split-include=10.0.10.0/24 split-dns=example.com system-dns=no \
static-dns=10.0.10.1

Phase 1 profile and phase 2 proposal — modern algorithms only. AES-GCM in phase 2 gets hardware acceleration on ARM chips and skips the separate auth pass:

Terminal window
/ip ipsec profile
add name=ike2 enc-algorithm=aes-256 hash-algorithm=sha256 dh-group=modp2048,ecp256
/ip ipsec proposal
add name=ike2 enc-algorithms=aes-256-gcm,aes-256-cbc auth-algorithms=sha256 \
pfs-group=none

pfs-group=none in the proposal is deliberate — native iOS and Windows clients don’t do phase 2 PFS by default, and requiring it breaks them. Phase 1 DH already provides forward secrecy for the session keys.

Peer, policy group with template, and identity:

Terminal window
/ip ipsec peer
add name=ike2 exchange-mode=ike2 passive=yes profile=ike2
/ip ipsec policy group
add name=ike2-policies
/ip ipsec policy
add group=ike2-policies template=yes proposal=ike2 \
src-address=0.0.0.0/0 dst-address=10.20.40.0/24
/ip ipsec identity
add peer=ike2 auth-method=digital-signature certificate=vpn-server \
match-by=certificate remote-certificate=none \
generate-policy=port-strict mode-config=ike2-conf \
policy-template-group=ike2-policies

What each piece does: passive=yes makes the router listen instead of dial. The policy template=yes doesn’t match traffic itself — it’s a stencil that dynamically generated per-client policies must fit inside (dst-address must fall within 10.20.40.0/24). generate-policy=port-strict creates those per-client policies automatically at connect time. remote-certificate=none with match-by=certificate means: accept any client certificate that chains to a CA the router trusts — which is your local CA, since it’s installed. To revoke a client, revoke its cert (/certificate issued-crl handles the CRL when you sign with ca-crl-host set).

Firewall and NAT-T

IKEv2 needs UDP 500 (initial IKE) and UDP 4500 (NAT-T — IKE and ESP wrapped in UDP once a NAT is detected on the path). Since nearly every client is behind NAT, virtually all real traffic ends up on 4500. RouterOS handles the detection automatically; you just open the ports:

Terminal window
/ip firewall filter
add chain=input action=accept protocol=udp dst-port=500,4500 comment="IKEv2"
add chain=input action=accept protocol=ipsec-esp comment="ESP (non-NAT peers)"
add chain=forward action=accept src-address=10.20.40.0/24 \
out-interface-list=LAN comment="VPN clients to LAN"

Two classic traps. First, if you masquerade on the WAN interface, the NAT rule can rewrite packets before IPsec policies match them, breaking return traffic to clients. Exempt IPsec traffic in srcnat, above the masquerade rule:

Terminal window
/ip firewall nat
add chain=srcnat action=accept ipsec-policy=out,ipsec \
comment="Bypass NAT for IPsec — keep above masquerade"

Second, fasttrack: the default fasttrack-connection rule can punt established connections past IPsec processing. If clients connect but LAN traffic is one-way, exclude IPsec from fasttrack:

Terminal window
/ip firewall filter
set [find action=fasttrack-connection] ipsec-policy=out,none

(Strictly you want to skip fasttrack for both in,ipsec and out,ipsec traffic; two mirrored rules matching ipsec-policy above the fasttrack rule is the tidy version.)

Client Notes

iOS/macOS: install the CA certificate and the PKCS12 bundle (AirDrop or MDM; then Settings → General → VPN & Device Management — trust the CA explicitly under Certificate Trust Settings). Create an IKEv2 VPN: Server and Remote ID both set to vpn.example.com — Remote ID must equal the server cert’s SAN, this is the field everyone leaves blank — authentication “Certificate”, select the imported identity. For always-on or per-app VPN you’ll need a configuration profile built in Apple Configurator or MDM rather than manual settings.

Windows: import the PKCS12 into the machine store (certlm.msc → Personal) and the CA into machine Trusted Root Authorities. The built-in client defaults to embarrassingly weak phase 1/2 algorithms, so fix it in PowerShell:

Terminal window
# PowerShell, elevated
Add-VpnConnection -Name "HQ" -ServerAddress vpn.example.com \
-TunnelType IKEv2 -AuthenticationMethod MachineCertificate
Set-VpnConnectionIPsecConfiguration -ConnectionName "HQ" \
-AuthenticationTransformConstants SHA256128 -CipherTransformConstants AES256 \
-EncryptionMethod AES256 -IntegrityCheckMethod SHA256 -DHGroup Group14 \
-PfsGroup None -Force

Without that Set-VpnConnectionIPsecConfiguration, Windows proposes 3DES/SHA1-era suites your profile rightly refuses, and the error is a generic “policy match error.” Note also that Windows ignores split-include from mode-config unless the connection has “Use default gateway on remote network” unchecked — split tunneling on Windows is a client-side routing decision (Set-VpnConnection -SplitTunneling $true plus Add-VpnConnectionRoute).

Verification

Terminal window
/ip ipsec active-peers print
# state=established, dynamic-address = the mode-config address handed out
/ip ipsec installed-sa print
# one inbound + one outbound SA per client; watch current-bytes move
/ip ipsec policy print
# dynamic policies appear here per connected client, matching your template
/log print where topics~"ipsec"
# enable debug when hunting: /system logging add topics=ipsec,!packet

The debugging decision tree: nothing in active-peers → phase 1 problem (profile mismatch, certificate, UDP 500/4500 blocked). Established peer but no installed-sa → phase 2 problem (proposal mismatch, template too narrow). SAs installed but no traffic → NAT bypass rule missing or fasttrack eating it.

Closing Thoughts

IKEv2 on RouterOS is verbose but not actually hard once you stop confusing the profile with the proposal. What goes wrong is always one of five things: SAN mismatch on the server cert, phase 1 mismatch, phase 2 mismatch, NAT rule rewriting tunnel traffic, or fasttrack bypassing policies. That’s the entire debugging surface.

Use WireGuard where you control the endpoints — it’s less config and less CPU. Use IKEv2 where the OS-native client is the requirement. Mine run side by side on the same router: WireGuard for my own devices, IKEv2 for everything managed. Previous article in this series covers the WireGuard half.

// share