IKEv2 for macOS clients with multiple networks behind the tunnel

Hi there,
I’m currently trying to implement an IKEv2 server in ROS (6.48.1) for macOS (Catalina/10.15) clients. Everything works great but only the first network in split-include is reachable. I have found multiple posts on this forum blaming the Apple VPN client. But I don’t think the problem is on the Apple side at least on my case. I think the problem resides on the dynamic policy generation on the Mikrotik side. Looks to me that the macOS client does add routes via the VPN interface for every network listed on the split-include parameter, but the dynamic policy generated on the router only includes the first network.

So the question is, how can I tell ROS to generated a policy for each network in the split-include parameter once a client connects?

Here is an example of the only dynamic policy generated once a client connects, as you can see, it only includes the network 10.10.9.0/24:

 2   DA  peer=roadw tunnel=yes src-address=10.10.9.0/24 src-port=any
        dst-address=10.10.200.200/32 dst-port=any protocol=all action=encrypt level=unique
        ipsec-protocols=esp sa-src-address=a.a.a.a sa-dst-address=b.b.b.b
        proposal=default ph2-count=1

And here are the routes generated on macOS for that connection, this is printed with netstat -nrf inet, as you can see both 10.10.9.0/24 and 10.10.10.0/24 are added:

default            link#12            UCSI        ipsec0
10.10.9/24         10.10.200.200      UGSc        ipsec0
10.10.10/24        10.10.200.200      UGSc        ipsec0
10.10.200.200      10.10.200.200      UH          ipsec0

Here is a redacted export of my ipsec configuration

/ip address
add address=a.a.a.a/29 interface=e1
add address=10.10.9.1/24 interface=bridge.9
add address=10.10.10.1/24 interface=bridge.10
/ip pool
add name=roadw-pool ranges=10.10.200.33-10.10.200.200
/ip ipsec mode-config
add address-pool=roadw-pool address-prefix-length=32 name=roadw-config split-dns=\
    example.com split-include=10.10.9.0/24,10.10.10.0/24 \
    static-dns=10.10.10.1 system-dns=no
/ip ipsec peer
add comment="RoadWarrior IKEv2" exchange-mode=ike2 local-address=a.a.a.a name=roadw \
    passive=yes send-initial-contact=no
/ip ipsec policy group
add name=roadw
/ip ipsec profile
set [ find default=yes ] enc-algorithm=aes-256 hash-algorithm=sha256
/ip ipsec proposal
set [ find default=yes ] auth-algorithms=sha256 enc-algorithms=aes-128-cbc,aes-128-gcm \
    pfs-group=modp2048
/ip ipsec identity
add auth-method=digital-signature certificate=gw01.example.com \
    generate-policy=port-strict mode-config=roadw-config peer=roadw policy-template-group=\
    roadw
/ip ipsec policy
add dst-address=0.0.0.0/0 group=roadw src-address=10.10.9.0/24 template=yes
add dst-address=0.0.0.0/0 group=roadw src-address=10.10.10.0/24 template=yes

Thanks in advance for your time.

Hi,
I also was playing a little bit with IKEv2. As I know macOS has some limitations.
In MikroTik wiki: https://wiki.mikrotik.com/wiki/Manual:IP/IPsec

Known limitations
Here is a list of known limitations by popular client software IKEv2 implementations.

Windows will always ignore networks received by split-include and request policy with destination 0.0.0.0/0 (TSr). When IPsec-SA is generated, Windows requests DHCP option 249 to which RouterOS will respond with configured split-include networks automatically.
Both Apple macOS and iOS will only accept the first split-include network.
Both Apple macOS and iOS will use the DNS servers from system-dns and static-dns parameters only when 0.0.0.0/0 split-include is used.
While some implementations can make use of different PFS group for phase 2, it is advised to use pfs-group=none under proposals to avoid any compatibility issues.

Maybe Apple has changed something and now is capable of more than one route.

But I think you have to do more general police and combine your two polices into one. I think that Mikrotik can generate only one dynamic police.
So in your case, I’ll do

/ip ipsec policy
add dst-address=10.10.200.0/24 group=roadw src-address=10.10.9.0/23 template=yes

If those two networks are only examples, and can’t be group so easy to one bigger network eg 10.0.10.0/24 and 192.168.1.0/24 I’ll do a general rule with src-address=0.0.0.0/0 dst-address=10.10.200.0/24 and add rules to firewall to permit only 10.0.10.0/24 and 192.168.1.0/24

So I followed the recommendation and widened the template policy like this

/ip ipsec policy
add dst-address=10.10.200.0/24 group=roadw-group src-address=0.0.0.0/0 template=yes

And also just for kicks added a windows client to the mix just to see the difference. I had to disable PFS since windows does not support it apparently. But in the end I managed to connect both clients at the same time.

The generated policies that are based on the same template, are different for some reason, check the src-address. Something is broken here and it does not look like the client.

# This is the policy generated for macOS
 2   DA  peer=roadw tunnel=yes src-address=10.10.9.0/24 src-port=any
        dst-address=10.10.200.200/32 dst-port=any protocol=all action=encrypt level=unique
        ipsec-protocols=esp sa-src-address=a.a.a.a sa-dst-address=b.b.b.b
        proposal=default ph2-count=1

# This is the policy generated for Windows
 3   DA  peer=roadw tunnel=yes src-address=0.0.0.0/0 src-port=any dst-address=10.10.200.199/32
        dst-port=any protocol=all action=encrypt level=unique ipsec-protocols=esp
        sa-src-address=a.a.a.a sa-dst-address=b.b.b.b proposal=default
        ph2-count=1

Here is how the routing tables look on the clients
Windows

10.10.9.0    255.255.255.0         On-link     10.10.200.199     26
10.10.9.255  255.255.255.255         On-link     10.10.200.199    281
10.10.10.0    255.255.255.0         On-link     10.10.200.199     26
10.10.255  255.255.255.255         On-link     10.10.200.199    281
10.200.199  255.255.255.255         On-link     10.10.200.199    281

macOS

default            link#12            UCSI        ipsec0
10.10.9/24         10.10.200.200      UGSc        ipsec0
10.10.10/24        10.10.200.200      UGSc        ipsec0
10.10.200.200      10.10.200.200      UH          ipsec0

I love how Mikrotik went out of their way to make a non-standard client like windows work out of the box by doing the DHCP magic, I really do. But I also think standard compliance should come first, and from what I can tell, the IKEv2 macOS client is doing it’s job correctly here and RouterOS is not. I wonder how a StrongSwan client would behave in this case, I might just try that next and see.
Anyway, I would love to be corrected on this so if anyone can jump in and prove me wrong I would be delighted.

I’m not sure if I understand your problem. Do you wonder why those two polices are different?
In my opinion it is because of windows. As you can see in a fragment from wiki which I’ve quoted already

Windows will always ignore networks received by split-include and request policy with destination 0.0.0.0/0 (TSr). When IPsec-SA is generated, Windows requests DHCP option 249 to which RouterOS will respond with configured split-include networks automatically.

Also on the same wiki page - https://wiki.mikrotik.com/wiki/Manual:IP/IPsec#Split_tunnel_configuration you have annotation

Warning: Split networking is not a security measure. The client (initiator) can still request a different Phase 2 traffic selector.

So you should additional firewall rules

Hi fpawlak, thanks for your reply. No, I’m not wondering anything, I’m simply stating the fact that IKEv2 seems to be broken in RouterOS when used with split-include, and that it only works with Windows clients by using a non-standard behavior of that specific client. Everything else in my posts is me trying to proof that fact.
As for the security warning on the Mikrotik Wiki, I don’t really care, this is a lab and security is not important or relevant to the conversation. If this ever gets to production, that warning will be taken into consideration. And no, there is no need for firewall rules on my setup other than for security purposes.

I haven’t tested Windows 10 client against other IKEv2 servers. But I think that Windows is not working properly, ignoring split include and asking for 0.0.0.0/0 police. But I may be wrong.

You are right, windows does not behave in a standard way, and yet (thankfully) it works with RouterOS. The real problem is that clients that do behave in a standard way, don’t work with RouterOS. Hopefully they will soon.

Hey @carragom,

I have the exactly same situation. On Windows 10/11 I get all the routes and the policy being generated is from 0.0.0.0/0 to whatever network was defined on the “Address Pool” at the IPSec Mode Config. All traffic flow just as expected. However, on MacOS and iOS, it generate routes for everything on the split include but, the template generate only a single policy, for the first split include network.

That is definitively a RouterOS issue. I want to move away from L2TP/IPSec to IKEv2 tunnels but as it seems, I’ll need to move away from MikroTik if that simple case isn’t supported :frowning:

Have you tried to talk to MikroTik support already?

Thanks!
Gutemberg

Hi! Any news on this issue? May be in newer versions (7+) of routeros its fixed? Or there is some workarounds?

With ROSv7 I switched from IKEv2 to WireGuard and my problems with more than one subnet as interesting traffic for the VPN tunnel are now gone. Sorry IKEv2, WireGuard is more versatile and simple to configure and deploy!

Well I tested this setup with StrongSwan Android client and it’s the same problem. Only the first network in split-include works.

Also tested a Linux client using NetworkManager with the StrongSwan plugin and again only the first network in split-include works.

I would love to be proven wrong but this seems like a problem in RouterOS where it only adds a dynamic policy for the first network in split-include.

I opened a support ticket referencing this thread. Hopefully I will get an answer.

These tests where using RouterOS v7.12.1 which is the latest stable version at this time.

any update on this?