Site-to-site Mikrotik IKEv2 VPN

Hi!

I’m trying to setup a VPN in the CCR1009-7G-1C-1S+ of my company, but facing strange problems. I’m using the latest stable version 6.47.1 in all devices.

I’ve been following Mikrotik’s Wiki tutorial (https://wiki.mikrotik.com/wiki/Manual:IP/IPsec#Road_Warrior_setup_using_IKEv2_with_RSA_authentication) and managed to setup a road-warrior setup that’s working ok with ubuntu 20.04 and Windows10.

In my home i have a Mikrotik RB750 which i use to connect to Internet, and i’ve tried to use it for a site-to-site VPN with my work’s router.

The IPSec tunnel is established correctly, but I can’t ping the other side addresses from none of the routers.

Thinking it was something in the routing rules of my company’s router I’ve tried to reproduce the scenario in GNS3, adding some vlans, as I have in the real setup, and the same behaviour happens.

This is the GNS3 setup:

I’ve followed the steps in Nikita Tarikin presentation (https://mum.mikrotik.com/presentations/ID19/presentation_7168_1572420263.pdf) but after establishing the connectivity I can’t ping the other side network.

I’ve tried to add remote networks in mode-config (split Include) but without success.

Server configuration:

/ip ipsec policy group
add name=ike2-group
/ip ipsec profile
add dh-group=modp2048,modp1536,modp1024 enc-algorithm=aes-256,aes-192,aes-128 hash-algorithm=sha256 name=ike2
/ip ipsec peer
add exchange-mode=ike2 name=ike2 passive=yes profile=ike2
/ip ipsec proposal
add auth-algorithms=sha512,sha256,sha1 enc-algorithms="aes-256-cbc,aes-256-ctr\
    ,aes-256-gcm,aes-192-ctr,aes-192-gcm,aes-128-cbc,aes-128-ctr,aes-128-gcm" \
    lifetime=8h name=ike2 pfs-group=none
/ip ipsec mode-config
add address-pool=ike2-pool address-prefix-length=32 name=ike2 split-include=\
    10.20.0.0/24,10.30.0.0/24 system-dns=no
/ip ipsec identity
add auth-method=digital-signature certificate=iesebre.com generate-policy=\
    port-strict match-by=certificate mode-config=ike2 my-id=fqdn:iesebre.com \
    peer=ike2 policy-template-group=ike2-group remote-certificate=\
    jaumeramos@iesebre.com remote-id=user-fqdn:jaumeramos@iesebre.com
/ip ipsec policy
add dst-address=10.10.0.0/24 group=ike2-group proposal=ike2 src-address=\
    0.0.0.0/0 template=yes

Client configuration:

/ip ipsec policy group
add name=ike2-group
/ip ipsec profile
add dh-group=modp2048,modp1536,modp1024 enc-algorithm=aes-256,aes-128 \
    hash-algorithm=sha256 name=ike2
/ip ipsec peer
add address=iesebre.com exchange-mode=ike2 name=ike2 profile=ike2
/ip ipsec proposal
add auth-algorithms=sha512,sha256,sha1 enc-algorithms="aes-256-cbc,aes-256-ctr\
    ,aes-256-gcm,aes-192-ctr,aes-192-gcm,aes-128-cbc,aes-128-ctr,aes-128-gcm" \
    lifetime=8h name=ike2 pfs-group=none
/ip ipsec identity
add auth-method=digital-signature certificate=jaumeramos@iesebre.com \
    generate-policy=port-strict mode-config=request-only my-id=\
    user-fqdn:jaumeramos@iesebre.com peer=ike2 policy-template-group=\
    ike2-group remote-id=fqdn:iesebre.com
/ip ipsec policy
add dst-address=0.0.0.0/0 group=ike2-group proposal=ike2 src-address=\
    10.10.0.0/24 template=yes

There’s no error in the log of both sides, but can’t ping the addresses of the router in any other side.

client side:

Server side:




Probably I’m missing something, but can’t find what it is.

Sorry for the long post.

I’ve been gathering more information, and I think there’s something wrong with the routes passed through modeconf.

The routes are shown in the IPSec policies, but do not work.

The tunnel is ok and the IP address is reachable

[admin@home] > ip address print 
Flags: X - disabled, I - invalid, D - dynamic 
 #   ADDRESS            NETWORK         INTERFACE                              
 0   10.40.0.1/24       10.40.0.0       home-40                                
 1   10.50.0.1/24       10.50.0.0       home-50                                
 2   10.100.0.2/24      10.100.0.0      ether2                                 
 3 D 10.10.0.199/32     10.10.0.199     ether2                                 
 4   10.200.0.2/24      10.200.0.0      ether1         
 
[admin@home] > ping 10.10.0.199 count=1
  SEQ HOST                                     SIZE TTL TIME  STATUS           
    0 10.10.0.199                                56  64 0ms  
    sent=1 received=1 packet-loss=0% min-rtt=0ms avg-rtt=0ms max-rtt=0ms

The tunnel is established and the routes passed through modeconf

[admin@home] > ip ipsec active-peers print 
Flags: R - responder, N - natt-peer 
 #    ID                   STATE              UPTIME          PH2-TOTAL
 0    iesebre.com          established        21m32s                  2
 
[admin@home] > ip ipsec policy print detail 
Flags: T - template, B - backup, 
X - disabled, D - dynamic, I - invalid, A - active, * - default 
 0 T  * group=default src-address=::/0 dst-address=::/0 protocol=all 
        proposal=default template=yes 

 1 T    group=ike2-group src-address=10.10.0.0/24 dst-address=0.0.0.0/0 
        protocol=all proposal=ike2 template=yes 

 2   DA  peer=ike2 tunnel=yes src-address=10.10.0.199/32 src-port=any 
        dst-address=10.20.0.0/24 dst-port=any protocol=all action=encrypt 
        level=unique ipsec-protocols=esp sa-src-address=10.100.0.2 
        sa-dst-address=10.100.0.1 proposal=ike2 ph2-count=1 

 3   DA  peer=ike2 tunnel=yes src-address=10.10.0.199/32 src-port=any 
        dst-address=10.30.0.0/24 dst-port=any protocol=all action=encrypt 
        level=unique ipsec-protocols=esp sa-src-address=10.100.0.2 
        sa-dst-address=10.100.0.1 proposal=ike2 ph2-count=1

But no ping to the addresses in the other side.

[admin@home] > ping 10.20.0.1 count=1 

  SEQ HOST                                     SIZE TTL TIME  STATUS           
    0                                                         no route to host 
    sent=1 received=0 packet-loss=100% 

[admin@home] > ping 10.30.0.1 count=1 
  SEQ HOST                                     SIZE TTL TIME  STATUS           
    0                                                         no route to host 
    sent=1 received=0 packet-loss=100%

Please print route list and address list on both sides.

Regards.

There must be some regular route for the packets whose source and destination addresses match the IPsec policies’ traffic selectors, as the policy matching only takes place after the regular routing is done. So if there is no route for a packet, the policies don’t get a chance to inspect it.

try to make sure you put firewall filter rules for both client and server side as per below

chain=input with protocol=ipsec-ah with action=accept
chain=input with protocol=ipsec-esp with action=accept

Thank you for your answers.

client side:

[admin@home] > ip add print          
Flags: X - disabled, I - invalid, D - dynamic 
 #   ADDRESS            NETWORK         INTERFACE                              
 0   10.40.0.1/24       10.40.0.0       home-40                                
 1   10.50.0.1/24       10.50.0.0       home-50                                
 2   10.100.0.2/24      10.100.0.0      ether2                                 
 3   10.200.0.2/24      10.200.0.0      ether1                                 
 4 D 10.10.0.200/32     10.10.0.200     ether2                                 

[admin@home] > ip route print detail 
Flags: X - disabled, A - active, D - dynamic, 
C - connect, S - static, r - rip, b - bgp, o - ospf, m - mme, 
B - blackhole, U - unreachable, P - prohibit 
 0 ADC  dst-address=10.10.0.200/32 pref-src=10.10.0.200 gateway=ether2 
        gateway-status=ether2 reachable distance=0 scope=10 

 1   S  dst-address=10.20.0.0/24 gateway=10.10.0.200 
        gateway-status=10.10.0.200 unreachable distance=1 scope=30 
        target-scope=10 

 2 ADC  dst-address=10.40.0.0/24 pref-src=10.40.0.1 gateway=home-40 
        gateway-status=home-40 reachable distance=0 scope=10 

 3 ADC  dst-address=10.50.0.0/24 pref-src=10.50.0.1 gateway=home-50 
        gateway-status=home-50 reachable distance=0 scope=10 

 4 ADC  dst-address=10.100.0.0/24 pref-src=10.100.0.2 gateway=ether2 
        gateway-status=ether2 reachable distance=0 scope=10 

 5 ADC  dst-address=10.200.0.0/24 pref-src=10.200.0.2 gateway=ether1 
        gateway-status=ether1 reachable distance=0 scope=10

server side:

[admin@iesebre] > ip add print          
Flags: X - disabled, I - invalid, D - dynamic 
 #   ADDRESS            NETWORK         INTERFACE                              
 0   10.20.0.1/24       10.20.0.0       iesebre-20                             
 1   10.30.0.1/24       10.30.0.0       iesebre-30                             
 2   10.10.0.1/24       10.10.0.0       bridge-loopback                        
 3   10.100.0.1/24      10.100.0.0      ether2                                 
 4   10.200.0.1/24      10.200.0.0      ether1                                 

[admin@iesebre] > ip route print detail 
Flags: X - disabled, A - active, D - dynamic, 
C - connect, S - static, r - rip, b - bgp, o - ospf, m - mme, 
B - blackhole, U - unreachable, P - prohibit 
 0 ADC  dst-address=10.10.0.0/24 pref-src=10.10.0.1 gateway=bridge-loopback 
        gateway-status=bridge-loopback reachable distance=0 scope=10 

 1 ADC  dst-address=10.20.0.0/24 pref-src=10.20.0.1 gateway=iesebre-20 
        gateway-status=iesebre-20 reachable distance=0 scope=10 

 2 ADC  dst-address=10.30.0.0/24 pref-src=10.30.0.1 gateway=iesebre-30 
        gateway-status=iesebre-30 reachable distance=0 scope=10 

 3 ADC  dst-address=10.100.0.0/24 pref-src=10.100.0.1 gateway=ether2 
        gateway-status=ether2 reachable distance=0 scope=10 

 4 ADC  dst-address=10.200.0.0/24 pref-src=10.200.0.1 gateway=ether1 
        gateway-status=ether1 reachable distance=0 scope=10



I had already tried to add a static route. From the client I can ping the local address of the tunnel, but if I try to add a route using that address it says that is “unreachable”.

[admin@home] > ping 10.10.0.200 count= 2 
  SEQ HOST                                     SIZE TTL TIME  STATUS           
    0 10.10.0.200                                56  64 0ms  
    1 10.10.0.200                                56  64 0ms  
    sent=2 received=2 packet-loss=0% min-rtt=0ms avg-rtt=0ms max-rtt=0ms 

[admin@home] > ip route print detail 

 1   S  dst-address=10.20.0.0/24 gateway=10.10.0.200 
        gateway-status=10.10.0.200 [b]unreachable[/b] distance=1 scope=30 
        target-scope=10



In my GNS3 test project there’s no filter firewall rules, so everything is accepted.

OK. The issue is the following:

  • the initiator (client) gets an IP address from the responder (server) from the pool, via the IKEv2 equivalent of mode config
  • the policies are automatically created at the initiator - one per each subnet on the mode-config row’s split-include list; however, the src-address of these policies is the /32 IP address assigned to the initiator via mode-config
  • none of the routes you have has pref-src set to this address, and it would be impractical to do that as in generic case, a different address may be assigned with each connection

The mechanism designed to resolve this is that you configure a src-address-list and/or connection-mark item in the only mode-config row on the initiator, and once the connection gets up and the initiator receives the mode-config settings (address, traffic selectors for the split-include subnets), a rule in chain srcnat of /ip firewall nat is created dynamically to src-nat all connections from addresses matching the address-list and/or connections matching the connection-mark set in the mode-config to the address dynamically assigned via mode-config. One such rule is created per every destination subnet listed in the split-include.

So you typically have to either use rules in chain prerouting of /ip firewall mangle to assign the connection-mark to whatever you want to be sent via the IKEv2 connection (so you use all the flexibility of mangle), or you configure a dedicated LAN subnet into the address-list, so all hosts in this LAN subnet use the IKEv2 connection.

If you want all traffic to the split-include destinations to be sent via the IKEv2 connection no matter the source address, you still have to create an address-list with a single item - list=via-ike2 address=0.0.0.0/0 and refer to it from the mode-config row. If no src-address-list is specified on the request-only mode-config row, the dynamic NAT rules are not created.

@sindy Your post was really helpful for me to understand how modeconfig works. Hope Mikrotik’s documentation was as good as your explanation!

Following your advice I’ve been able to put to work my test setup, and what’s more important, now I have a better understanding of how the tunnel works. :slight_smile:

I’ve added my local LAN in an address-list and put it into the modesetting line of the initiator. Now I can see the dynamic srcnat rule and I can reach the remote network. Now I’ll try to use Mangle rules as you advised.



Thank you very much for all the answers!!