Multiple Road Warrior L2TP/IPsec clients behind NAT - solved

But unfortunately you cannot use manual peer config with multiple peer addresses (which works OK with auto-generated policies)

Don’t mix auto-generated (dynamic) policies with auto-generated (dynamic) peers. With mode-config, the policy is dynamically generated at both peers (“client” and “server”), always using the locally visible (public) IP address of the remote peer as sa-dst-address.

But yes, plain IKE2 uses policies to choose packets to be tunnelled, which you are famous for not being a fan of :slight_smile:

No worries Sindy

I’ve temporarily set in place a softether.org server instance which seems to work flawlessly with multiple clients dialling side-by-side behind same wan ip.

Would be nice to have a pure mikrotik solution to it, but I can also appreciate Mikrotik not focusing on L2TP/IPsec that much as it becomes deprecated in favour of IKE.

Will pursue this thread with same interest as your solution does look intriguing in its own right :slight_smile:

This is normal because you’ve kept the src-port=!4500 in the dst-nat rule. This causes the first connection established through the client-side NAT to bypass the whole thing. The sole purpose of this is to reduce flash wear as the whole “overcomplicated thing” is necessary only if multiple clients are behind the same NAT. The fact that you can see it as 2nd in the list is not important, the list is not ordered by connection establishment time. And it also explains why the rules preventing one connection from affecting the next one do not count, as there is no conflict. The second connection through the NAT comes from a source port like 1024, and the locally assigned source address (10.0.0.1) is added to the address-list, but as no further connection comes in before the scheduled script changes the to-addresses value in the action=src-nat rule, the collision-preventing rule (drop new connections if coming from an IP currently on address-list) has no reason to kick in.


No idea here, it sounds to me as unrelated to the NAT-beating setup.

Can you show me the output of /ip firewall connection print where dst-address~“:4500” (substitute the public IPs of course) while both connections are up (logged in)?

Can you add a 3rd device and show the same output?

Good day,
Great analysis and superb workaround!!

I had the same problem, came here googling. Now I know this is out of my league though so will find other solution.
Seems this is not a mikrotik issue, but a protocols and features limitation.
Would be nice though, to have the wiki updated on this things, giving that (to my knowledge) is the official mikrotik documentation, they should put a little effort in the guidance of this kind of common scenarios (roadwarriors behind NAT)..And if opting for betters solutions, as IKE is the trend, well then put that statement somewhere with emphasis.
I would have saved time not reading on solutions that require god level tweaking.
thanks again sindy!

It is actually not so complex once you draw it. The only complex thing in it is that you have to squeeze the functionality normally provided by two routers into just one.


Correct.


A standalone IKEv2 (i. e. without the L2TP on top of it) is the trend, not IKE(v1) which is outdated, and the way it is used in the operating systems’ native clients, IKEv2 has the advantage of leaving out one layer of tunneling so the confusion intirinsic to L2TP/IPsec doesn’t exist: also here, packets from each of the clients behind a common public IP arrive from a different UDP port, but unlike in the L2TP/IPsec case, the information about that client-representing port is not lost.

What scares many people is the need to handle certificates induced by the fact that all OS-provided IKEv2 clients seem to insist on their use although a pre-shared key is also supported by IKEv2 as a protocol suite. If all you want is to connect the device to a single VPN “server”, handling of certificates is actually not terribly complex. As soon as you need the same device to connect to several servers, it may be more tricky: I haven’t seen any support of multiple own identities on e.g. Windows or Android, so I’m afraid the embedded client would use the same certificate to authenticate itself to all servers, and this causes a headache if the certificate is not signed by any public certification autority because all servers would have to accept certificates signed by the private CA used. Which constitutes a security hole from the point of view of the server administrator.

But unless one of the certificate-related points as mentioned above is an issue for you, IKEv2 is an easy substitution of L2TP/IPsec which doesn’t suffer from the “multiple clients behind same public IP” trouble.

Thank you for information, explanation and example. I tested this, it works with iPhone and Windows and, really, Android can’t connect to the server :frowning:

I would suspect the Android connection issue to be related either to permitted encryption algorithms in peer profile and/or policy, or to some particular Android version. My variouos Android devices work well with this (except that after the initially suggested session time expires, they pretend to be connected but actually transport no data, but that’s again unrelated to the multiple-clients-behind-same-NAT issue).

So as the first step, I’d disconnect all clients if possible, enable IPsec logging (/system logging add topics=“ipsec,!packet”), run /log print follow-only where topics~“ipsec” file=ipsec-start, make an attempt to connect the Android, stop the log print once the Android reports failure, download the file and study it for encryption and authentication algorithm match between the devices.

Indeed you must set
/ip ipsec peer profile
enc-algorithm=aes-128,3des hash-algorithm=sha1

When you set other enc-algorithm like aes-256 or other hash algoritthm it will just fail on some Android versions.
For /ip ipsec proposal (phase 2 settings) you can have aes-256 enabled when you really think that the secret service is after you.

Hi!
I build a hub and spokes IKEv2/rsa signature auth with L2TP over IPSec setup with Tik deivces.
There is one central HUB with static public address, and there are some spokes, one of them have a dynamic public address, and the other is behind NAT where NAT public address is dynamic as well.
Public addressed CPE is connect to the HUB Tik router without any problem, but the CPE behind NAT can’t connect. I think because dynamic policy derived from template is always gets transport mode and I need tunnel mode. So IKEv2 not solve my problem :frowning:
I using RoS v6.44.3 all of the devices.
Sorry if someone asked the same before, but is there a way to create a template which creating tunnel mode dynamic policies? Or it is impossible?
cheers,
oreggin

A policy generated from a template always accommodates to the tunnel or transport mode requested by the remote peer.

Independent from this, I didn’t have in mind to use IKEv2 to transport L2TP instead of IKE(v1) but to use directly IKEv2, i.e. without the L2TP inside.

How can I request tunnel mode, if both side has dynamic policies? I can’t find this option in RoS :frowning:
I using BGP inside L2TP to distribute (IPv4+IPv6) routes between hubs and spoke, so i think i can’t drop L2TP, or can I? How?
Oh, and I missed the MPLS part inside the L2TP.

As you’ve mentioned IKEv2 and rsa-signature, I cannot see how you can use a dynamically created policy at both ends. Do you have use-ipsec=yes in the /interface l2tp-client settings? And if you do, doesn’t the dynamically created IKE(v1) peer collide with the manually created IKEv2 one when it comes to which one of the two will be used to create the SAs used by the policy? I mean, the two pairs of peers (with exchange-mode=main and with exchange-mode=ike2) may run simultaneously, but as IP addresses of the endpoints are the same, I don’t dare to guess which of the pairs of control SAs will be used to negotiate the transport SAs for the policy.


BGP would not be a problem with GRE or IPIP, but for MPLS you need L2TP or EoIP.

In any case, I think we’ve got quite far away from the scope of the topic - do you really have multiple spokes visible to the hub from behind a common IP address, and these spokes are road warriors, i.e. they connect from another place each time?

Under “/interface l2tp-client” I set “use-ipsec=no” as if I’m right it supports only PSK based auth.
I configured dynamic policies under “/ip ipsec”:

/ip ipsec peer set 0 exchange-mode=ike2
/ip ipsec identity set 0 auth-method=rsa-signature generate-policy=port-override

Unfortunately I didn’t found better solution.

Wait. Are you saying that by setting generate-policy=port-override at both peers, if one of them wants to send a packet to the other one, a matching transport policy is automatically generated from the template? That doesn’t make sense to me… I’ve always thought that at least one end must have a fixed policy, or use mode-config=request-only to request its local address from the remote peer and generate the local policy from the received mode-config instruction.

I didn’t mentioned IPSec is the outer and L2TP is inside of it. In the reverse situation the result performance is terrible.
Now I have dynamic policies on both end and it works if peers are not behind NAT.
I’m not an IPSec expert, so do you say I need set static policy on spokes? On spokes because I have only one fix IP and it has the HUB and I must set SA dest address in static policy? How policies generated on hub for each spokes? And how it will works if a spoke is behind NAT?

Thanks!

OK, I’m afraid I start understanding what’s actually going on there.


I don’t consider myself an IPsec expert either, just an advanced user. But my understanding is this:

  • to transport the actual data, you need a pair of security associations, which are basically unidirectional encrypted links
  • to choose which data to send via the security association and in which form, you need a policy, which is a combination of
    • the traffic selector - a combination of source and destination IP addresses or subnets and, eventually, protocol, and if protocol is specified and supports the notion of ports, also possibly of source and destination port
    • payload encapsulation mode (transport or tunnel)
    • encryption and authentication algorithms which may be chosen from (the “proposal”)
    • the rules to create and use the SA - the address of the remote device which must be one of IPsec peers, the local address to use if it makes a difference, and the sharing mode, i.e. whether an existing SA to the same remote peer can be reused for packets matching other policies’ traffic selectors
  • to control the establishment of the SAs needed to serve the policies, a “control” SA between the peers needs to be established first.

A “data” SA may be created only as late as when a packet matching policy’s traffic selector appears, or in advance. But if the packet to be transmitted doesn’t match the traffic selector of any existing policy, it is simply sent in plaintext. No comparison to peer addresses is done.

To accommodate for dynamic environments, you can use policy templates which are then used in one of the following ways:

  • if one peer has a manually configured policy (manually configured from the perspective of the IPsec astro clock), it offers its traffic selector to the other peer, which checks whether a mirror traffic selector fits to one of its policy templates and dynamically creates a policy if it does
  • if mode-config is used, the mode-config requestor (which is normally the initiator) gets the address and route list from the other peer and converts that into policies locally (so it needs to have generate-policy set to something else than no), and then offers the result to the other peer as in the case above
  • specifically for L2TP, EoIP, … tunnels in Mikrotik, the code handling the tunnel interface creates the policy at client side, so from the perspective of the user it is a dynamically created one but the IPsec treats it as one provided from outside, so it handles it as in the first point

All the above leads me to a conclusion that when you start the hub and the spoke on public address, you’ll likely find that no policy’s traffic selector actually matches the L2TP transport packets, so they flow between the devices in plaintext. Which also explains why it doesn’t work on spokes which are behind NAT.

When the policy is generated from a template, its sa-dst-address and sa-src-address are assigned dynamically to match those used by the “control” SA. This allows to traverse NAT if tunnel mode is used, and to certain extent also if transport mode is used - in particular, the combination of public IP and the port of the remote peer must be unique for each remote peer.

Thanks for deep explanations, good to learn something new every day.
BTW your conclusion is not exactly right as our L2TP tunnels are encrypted, I checked it. Dynamic policies generated on HUB and spokes and SA counters increasing with the amount of trasmitted bytes. I don’t say that I 100% understand why, but all of it works while all spokes has public IP. And you are right as I must have an additional firewall rule on HUB to drop unencrypted L2TP traffic.
My detailed configs over here:
HUB:

/ip ipsec peer add exchange-mode=ike2 local-address=192.0.2.1 name=Spokes passive=yes send-initial-contact=no
/ip ipsec identity add auth-method=rsa-signature certificate=cert_HUB generate-policy=port-override peer=Spokes

Spoke1:

/ip ipsec peer add address=192.0.2.1/32 exchange-mode=ike2 name=HUB
/ip ipsec identity add auth-method=rsa-signature certificate=cert_Spoke1 generate-policy=port-override peer=HUB remote-certificate=cert_HUB

192.0.2.1 is my HUB’s address for the documentation. I know the certs part is not clear for now but working on it :wink:

“ip ipsec policy print” on HUB shows every spokes has a policy with “DA” flag and “action=encrypt level=unique ipsec-protocols=esp tunnel=no ph2-count=1”

Do you think my setup would not work or it is bad conception?

I just don’t get how these dynamically created policies came into existence out of blue. I’ll have to check later how is that possible, but I’d prefer to see the full export and also the output of /ip ipsec policy print (anonymized along with the export as per my hint below to maintain consistence) from the hub and from one spoke on a public address.

Here are my anonymised configs and print outputs:

[oreggin@HUB] > ip ipsec export verbose
# may/20/2019 17:52:51 by RouterOS 6.44.3
# software id = XXXX-XXXX
#
# model = XXX
# serial number = XXXXXXXXXXXX
/ip ipsec mode-config
set [ find default=yes ] name=request-only responder=no
/ip ipsec policy group
set [ find default=yes ] name=default
/ip ipsec profile
set [ find default=yes ] dh-group=xxx dpd-interval=xxx dpd-maximum-failures=xxx enc-algorithm=xxx hash-algorithm=xxx lifetime=xxx name=default nat-traversal=yes proposal-check=xxx
/ip ipsec peer
add disabled=no exchange-mode=ike2 local-address=192.0.2.1 name=Spokes passive=yes profile=default send-initial-contact=no
/ip ipsec proposal
set [ find default=yes ] auth-algorithms=xxx disabled=no enc-algorithms=xxx lifetime=xxx name=default pfs-group=xxx
/ip ipsec identity
add auth-method=rsa-signature certificate=cert_HUB disabled=no generate-policy=port-override peer=Spokes
/ip ipsec policy
set 0 disabled=no dst-address=0.0.0.0/0 group=default proposal=default protocol=all src-address=0.0.0.0/0 template=yes
/ip ipsec settings
set xauth-use-radius=no
[oreggin@HUB] > ip ipsec policy print
Flags: T - template, X - disabled, D - dynamic, I - invalid, A - active, * - default 
 0 T * group=default src-address=0.0.0.0/0 dst-address=0.0.0.0/0 protocol=all proposal=default template=yes

 1  DA  src-address=192.0.2.1/32 src-port=any dst-address=198.51.100.1/32 dst-port=any protocol=all action=encrypt level=unique ipsec-protocols=esp tunnel=no proposal=default ph2-count=1
[oreggin@HUB] >

Spoke1:

[oreggin@spoke1] > ip ipsec export
# may/20/2019 17:52:57 by RouterOS 6.44.3
# software id = XXXX-XXXX
#
# model = XXX
# serial number = XXXXXXXXXXXX
/ip ipsec mode-config
set [ find default=yes ] name=request-only responder=no
/ip ipsec policy group
set [ find default=yes ] name=default
/ip ipsec profile
set [ find default=yes ] dh-group=xxx dpd-interval=xxx dpd-maximum-failures=xxx enc-algorithm=xxx hash-algorithm=xxx lifetime=xxx name=default nat-traversal=yes proposal-check=xxx
/ip ipsec peer
add address=192.0.2.1/32 disabled=no exchange-mode=ike2 name=HUB profile=default send-initial-contact=yes
/ip ipsec proposal
set [ find default=yes ] auth-algorithms=xxx disabled=no enc-algorithms=xxx lifetime=xxx name=default pfs-group=xxx
/ip ipsec identity
add auth-method=rsa-signature certificate=cert_Spoke1 disabled=no generate-policy=port-override match-by=certificate peer=HUB remote-certificate=cert_HUB
/ip ipsec policy
set 0 disabled=no dst-address=0.0.0.0/0 group=default proposal=default protocol=all src-address=0.0.0.0/0 template=yes
/ip ipsec settings
set xauth-use-radius=no
[oreggin@spoke1] > ip ipsec policy print
Flags: T - template, X - disabled, D - dynamic, I - invalid, A - active, * - default
 0 T * group=default src-address=0.0.0.0/0 dst-address=0.0.0.0/0 protocol=all proposal=default template=yes

 1  DA  src-address=198.51.100.1/32 src-port=any dst-address=192.0.2.1/32 dst-port=any protocol=all action=encrypt level=unique ipsec-protocols=esp tunnel=no proposal=default ph2-count=1
[oreggin@spoke1] >

I hope you can find out why my setup works.