OpenWrt Forum Archive

Topic: L2TP over IPsec with PSK using racoon/xl2tpd

The content of this topic has been archived between 26 Mar 2018 and 19 Apr 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

This howto will document the needed components for an L2TP/IPsec tunnel as supported by iPhone/Android clients. There are many different IPsec implementations for Linux, like Openswan and strongSwan, but I prefer ipsec-tools because of it's light footprint. Note that I use my own init script that runs setkey.conf. I also include a hotplug script to restart racoon on WAN ifup, this is needed so that setkey.conf runs with the new IP address.

Ok, let's get started. First, we install all the required packages:

# opkg install iptables-mod-ipsec kmod-crypto-authenc kmod-crypto-cbc kmod-crypto-deflate kmod-crypto-des kmod-crypto-hmac kmod-crypto-iv kmod-crypto-md5 kmod-crypto-rng kmod-crypto-wq kmod-zlib kmod-ipsec kmod-ipsec4 libopenssl xl2tpd ppp
# opkg install http://enduser.subsignal.org/~trondah/packages/ipsec-tools_0.8.0-1_ar71xx.ipk

Now, let's configure racoon.

/etc/racoon.conf:

path pre_shared_key "/etc/racoon/psk.txt";

remote anonymous {
        exchange_mode main;
    nat_traversal on;
        generate_policy on;
        proposal_check obey;
        proposal {
                encryption_algorithm 3des;
                hash_algorithm sha1;
                authentication_method pre_shared_key;
                dh_group 2;
        }
}
sainfo anonymous {
        encryption_algorithm aes;
        authentication_algorithm hmac_sha1;
        compression_algorithm deflate;
}

/etc/racoon/psk.txt (this file needs to be chmod 0600):

# * is a wildcard, means any IP address
* changeme

/etc/setkey.conf:

#!/bin/sh

# This shell script is run by the racoon init script with your WAN address as an argument

setkey -c <<EOF

flush;
spdflush;

# All tunnels to this host shall use ESP transport mode
spdadd $1[l2tp] 0.0.0.0/0 udp -P out ipsec esp/transport//require;
spdadd 0.0.0.0/0 $1[l2tp] udp -P in ipsec esp/transport//require;

EOF

Now on to xl2ptd.

/etc/xl2tpd/xl2tpd.conf:

[global]
port = 1701
access control = no
ipsec saref = yes

[lns default]
exclusive = yes
ip range = 192.168.1.81-192.168.1.89
local ip = 192.168.1.80
;hidden bit = no
length bit = yes
name = VPNServer
ppp debug = yes
require authentication = yes
unix authentication = no
require chap = yes
refuse pap = yes
pppoptfile = /etc/ppp/options.xl2tpd

/etc/ppp/options.xl2tpd

lock
auth
name "l2tp-server"
dump
# CCP seems to confuse Android clients, better turn it off
noccp
novj
novjccomp
nopcomp
noaccomp
require-mschap
require-mschap-v2
ms-dns 192.168.1.80
lcp-echo-interval 120
lcp-echo-failure 10
idle 1800
connect-delay 5000
nodefaultroute
noipdefault

proxyarp
mtu 1400
mru 1400

xl2tpd will use ppp for chap authentication.

/etc/ppp/chap-secrets:

#USERNAME PROVIDER PASSWORD IPADDRESS
someuser * somepassword *

You'll need to open up your firewall for UDP port 500, 4500, and ESP encapsulated packets to port 1701.

# IPsec/NAT-T
config 'rule'
        option 'target' 'ACCEPT'
        option '_name' 'IPsec NAT-T'
        option 'src' 'wan'
        option 'proto' 'udp'
        option 'dest_port' '4500'

# IPsec/IKE
config 'rule'
        option 'target' 'ACCEPT'
        option '_name' 'IPsec IKE'
        option 'src' 'wan'
        option 'proto' 'udp'
        option 'dest_port' '500'

# IPsec/ESP
config 'rule'
        option 'target' 'ACCEPT'
        option '_name' 'IPsec ESP'
        option 'src' 'wan'
        option 'proto' 'udp'

# L2TP/ESP
config 'rule'
        option 'target' 'ACCEPT'
        option '_name' 'L2TP ESP'   
        option 'src' 'wan'      
        option 'proto' 'udp'
        option 'dest_port' '1701'
        option 'extra' '-m policy --strict --dir in --pol ipsec --proto esp'

You'll also want to allow forwarding to/from ppp interfaces.

/etc/firewall.user:

# Allow forwarding from/to VPN interfaces
iptables -A forwarding_rule -i ppp+ -j ACCEPT
iptables -A forwarding_rule -o ppp+ -j ACCEPT

Now you can start racoon/xl2tpd:

/etc/init.d/racoon start
/etc/init.d/xl2tpd start

And you're done! Easy wasn't it smile

(Last edited by arokh on 5 Jan 2012, 17:32)

Thanks arokh!

Just a few errors installing the dependencies:

Collected errors:
 * opkg_install_cmd: Cannot install package kmod-crypto-cbc.
 * opkg_install_cmd: Cannot install package kmod-crypto-deflate.
 * opkg_install_cmd: Cannot install package kmod-crypto-iv.
 * opkg_install_cmd: Cannot install package kmod-crypto-rng.
 * opkg_install_cmd: Cannot install package kmod-crypto-wq.
 * opkg_install_cmd: Cannot install package kmod-zlib.

This results in racoon not starting with the provided config:

/etc/init.d/racoon start
setkey: can't load library 'libcrypto.so.1.0.0'
racoon: can't load library 'libcrypto.so.1.0.0'

Could you post a link to these packages too? They are being built since May only according to a patch I noticed while searching for these packages.

Thanks a lot for this tutorial!

Best regards,
Frederik

I'm running a slightly customized version of gargoyle-router with kernel 2.6.32 still. Looks like I'll have to build a new version first, as these packages rely on kernel 2.6.39.

Updated the ipsec-tools default psk patch.

Glad to hear it, the racoon/xl2tpd combo seems to work very good.

arokh,

Thanks for putting this together. I've been using this over the last few days as I work to setup something similar on my Backfire builds for my Alix platform. I want to comment on this one part:

config 'rule'
    option 'target' 'ACCEPT'
    option '_name' 'L2TP'
    option 'src' 'wan'
    option 'proto' 'udp'
    option 'dest_port' '1701'

This is bad. You don't want to do this. Specifically this is opening your L2TP process up, naked, to the Internet. That's a bad thing because it can allow unencrypted L2TP sessions to terminate on your router. You should change this so that it only accepts packets to the L2TP port that were IPsec/esp encrypted. This rule will do that:

iptables -A input_wan -p udp -m policy --strict --dir in --pol ipsec --proto esp -m udp --dport 1701 -j ACCEPT
iptables -A input_wan -m policy --strict --dir in --pol ipsec --proto esp -j REJECT

This is a much "safer" way to allow traffic into udp port 1701. Again, only traffic that is ipsec encrypted will be allowed in. The rest will be rejected.

Thanks for pointing that out, fixed in the OP smile

Just for completeness, the ipsec arguments can be also added like this:

config 'rule'
    option 'target' 'ACCEPT'
    option '_name' 'L2TP'
    option 'src' 'wan'
    option 'proto' 'udp'
    option 'dest_port' '1701'
    option 'extra' '-m policy --strict --dir in --pol ipsec --proto esp'

Thanks for the tutorial. Got it working fine except one thing.

I can connect to the VPN Router, ping the VPN Interface 192.168.6.1, but can't get inside the LAN with subnet 192.168.2.0. I can ping the remote VPN client from inside the LAN though.
So I added the following route on the client:

route add -net 192.168.2 192.168.6.1 255.255.255.0

And there it goes, everything working.

What am I missing? Here's my iptables config:

### allow ipsec traffic from your wan port to the router
iptables -A input_wan -p udp -m policy --strict --dir in --pol ipsec --proto esp -m udp --dport 1701 -j ACCEPT
iptables -A input_wan -m policy --strict --dir in --pol ipsec --proto esp -j REJECT
iptables -A input_wan -p udp --dport 500  -j ACCEPT # allow ISAKMP
iptables -A input_wan -p udp --dport 4500 -j ACCEPT # allow NAT-T

### disable nat for the remote peer subnet, in this example 192.168.6.0/24
iptables -t nat -A postrouting_rule -d 192.168.6.0/24 -j ACCEPT

### Allow any traffic between your local LAN and remote peer LAN
iptables -A forwarding_rule -o ppp0 -j ACCEPT
iptables -A forwarding_rule -i ppp0 -j ACCEPT

for the follow rules,

iptables -A input_wan -p udp -m policy --strict --dir in --pol ipsec --proto esp -m udp --dport 1701 -j ACCEPT
iptables -A input_wan -m policy --strict --dir in --pol ipsec --proto esp -j REJECT

the package iptables-mod-ipsec is required or you will get the following errors

iptables v1.4.6: Couldn't load match `policy':File not found

There is no need to use racoon if you configure strongswan. I'll post the instructions here shortly (after I come back home).

Why would you want to use strongswan over racoon? Racoon is smaller and uses KLIPS, much better choice for a router.

Well, couple of reasons behind,

1. Don't need to patch racoon (strongswan just works without any modification)
2. Strongswan supports dynamic dns (which is useful in dyndns.org type of scenarios)
3. It use netkey (Somehow I've difficulty with klips in my wndr3700 together with pppoe), however with native Linux netkey it just works.

They did the same work basically.

And I tried pure ipsec with strongswan and iPhone, it works beautifully for XAUTH and certificate based authentication as well. This eliminates the use of xl2tpd (though I am still using l2tp now since I need it for different things).

It is just another option...

By the way, what's the purpose of this?

"iptables -A input_wan -m policy --strict --dir in --pol ipsec --proto esp -j REJECT"

1. The patch is already upstream in OpenWrt now I believe. It's a relatively simple task anyways.
2. What does dynamic dns have to do with ipsec?

My main concern is binary size as I include this setup in my community image. Anyways, it's good to have options why don't you write up a similar howto for strongSwan with xauth/certificates?

The reject rule is not needed. I guess the idea was to allow IPSec encrypted packets to port 1701 and reject others, but all traffic that's not specifically allowed is dropped by default OpenWrt rules anyways.

@jow

Thanks for the UCI policy match magic updated first post smile

(Last edited by arokh on 4 Nov 2011, 12:53)

Looks like I've been a bit confused about netkey/klips. Klips is the old way of doing kernel ipsec and required patching the kernel. Recent kernels have netkey and all the major ipsec implementations use it now it seems. I always thought *swan didn't use kernel ipsec but I guess things have changed.

Are you saying your PSK patch is in OpenWRT proper now? Was there a ticket / changeset for this? Did it make it into Backfire?

Yes to all: https://dev.openwrt.org/changeset/28102

Not my patch btw, just found it off google. Also, the one that was submitted is more proper, it falls back to default PSK if an IP specific one wasn't found.

Hmmm...I'm not seeing this patch in the Backfire feed for IPSec-tools.

I thought backfire shared the same package tree? I might be mistaken there. Nothing is stopping you from pulling that package from trunk though.

For anyone excited about PSK patch is in OpenWRT proper, no, this is not in Backfire 10.03.1-rc6

I have a clean install of trunk, the ipsec appears to be patched, as the ipsec part of my connection is working
however xl2tpd is not picking up anything, as seen when i run "xl2tpd -D"
any helps?

kiddyfurby wrote:

For anyone excited about PSK patch is in OpenWRT proper, no, this is not in Backfire 10.03.1-rc6

I have a clean install of trunk, the ipsec appears to be patched, as the ipsec part of my connection is working
however xl2tpd is not picking up anything, as seen when i run "xl2tpd -D"
any helps?

I have exactly the same problem.

At the moment I remove the line:

option 'extra' '-m policy --strict --dir in --pol ipsec --proto esp'

things start working, so there must be a kind of a hickup in the command.

I have a question as well: I do have 2 lan's defined on my router, how do I attach the ipsec/xl2tpd connection to the other lan?

rgds

(Last edited by daballiemo on 21 Nov 2011, 22:24)

These two firewall rules appear to be the same.  Have I missed something?
# IPsec/IKE
# IPsec/ESP

I had a bit of trouble connecting but changing permissions helped (chmod 755 /etc/setkey.conf).  It's easy to forget that setkey.conf is a script not a conf.  It also doesn't seem to get called automagically in my set-up.  Do I have a fault?  (Edit:  it might be that I'm running in forground to test and not using /etc/init.d/racoon.  I'll check Monday.) <-- my /etc/init.d/racoon calls the wrong setkey script.

Finally, I cant seem to access anything on my servers lan from the client.  Just the server it's self.  I'm running (testing on) rc6 with the trunc packages.  I have the ppp forwarding rules but all I can access is the little blue box.

Edit:  Started again, right from flash.  It worked.

(Last edited by ok-man on 29 Nov 2011, 23:30)

from tcdump, i found that my udp port 1701 is unreachable, tcp is fine.
any idea?