L2TP/IPsec - how do I set different users with dynamic IP?

This is what I have:

  1. One L2TP/IPSec server, which should be used by several users. Dynamic IP.
  2. Several road warriors, that should be able to use the server - but with different passwords.

The server and road warriors are using ROS 6.41.3

I must be missing something quite obvious, but have no idea what it would be.

This is the server configuration:

/ip ipsec mode-config
set [ find default=yes ] name=request-only
/ip ipsec policy group
set [ find default=yes ] name=default
add name=redescambo
/ip ipsec proposal
set [ find default=yes ] auth-algorithms=sha1 disabled=no enc-algorithms=aes-256-cbc,aes-192-cbc,aes-128-cbc lifetime=30m name=default pfs-group=modp1024
add auth-algorithms=sha1 disabled=no enc-algorithms=aes-256-cbc,aes-192-cbc,aes-128-cbc lifetime=30m name=RedEscambo_proposal pfs-group=modp1024
/ip ipsec peer
add address=::/0 auth-method=pre-shared-key comment=RedEscambo dh-group=modp2048,modp1024 disabled=no dpd-interval=2m dpd-maximum-failures=5 enc-algorithm=aes-256,aes-192,aes-128 exchange-mode=main-l2tp generate-policy=port-strict \
    hash-algorithm=sha1 lifetime=1d nat-traversal=no passive=yes policy-template-group=redescambo proposal-check=obey secret=<my secret> send-initial-contact=yes
/ip ipsec policy
set 0 disabled=yes dst-address=::/0 group=default proposal=default protocol=all src-address=::/0 template=yes
add comment="RedEscambo policy" disabled=no dst-address=::/0 group=redescambo proposal=RedEscambo_proposal protocol=udp src-address=::/0 template=yes
/ip ipsec user settings
set xauth-use-radius=no

One of the peers config

/interface l2tp-client
add allow=chap comment=“Conect on server” connect-to= ipsec-secret= keepalive-timeout=disabled name=l2tp-ipsec-server password=
profile=default use-ipsec=yes user=


As of now, all the road warriors connect - but using the same IPSec secret. What I want is - exactly - to have one different secret to each client. If I declare one more peer, with a different secret, everything goes to hell. Only the higher one (the first match) will connect. The rest will get a “wrong password” error. One would expect the server would try all the peers, before giving up.

So, this is the problem. What am I doing wrong? How do I fix this?

Thanks,

Found one (partial) solution - but it led me into another problem.

Server part: Use “pre shared key xauth”. The secret is the same (sigh) - but now I have user and password, so works for me. Probably could do it with rsa keys too, but didn’t test it. The setup part that changed is:

/ip ipsec peer
add address=0.0.0.0/0 auth-method=pre-shared-key-xauth comment="Redescambo psk xauth" dh-group=modp1024 enc-algorithm=aes-256,aes-192,aes-128 exchange-mode=main-l2tp generate-policy=port-strict passive=yes policy-template-group=\
    redescambo secret=<ipsec password>

And added the users and password to /ip ipsec user. So far, so good. Now, the new problem:

I can’t use, on the clients, the L2TP menu to create the IPSec rules anymore. It only understands “IPsec secret” as authentication, and I’m using “pre shared key with xauth”. So, I decided to create by hand the L2TP IPsec config. And got stumped. I can make the client connect, and authenticate, with the server. But I can’t make them create the policy, and can’t force the client to use IPsec on the L2TP connection.

I made it work. Sort of. Using a hack ugly as hell:

On the client:

  1. Create the L2TP connection, as usual.
  2. Mark “use IPsec”
  3. Leave the secret blank.
  4. Create a peer, by hand, at the IPsec config:
/ip ipsec peer
add address=<server FQDN> auth-method=pre-shared-key-xauth comment="psk xauth" dh-group=modp1024 enc-algorithm=aes-256,aes-192,aes-128 exchange-mode=main-l2tp generate-policy=port-strict secret=<IPsec secret> xauth-login=<username> \
    xauth-password=<user password>

It works. Sort of. But hurts my brain, just to know i did it. If I could just find out how to force L2TP to use IPsec, without using that checkmark on the connection…

Anyone has an idea?
Thanks,

No one? Cant it be done?

Wouldn’t it be enough for you to block outgoing L2TP connections if there’s no IPSec policy?

/ip firewall filter
add action=reject chain=output dst-port=1701 ipsec-policy=out,none protocol=udp \
    reject-with=icmp-network-unreachable

But my problem is, exactly, to make the mikrotik use IPsec with L2TP!

Without using the easy way (useless to me, as I want to use xauth or RSA), I can’t force it to encrypt the L2TP tunnel.

Even using this line on L2TP/IPsec client:

/ip ipsec peer
add address=<IPSec server> auth-method=pre-shared-key-xauth comment="ps xauth" enc-algorithm=aes-256,aes-192,aes-128 exchange-mode=main-l2tp my-id=fqdn:victor policy-template-group=redescambo secret=segredo \
    xauth-login=<username> xauth-password=<password>

It just tries to connect the L2TP without IPsec.

I understand. And no, with the rule I posted, L2TP won’t be directly linked with IPSec in any way. But that rule will prevent outgoing L2TP connections, if there won’t be IPSec policy, i.e. the packets would go out unencrypted. Once there’s the independently established IPSec link, L2TP client will be allowed to connect. It’s not perfect, but the end result should be ok.

I don’t know what is the degree of automation you expect. If the idea is to only enable manually the ****

l2tp-out

using the GUI (Winbox, WebFig) and let the RouterOS establish the IPSec transport for it, I can suggest you a simple script to be scheduled for every 10 seconds or so which would copy the value of the

disable

parameter of

l2tp-out

to the one of the IPsec peer. @Sob’s rule would remain in place to prevent the l2tp packets from leaving the Mikrotik without encryption, until the IPsec SA between the peers establishes.

My problem is exactly this: the SA is not established. Even if i copy, by hand, the policy automatically created by the L2TP client interface.

In the logs I see the IPsec xauth connection. I know the user/password was accepted (forced the error with a wrong one). But the policy is not installed - and I can’t understand why.

Server always use the same setup. Client as follows:

Case 1:
Connection made through L2TP client. I check the “use IPsec” option. Connection is made, L2TP goes through IPsec. The following dynamic policy is created on the client. Everything works.

src-address=<client ip>/32 src-port=1701 dst-address=<server ip>/32 dst-port=1701 protocol=udp action=encrypt level=require ipsec-protocols=esp tunnel=no proposal=default ph2-count=1

Case 2:
Connection made through L2TP client. I don’t check the “use IPsec” option. I manually insert the policy below. Connection is made, L2TP goes through IPsec. Everything works.

src-address=<client ip>/32 src-port=1701 dst-address=<client ip>/32 dst-port=1701 protocol=udp action=encrypt level=require ipsec-protocols=esp tunnel=no proposal=default ph2-count=0

Case 3:
Connection made through L2TP client. I don’t check the “use IPsec” option. I manually insert the template policy below. Connection is made, L2TP does not go through IPsec. Why? Shouldn’t the template take care of this?

add dst-address=0.0.0.0/0 protocol=udp src-address=0.0.0.0/0 template=yes

The IPsec authentications works, but not the phase 2

 19:13:36 ipsec,info respond new phase 1 (Identity Protection): <server IP>[500]<=><client ip>[500] 
19:13:36 ipsec,info ISAKMP-SA established <server ip>[500]-<client IP>[500] spi:30ac132170db79af:a849ce5a6cd3ef0a

Both machines are using public IPs.

I have few blanks in my knowledge when it comes to IPSec, so I’m sorry if I happen to be lying. But I don’t think you can use templates on both ends, one of them needs to suggest a policy and the other can accomodate to that if it has template that allows it.

With road warriors setup, the server doesn’t know where clients will connect from (so it will use template), but client knows where server is, so it can have a policy defined. Only trouble is when client has dynamic address, then the local address for IPSec needs to be updated. I believe it’s one of the reasons why IPSec was never fun to work with.

To me, the mysterious part was the link between the L2TP authentication and IPsec authentication, but it seemed to me that you’ve already got past that.

When you check the “use IPsec” in L2TP client configuration, both an IPsec peer and an IPsec policy are created “dynamically”. The dynamically created policy:

  • is a “real” policy, not a template,
  • matches UDP traffic from port 1701 at the IP address which is the best-fitting local source for the route towards the “server” to port 1701 at the IP address of the “server”,
  • and requires use of ESP in transport, not tunnel, mode. So it only encrypts and encapsulates the L2TP transport packets.

The generic (i.e. not L2TP/IPsec specific) policy template on the server side is open so widely that a mirror policy to the above one can be generated from it. The peer has an exchange mode “main-l2tp”, which is an important point.

When you check the “use IPsec” in L2TP server configuration, a “dynamic” IPsec peer is generated as well, with policy-generate mode set to “port strict”, choosing from policy template group “default”, and with authentication mode “main-l2tp” as well.

The manual says:

main-l2tp > mode relaxes rfc2409 section 5.4, to allow pre-shared-key authentication in main mode.

I’m also not sure what that means in detail, but the outcome is that a match of the pre-shared key between the peers (and intersection of IPsec proposals of course) is the only prerequisite necessary to establish an IPsec SA between such peers. No additional authentication is necessary.

To check this, you may

  • disable all the peers and policies you’ve created manually and keep only the default ones
  • activate an L2TP server with use-ipsec=true and a pre-shared secret at the server side, and create an L2TP client interface with corresponding settings at the client side
  • do ****
/ip ipsec peer add copy-from=[find exchange-mode="main-l2tp"] disabled=yes

at both the server machine (at any time) and the client machine (while the L2TP connection establishment attempt is running

  • do ****
/ip ipsec policy add copy-from=[find src-port=1701] disabled=yes

at the client machine while the L2TP connection establishment attempt is running

  • disable the L2TP server and the L2TP client interface, and enable the cloned peers and policies.

At this moment, you should see two SAs established.

And this is the moment when, in the “normal” case where these peers and policies are dynamically created and activated by the L2TP/IPsec astro clock, the L2TP client starts establishing its conection to the server. If the attempt doesn’t succeed within timeout, the client side removes the dynamic peer and policy and starts the whole procedure again.

So to summarize: in the L2TP/IPsec “bundle”, the IPSec is only used to encapsulate and encrypt the connection between the L2TP client and the L2TP server. All the rest (authentication of the L2TP client, choice of the address to be assigned to the client based on its user name, its assignment to the virtual interface at client side, delivery of default route etc.) are the job of L2TP, And the operation of the L2TP part is identical regardless whether the packets between client:1701 and server:1701 run via IPsec SAs or directly.

By decoupling the IPsec layer from the L2TP, which consists in unchecking the “use IPsec” in L2TP configuration and configuring IPsec peers and client side policy manually or using a script if the client’s address changes, you can choose different encrytptions and authentication algorithms, but you must not change the “main-l2tp” exchange mode, and you effectively cannot use rsa-key mode because exactly one remote key must be indicated.

If you use IPsec xauth, the user name and password are used to authorize the user and eventually choose a particular client-side IP address for him already at IPsec level. At server side, the necessary user name and password are configured in the ****

/ip ipsec user

branch rather that the

/ppp secret

one. The IP settings are delivered to the client using the mode-config mechanism, and the address is not assigned to an eventually existing L2TP interface at client side (about which the IPsec layer knows noting at all). The mode-config mechanism attaches the IP address as a secondary one to a seemingly randomly chosen local interface of the client and creates the policy (or multiple policies if “split include” is configured) referring to this address at client side.

xauth can only be used together with pre-shared key, rsa-signature (the mode is called rsa-signature-hybrid) and IKEv2 modes. rsa-key mode does not permit a wildcard for the remote key and it is impossible to have the same rsa key at all clients as the private part of it must always be generated locally.

To use L2TP over IPsec with xauth is possible but it is a kind of an overkill, plus you need two user names and two passwords (which may be identical but need to be configured at two places per connection side) and two IP addresses (which must differ) per client to make it work.

However, although the mode-config settings at both ends mention an address prefix size, and the IP settings at client side respect that, the generated policies don’t. This may be a bug of the versions used (6.41.1 at server side and 6.42rc49 at client) or an intention, I don’t know.

But, from ROS 6.41 onwards, we can declare an FQDN as the peer address! Take this, for example:

/ip ipsec peer
add address=<server FQDN> comment=psk enc-algorithm=aes-256,aes-192,aes-128,3des exchange-mode=main-l2tp generate-policy=port-strict secret=<ipsec secret>

This is the config I used to connect to the server IPsec. It connects, and verifies the password. It just doesn’t create the SA. Even weirder, take this print:

 1 X   ;;; psk
       address=<server FQDN> auth-method=pre-shared-key secret="IPsec password" generate-policy=port-strict policy-template-group=default exchange-mode=main-l2tp send-initial-contact=yes nat-traversal=yes proposal-check=obey 
       hash-algorithm=sha1 enc-algorithm=aes-256,aes-192,aes-128,3des dh-group=modp2048,modp1024 lifetime=1d dpd-interval=2m dpd-maximum-failures=5 

 2  D  address=<server IP>/32 auth-method=pre-shared-key secret="IPSec password" generate-policy=port-strict policy-template-group=default exchange-mode=main-l2tp send-initial-contact=yes nat-traversal=yes proposal-check=obey 
       hash-algorithm=sha1 enc-algorithm=aes-256,aes-192,aes-128,3des dh-group=modp2048,modp1024 lifetime=1d dpd-interval=2m dpd-maximum-failures=5

The rule #1 I created by hand. It is disabled now. The rule #2 was created by checking the “use IPsec” option, on the client I took this print from. Rule #1 connects, but doesn’t create SA. Rule #2 connects and creates SA. How come? Is it a bug?

Yes, I will need two usernames and two passwords. Maybe I’m being paranoid, but I don’t like the idea of only one password to the IPsec. You see, this would be used with some users and I want to be able to block one of them. With only one IPsec password I would need to warn all the other users, when I changed it.

By the way: You post was really informative, and I thank You for it. Some things really helped with my understanding of the situation.

But, at this point, I believe I just found a bug. My post just above this one shows my reasoning. What do You think?

I thought that L2TP client with enabled IPSec adds not only peer, but also policy. It would explain, why it doesn’t work with your manual peer, when you don’t add any policy.

But the peer added by L2TP really does have generate-policy=port-strict policy-template-group=default. Although it’s strange that it works even when I disable default template. What does it use then? And even with default template enabled, it’s for 0.0.0.0/0 and all protocols on both ends, so how exactly it changes to udp/1701?

Even before this, I thought that generate-policy=<port-override|port-strict> in other words means “wait for what peer suggests, and if it fits in my template, use it”. And if it’s on both sides, they both wait for the other one and nothing happens. Because that’s exactly what I’ve been seeing. Although, I also thought that generate-policy on both sides could work, initiator could take templates from given group and suggest to use them. But it just doesn’t, no matter what I do.

I guess I’m officially confused. Do we have any real experts here? :slight_smile:

To understand the recursivity You must understand the recursivity.

It looks, more and more, like a bug to me. Server has a 0.0.0.0/0, all protocols, all ports policy. It gets used, when the client policy is generated by the L2TP client - or if I copy it with the IPs and use. But if I copy it, change the server’s IP address to its FQDN name (keeping the rest equal), it stops working. Really weird.

One detail, what you’ve shown in previous post is peer (/ip ipsec peer), not policy (/ip ipsec policy). If you’d copy both, it would work. But policy doesn’t take FQDNs.

As @Sob has pointed out, the “rules” you mention here are peer configurations, not policies.

In my summary, I have written clearly:

disable the L2TP server and the L2TP client interface, and enable the cloned > peers > and > policies> .

Without a policy, there is no reason to create an SA - the SA is a “carrier channel” for a policy. So the astro clock associated to the “use ipsec” checkmark in the L2TP configuration generates both the peer and the policy at the client side, and if you disable that astro clock, you must provide manually what it creates when active, which means the peer and the policy.

Yes, I will need two usernames and two passwords. Maybe I’m being paranoid, but I don’t like the idea of only one password to the IPsec. You see, this would be used with some users and I want to be able to block one of them. With only one IPsec password I would need to warn all the other users, when I changed it.

Both the xauth user/password and the l2tp user/password are just an add-on on top of the ipsec shared secret. So if you want to ban a user with L2TP/IPsec, by banning his individual username/password you prevent the L2TP tunnel from getting open him. He’ll just be able to establish the SA but not to get anywhere using it. But it is true that the policy template at server side has to be accordingly restrictive, otherwise the user knowing the IPsec shared secret can suggest his own policy and if it would fit the template, it would be accepted.

But I have a template policy, wide open to the world: 0.0.0.0/0, all protocols and all ports. The whole idea behind a template is to create policies on the fly, isn’t it?

Yes, but you cannot have a template at both peers of the session. One peer must choose a particular policy and inform the other one about it, and the other one creates a mirror policy and uses it if it fits to the template. The ****

/ip ipsec peer

branch of the configuration is only there to establish relatioship for further negotiation, but the policies must be set separately. The policy can be forced to the client from the server using

mode-config

, but

mode-config

doesn’t allow you to directly define a policy; instead, you define IP address ranges (the default is

0.0.0.0/0

) and you get one policy per each range with all protocols and all ports permitted. So not really a good base for L2TP, or, better to say, you don’t need L2TP once you provide IP address to the client and a (set of) policies to let the client access the subnets you want to permit him via the IPsec session.

Do you have an explanation of the part that confused me, i.e. why dynamic peer created by L2TP client has “generate-policy=port-strict policy-template-group=default”?


port-strict

is necessary so that the policy would match ports at all. As you don’t want to permit any other traffic than L2TP, which is UDP port 1701 at server side and (normally) also at client side, you have to set this, otherwise the policy would match on IP addresses and protocol type (UDP) only, so any UDP traffic would pass through. Why these parameters are there also at client side is not clear to me, maybe they are mandatory parameters for the configuration manager but not for the purpose, or the code for the client and server side is the same and no one took care about suppressing these parameters to be set also at client side where they are actually useless.