Share |

Linux as an L2tp/IPSec client for Microsoft Windows/ISA server VPN

Introduction

This document describes how to setup a roadwarrior VPN connection from Linux to an MS Isa L2tp/Ipsec server with an X.509 certificate and RSA key.
The distribution I used was Gentoo.

Requirements

-Pvkimprt.exe from Office 2000
-Openssl
-Openswan (in this case 2.4.15) patched with ALLOW_MICROSOFT_BAD_PROPOSAL patch for the ipsec phase
-Xl2tpd: an l2tp daemon for Linux
-Ppp: the standard Linux ppp daemon

Getting the certificate and have it signed

You need to get a certificate from your Microsoft Certificate server

With Internet Explorer in Windows:

Go to http://yourcertificateserver/certsrv
Click on "Request a certificate" => "Create and submit a request to this CA"
Enter your personal data

-Mark private key as exportable and provide a filename (e.g. c:\temp\myuser.pvk) on your local disk. This is very important you do this now, otherwise there is no more way to save your private key.

-Submit the request (password not needed, you will add one later with pvkimprt)

-Have the certiciate signed by your ISA server administrator

-Return to the page http://yourcertificateserver/certsrv

-Download your pending certificate (not the chain). Save it as e.g. myuser.cer

Converting the certificate to a PKCS#12/PFX format

Install the tool Pvkimprt.exe

Go to a commandline and type:
pvkimprt -pfx c:\temp\myuser.cer c:\temp\myuser.pvk (in this order with full path)
Follow the wizard:
-answer "Yes, export the private key"l
-Select "Include all certificates in the certification path if possible",  deselect "Enable strong protection" and do not select "Delete the private key"
-Enter the password you will be using on your private key. You can later include it in your config files or have it prompted for.
-Save the file as myuser.pfx and transfer it to your Linux machine.
This is the last time you will have to use Windows.

Extract and install the certificate

This phase is Linux. Make sure you have openssl installed

# (Tip: use copy and paste for these commands)
#
# Extract the user certificate contained within the PKCS#12 file:

openssl pkcs12 -in myuser.pfx -nokeys -clcerts -out myuser-crt.pem

# Extract the CA certificate(s) contained within the PKCS#12 file:
openssl pkcs12 -in myuser.pfx -nokeys -cacerts -out mycompany-cacrt.pem

# Extract the private key contained within the PKCS#12 file.
openssl pkcs12 -in myuser.pfx -nocerts -out myuser-key.pem

Copy these files to the appropriate location:

/etc/ipsec.d/private/myuser-key.pem
/etc/ipsec.d/certs/myuser-crt.pem
/etc/ipsec.d/cacerts/company-cacrt.pem # This will later turn out as being optional

 

IPSec phase

Let's analyse the config files

ipsec.conf

# /etc/ipsec/ipsec.conf - Openswan IPsec configuration file
# RCSID $Id: ipsec.conf.in,v 1.15.2.6 2006-10-19 03:49:46 paul Exp $

# This file:  /usr/share/doc/openswan-2.4.14/ipsec.conf-sample
#
# Manual:     ipsec.conf.5


version	2.0	# conforms to second version of ipsec.conf specification

# basic configuration
config setup
	#plutodebug = "all"
	# plutodebug / klipsdebug = "all", "none" or a combation from below:
	# "raw crypt parsing emitting control klips pfkey natt x509 private"
	# eg: plutodebug="control parsing"
	#
	# ONLY enable plutodebug=all or klipsdebug=all if you are a developer !!
	#
	# NAT-TRAVERSAL support, see README.NAT-Traversal
	nat_traversal=yes
	virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
	#
	# enable this if you see "failed to find any available worker"
	nhelpers=0

# Add connections here

# sample VPN connections, see /etc/ipsec.d/examples/

#Disable Opportunistic Encryption
include /etc/ipsec/ipsec.d/examples/no_oe.conf
include /etc/ipsec/ipsec.d/private/l2tp-cert-mycompany.conf


ipsec.conf is the general ipsec config file which includes a reference to our most important config file, l2tp-cert-mycompany.conf
Important lines in this config are

nat_traversal=yes

This enables IPSec over a NAT-T type internet connection. Not all routers support IPSec nat traversal (f.i. certain Zyxel models), but most modern ones do or have firmware updates available that make it support it. Linux as a nat-router supports it out-of-the-box.

virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12

This tells IPsec what are private IP ranges. If your home network (or the one you are connecting from) is not in one of these offical ranges, add your range here.

BEWARE!
Make sure your home network is not in any way in the same ip-range as the remote network you are connecting to, otherwise you might get strange behavior. So in our case, don't run your network in the 10.0.0.0/8 range. However 192.168.0.0/16 is a good idea.

include /etc/ipsec/ipsec.d/private/l2tp-cert-mycompany.conf

This is the pointer to your  Ipsec config file. Let's take a look at that file

l2tp-cert-mycompany.conf

conn l2tp-X.509-mycompany
        #
        # Configuration for one user with any type of IPsec/L2TP client
        # including the updated Windows 2000/XP (MS KB Q818043), but
        # excluding the non-updated Windows 2000/XP.
        #
        #
        # Use a certificate. Disable Perfect Forward Secrecy.
        #
        authby=rsasig
        pfs=no
        # we cannot rekey for %any, let client rekey
        rekey=yes
        keyingtries=3
        # Do not enable the line below. It is implicitely used, and
        # specifying it will currently break when using nat-t.
        # type=transport. See http://bugs.xelerance.com/view.php?id=466
        #
        type=transport
        left=%defaultroute
        leftnexthop=%defaultroute
        leftcert=/etc/ipsec.d/certs/tke.pem
        leftrsasigkey=%cert
        # For updated Windows 2000/XP clients,
        # to support old clients as well, use leftprotoport=17/%any
        leftprotoport=17/1701
        #
        # The remote user.
        #
        right=companyvpn.mydomain.be
        rightid="C=BE, L=Mytown, O=Mycompany, OU=IT, CN=companyvpn
.mydomain.be, E=
"
        rightca="DC=BE, DC=MYDOMAIN, CN=MYCOMPANYROOTVPN"
        rightprotoport=17/1701
        auto=add



First of all, indentation is important in this file. We describe the connection with

conn l2tp-X.509-mycompany

...and next we indent. This connection "l2tp-X.509-mycompany" is the name you will use when you bring up the ipsec connection.

authby=rsasig

We authenticate by RSA signature/certificate. The other option is "psk" or Pre-Shared Key which we don't handle in this doc.

rekey=yes
keyingtries=3

Rekeying occurs after a while and if we do not rekey, our connection will get dropped after some time. We don't set any rekeying times, Openswan IPsec will normally do that in time (I believe the default is 3600 seconds). Keyingtries=3 is sufficient, if more is needed, the connection is probably bad anyway.

type=transport

Important. The other mode is "tunnel", but we do not use IPsec to set up a virtual lan, we use l2tp/ppp for that. The comment above that says it will break when using nat-t appears not to be applicable anymore

left=%defaultroute
leftnexthop=%defaultroute

Everything left is "us", right is "them"
you may replace "left=%defaultroute" by your ip-address, but since we are in a roadwarrior configuration, we need to be dynamic, so we put the magic string %defaultroute. Ipsec will put your IP from the interface that has the default route.
"leftnexthop" is your default gateway. Also put %defaultroute here.
If these values are not specified, your routing will be wrong and you will have a route pointing directly to the remote host, which is not the case of course.

leftcert=/etc/ipsec.d/certs/myuser.pem
leftrsasigkey=%cert

"leftcert=" Your private certificate, signed by the root CA.
"leftrsasigkey=%cert" defines that the RSA signature key information can be found in your certificate. You need to specifiy this rsa key in ipsec.secrets. Let's talk about that file quickly, it contains only 1 line

: RSA /etc/ipsec.d/private/myuser-key.pem "mypassword"

-Before the ":" you can put an index, which can be an IP address or a FQDN. In our case we only use 1 VPN connection; so specifying nothing before the ":" acts as a wildcard
-"RSA" means we're going to specifiy a secret about an RSA key
-Next is the path to the RSA key
-The last field is the password. If you like more security, you can replace "mypassword" by the magic value "%prompt" (not quoted), which will - well yes, you guessed it - PROMPT you for your RSA key password at the moment you try to esatblish your connection.

BEWARE!

Be sure all of your config files reside in the right place! I've been struggling for months, giving up each time because this file was in the wrong location. The manpage specified that the file resided in /etc/ while in Gentoo it actually resides in /etc/ipsec/
Each time I got the error message "#1: unable to locate my private key for RSA Signature" until I just moved the file to the right location. It's nowhere in any other config file pointed out where this file resides and so it's hardcoded in the Openswan binaries.

 

 leftprotoport=17/1701

This signifies you will use protocol 17, which is UDP on port 1701 for your l2tp connection after the IPSec phase is established

Next up is the remote peer section or "them"

right=companyvpn.mydomain.be

"right" is the IP address or FQDN to which we will connect.

rightid="C=BE, L=Brussels, O=Mycompany, OU=IT, CN=companyvpn.mydomain.be, E=
"

"rightid" in our case is the string we will use. Other documentation describes that you can put your root CA here, but then we receive the error: "we require peer to have ID 'DC=BE, DC=MYDOMAIN, CN=MYCOMPANYROOTVPN', but peer declares 'C=BE, L=Mytown, O=Mydomain, OU=IT, CN=mycompanyvpn.mydomain.be, E= '" Rightid is in fact the string of the server you are connecting to, not the root CA.
So we put what he requires.

rightca="DC=BE, DC=MYDOMAIN, CN=MYCOMPANYROOTVPN"

This parameter is something I've been struggling with for a while since it's not documented anywhere. By default, the value is "rightca=%same" but this never worked and IPSec got stuck in the Quick Mode phase ("initiating Quick Mode RSASIG+ENCRYPT+TUNNEL+UP {using isakmp#1}"), without any clue to what could be wrong. In the end, I did the logical assumption to put the rightca string like I did for rightid. This worked and the IPSec phase went to the next level.

rightprotoport=17/1701
auto=add

The protocol and port are the same as us: UDP:1701
auto=add means you add this connection to your list of connections.

Patching Openswan

Now, in order for Openswan to communicate with a Microsoft ISA server and you being natted, we need to apply a patch since Microsoft has a long time going bug that falsely proposes the wrong subnet. It sees the outside IP-address instead of the internal private. The error in the logfiles appears like this: "our client subnet returned doesn't match my proposal - us:192.168.5.49/32 vs them:94.225.227.180/32"
We need to "downgrade" paranoia levels for Openswan by applying this patch to the sources and then recompile:

--- programs/pluto/Makefile.org	2007-11-06 19:56:26.000000000 +0100
+++ programs/pluto/Makefile	2008-02-23 20:10:13.000000000 +0100
@@ -244,6 +244,7 @@
 	-DGCC_LINT \
 	-DUSE_AES -DUSE_3DES \
 	-DIKE_ALG -DKERNEL_ALG -DDB_CONTEXT \
+	-DALLOW_MICROSOFT_BAD_PROPOSAL \
 	${AGGRESSIVE_DEFS} \
 	${XAUTH_DEFS} ${XAUTHPAM_DEFS} \
 	${NAT_DEFS} ${CURL_DEFS}\

I did the patch on my Gentoo installation, other will need to do it on Ubuntu or Fedora. Patching is out of the scope of this document. For Gentoo, follow this piece of documentation

After that, your ipsec/pluto will allow the proposal and will just ignore it. Your logs will turn up this: "Allowing questionable proposal anyway [ALLOW_MICROSOFT_BAD_PROPOSAL]"

Bringing up IPSec

Once all of this is done, you can start ipsec and bring up the connection:

/etc/init.d/ipsec start # Start the necessary daemons like pluto
ipsec auto --up l2tp-X.509-mycompany # Bring up the IPSec connection

If you see something like the following message in your logs, it means you've successfully set up the IPSec phase:
"STATE_QUICK_I2: sent QI2, IPsec SA established " <line continued>

L2TP phase

For this, you need an l2tpd daemon and ppp. We will be using xl2tpd and the standard linux ppp daemon.

Let 's start with the config files once again

xl2tpd.conf

Resides in /etc/xl2tpd/

[global]
port = 1701
access control = no
debug avp = yes
debug network = yes
debug state = yes
debug tunnel = yes
rand source = dev
;
[lac companyvpn]
lns = 123.1.2.34
require chap = yes
refuse pap = yes
require authentication = yes
redial = yes
redial timeout = 15
max redials = 5
length bit = yes
name = mydomain\myuser
ppp debug = yes
pppoptfile = /etc/ppp/options.l2tpd.client

[global]
port = 1701

In the global config of xl2tpd, we set it up to listen to port 1701

access control = no
debug avp = yes
debug network = yes
debug state = yes
debug tunnel = yes
...
ppp debug = yes

We don't use access control and in this example we enable all debugging. I copied these parameters from Jacco's IPSec site. You can probably disable debugging once everything works; otherwise it creates large log files.

[lac mycompanyvpn]

The name used for the xl2tpd connection

lns = 134.7.45.8

The IP address (or hostname) we connect to. Remember we are still in a phase where we only encrypt traffic to our remote peer, there 's no tunnel yet.

require chap = yes
refuse pap = yes
require authentication = yes

These 3 parameters are important, because we don't want to be proposing any other authentication protocol than MS Chap (Challenge-handshake authentication protocol). Otherwise, authentication will fail.

name = mydomain\myuser

This parameter is EXTREMELY important! I've been chewing on this for days and is again not decently documented apart from a few small comments.
It appeared as if this parameter was any name you would like to put in here, but apparently you need to put your "domain\username" and this is passed to the MS ISA server as your connection name. The ISA server appears to be touchy on this being right. No double backslashes for escaping needed here, otherwise it won't work.

pppoptfile = /etc/ppp/options.l2tpd.client

Xl2tpd invokes the pppd daemon. In here you tell it where it can find the config file for pppd. We 'll be looking into that file next.

All other parameters require no real explanation as they were default.

options.l2tpd.client

Apparently, this file accepts no comments, so make it clean. It resides in /etc/ppp/

ipcp-accept-local
ipcp-accept-remote
require-mschap-v2
mppe required
noauth
usepeerdns
refuse-pap
refuse-eap
noccp
crtscts
idle 1800
mtu 1410
mru 1410
nodefaultroute
debug
lock
connect-delay 5000

In fact, most of this file has been copied from Jacco's instructions and requires no special tweaking.
I did however, in the process of troubleshooting, add a few lines which don't seem to be doing any harm

require-mschap-v2

We do require MS Chap, although we already specified so in our xl2tpd.conf

mppe required

Microsoft Point-to-Point Encryption: probably already a default, maybe not needed

refuse-pap
refuse-eap

We don't want to have any other authentication protocol but chap, so we make sure we refuse any others.

noauth

In a ppp connection, authentication occurs normally in both ways. We don't need the peer to authenticate to us. Hence "noauth"

usepeerdns

We want to use the DNS from our VPN so we can find hostnames from inside.

chap-secrets

In /etc/ppp/chap-secrets

# Secrets for authentication using CHAP
# client	server	secret			IP addresses
mydomain\\myuser	*	mypassword	*
*	mydomain\\myuser	mypassword	*


This is where your domain«username + password goes.
Do it like this. The lines with your username/password have to appear twice, with username and server (wildcard *) inverted on the second line. Make sure it is well tab separated and readable only by root. Here you need double backslashes for escaping the domain\username separation.
If your password contains any special, non ASCII characters, put the password between quotes

Bringing up the l2tp tunnel

Here 's the final phase:

/etc/init.d/xl2tpd start
echo "c mycompanyvpn" > /var/run/xl2tpd/l2tp-control
route add -net 10.0.0.0/8 dev ppp0 # "route add -net 0.0.0.0 dev ppp0"  will also work but route ALL traffic through your vpn

If all went well, something like this will appear in your logs:

"Sep  8 10:05:58 wiske pppd[13840]: local  IP address 10.17.11.145
Sep  8 10:05:58 wiske pppd[13840]: remote IP address 10.17.11.0
Sep  8 10:05:58 wiske pppd[13840]: primary   DNS address 10.63.25.34
Sep  8 10:05:58 wiske pppd[13840]: secondary DNS address 10.63.25.34"

That 's it you 've set up a VPN

In short

Once all config is done, these are the steps to follow. You can put it in a script:

/etc/init.d/ipsec start
/etc/init.d/xl2tpd start
ipsec auto --up l2tp-X.509-mycompany
echo "c mycompanyvpn" > /var/run/xl2tpd/l2tp-control
route add -net 10.0.0.0/8 dev ppp0

To bring the VPN down

echo "d mycompanyvpn" > /var/run/xl2tpd/l2tp-control
ipsec auto --down l2tp-X.509-mycompany

And you can stop the daemons, which I think is even better because I suspect IPSec to fiddle with my normal lan conection from time to time. But do bring down the xl2tpd connection first with the echo command, otherwise your VPN DNS entries will stay in your /etc/resolv.conf

Many references for this documentation can be found here: http://www.jacco2.dds.nl/networking/linux-l2tp.html

Updated: December 29, 2010