IPCop L2TP Remote Access Server

How-to Build an IPCop L2TP Remote Access Server
for Microsoft Windows Clients
By Duncan Reed
1. Introduction
 
Currently, as of version 1.4.0, IPCop does not allow you to create Roadwarrior accounts for Windows users without either going under the covers of IPCop and modifying various configuration files by hand and adding additional binaries, or by adding a package to windows clients to allow them to do pure IPSec.
 
This document shows how to set-up IPCop to allow incoming IPSec/L2TP connections from Windows clients. We have not gone down the pure IPSec on Windows approach because this involves downloading, installing and configuring this software on many many Windows clients. The Windows users have a varying level of access and its easier to use what is default on a Windows install.
 
Using IPSec/L2TP rather than PPTP because PPTP is less secure and has a number of other gotcha's.
 
Also we will be using X509 certificates for the IPSec tunnel rather than ~PreShared Keys (PSK) because only Windows XP supports PSK so to support Win2k and WinNT clients (needs free MS L2TP download for WinNT) we need to use certificates.
 
There are various issues with older patch levels of windows so we assume Windows Clients are patched to one of the following:
 
·         Windows XP Professional sp2
·         Windows 2000 Professional sp4
·         Windows NT sp6a
 
 
This document also covers doing the authentication via a Radius server rather than though the chap-secrets or pap-secrets files which are part of ppp. This document only covers configuring the radius client on the IPCop machine, the configuration of the Radius server is beyond the scope of this document.
 
The configuration of windows clients will not be covered here. A separate document exists to explain how to configure the Windows clients to use the Roadwarrior VPN.
 
 
I assume the following:
Your IPCop box is 192.168.1.2 mask 255.255.255.0
You have another gateway on 192.168.1.1 mask 255.255.255.0
 
Which gives access to:
192.168.0.0 netmask 255.255.255.0
10.0.0.0 netmask 255.255.255.0
 
Your DNS/WINS server's are:
192.168.1.5
192.168.1.6
 
 
2. Install IPCop and Configure IPCop
 
The first step is to install IPCop 1.4.0, which is not covered by this document and it is assumed you have already successfully done by following this link [http://www.ipcop.org/1.4.0/en/install/html/].
 
Generate Certificate Authority Certificate
 
This can be done from the GUI. You can find the official IPCop VPN Administration document here ([http://www.ipcop.org/1.4.0/en/admin/html/vpnaw.html]).
 
This must be done BEFORE you can generate you Roadwarrior host certificates.
 
Navigate to the VPN Certificate Authority section, you can find this by selecting the VPN subsection from the VPN section tab.
 
[http://www.ipcop.org/1.4.0/en/admin/images/vpn-ca1.png]
 
Either upload a CA certificate using the 'Upload CA Certificate' button or create your own by clicking on the Generate Root/Host Certificates' button.
 
Once done you will have a screen that looks like this [http://www.elminster.com/images/vpn-ca-done.jpg]
 
Then will be able to sign your Roadwarrior certificates, which will be covered later.
 
!Build Pseudo Terminals
Unlike many newer 2.6 kernels the kernel in IPCop still has BSD style Pseudo Terminals enabled but the the device file have not been 'made', so confusingly you would get the same error as if the kernel option for BSD style Pseudo Terminals was not enabled. To enable PTY's you must do the following.
 
 
cd /dev
vi make_devices (or editor of choice)
 
Search for 'ptyp0' and uncomment the line:
mknod -m $MODE ptyp0 c 2 0 ; chgrp $GROUP ptyp0
 
Search for 'ttyp0' and uncomment the line:
mknod -m $MODE ttyp0 c 3 0 ; chgrp $GROUP ttyp0
 
Uncomment as many ttypX's as you require dial-in users.
Save & Exit
 
./make_devices
 
 
This should create the device files /dev/ptyp0 and /dev/ttypX.
 
Add routes
If you have any other networks that you need dial-in users to access then you will have to add additional routes. These will need to be added to the /etc/rc.d/rc.local file.
 
e.g
 
route add -net 192.168.0.0 netmask 255.255.255.0 gw 192.168.1.1 eth0
route add -net 10.0.0.0 netmask 255.255.255.0 gw 192.168.1.1 eth0
 
 
If you have more complicated routing requirements you may wish to look at GRE tunnels. See the gre-howto URL in the links section.
 
Add firewall rules
Additional firewall rules will be required to allow the ppp connections to access the various interfaces, otherwise user packets can't escape out Red or Green. We will also need to (pre)route the L2TP traffic to the local interface only.
 
Therefore need to modify the /etc/rc.d/rc.firewall.local file with the following:
 
 
## add your 'start' rules here
/sbin/iptables -t nat --append CUSTOMPREROUTING -i ipsec0 \
-p udp --sport 1701 --dport 1701 \
-j DNAT --to-destination 192.168.1.2
 
/sbin/iptables -A CUSTOMINPUT -i ppp+ \
-m state --state NEW -j ACCEPT -p ! icmp
 
/sbin/iptables -A CUSTOMFORWARD -i ppp+ \
-m state --state NEW -j ACCEPT
 
## add your 'stop' rules here
/sbin/iptables -t nat --delete CUSTOMPREROUTING -i ipsec0 \
-p udp --sport 1701 --dport 1701 \
-j DNAT --to-destination 192.168.1.2
 
/sbin/iptables -D CUSTOMINPUT -i ppp+ \
-m state --state NEW -j ACCEPT -p ! icmp
 
/sbin/iptables -D CUSTOMFORWARD -i ppp+ \
-m state --state NEW -j ACCEPT
 
 
 
To make IPCop use the above iptables rules you will need to run the following command:
/etc/rc./rc.firewall.local start
 
This is run automatically at boot time.
 
 
 
3. Installing L2TPD
 
I created the following IPCop binary tar ball from the Fedora RPM ([http://www.jacco2.dds.nl/networking/RPMS/]) produced by Jacco de Leeuw ([http://www.jacco2.dds.nl/contact/index.html]) on his L2TPD how-to site [http://www.jacco2.dds.nl/networking/freeswan-l2tp.html].
 
The IPCop Tar ball can be found here [http://www.elminster.com/downloads/l2tpd-0.69-9jdl_ipcop140-b1.tar.bz2]. You can install this as follows:
 
tar -jvxf l2tpd-0.69-9jdl_ipcop140-b1.tar.bz2 -C /
 
This reduced tar ball will install the following files:
 
/etc/l2tpd/l2tpd.conf
/etc/ppp/options.l2tpd
/usr/sbin/l2tpd
/etc/rc.d/rc.l2tpd
 
As explained in Chapter 4 if you connect to your ISP via PPP you will need to put the L2TPD server on another machine. You can follow the links above to find an appropriate RPM, tar ball etc. for your nominated server. Or just forward to a windows server as explained here [http://koeppe-net.de/l2tp-howto.txt].
 
There are other l2tp servers available. An overview can be found here [http://www.jacco2.dds.nl/networking/freeswan-l2tp.html#L2TPoverview]. Now we have a radius server working we may at some point switch to rp-l2tp ([http://sourceforge.net/projects/rp-l2tp/]) as Radius can handout IP addresses which rp-l2tp doesn't do. As all pre-Radius testing was done with l2tpd (because it can handout IP addresses to client machines dynamically) we decided in the short term we would stick with this.
 
 
4. Configure L2TPD/PPP
 
Configure /etc/l2tpd/l2tpd.conf
You will probably only need to reconfigure the IP parts of the config file. e.g.
 
[global]
listen-addr = 192.168.1.2
 
The 'listen-addr' parameter should be set to the green interface of IPCop.
 
[lns default]
ip range = 192.168.1.220-192.168.1.254
local ip = 192.168.1.99
 
The 'ip range' should be on the same network as IPCop and must not appear in the DHCP range of ip's. i.e. They must not be used elsewhere or you will end up with two machines with the same IP. You can elect to have the above handled by a Radius server.
 
The 'local ip' parameter is the pppd ip address that will be IPCop side of the ppp tunnel. i.e. In the above example a windows client will see its default gateway as 192.168.1.99 not 192.168.1.2.
 
Configure /etc/ppp/options.l2tpd
 
You will need to change the values for the primary and secondary DNS servers; and the same again for any wins servers. e.g.
 
ms-dns 192.168.1.5
ms-dns 192.168.1.6
ms-wins 192.168.1.5
ms-wins 192.168.1.6
 
Alter ip-up/ip-down scripts
 
These break everything on IPCop when doing PPP via L2TP. So you will need to rename these so they don't get called. E.g.
 
cd /etc/ppp
mv ip-up ip-up.orig
mv ip-down ip-down.orig
 
This Solution won't work if you use PPP as part of you dial-up solution for your red interface, if this is the case you will have to run your L2TPD daemon, and therefore you ppp daemon, on a different server on your internal network. This means altering the IP address specified in the CUSTOMPREROUTING chain above to reflect the server where L2TPD traffic should be sent.
 
Auto Start-up
To get l2tpd to start at boot time you will need to added the start-up command to /etc/rc.d/rc.local e.g.
 
/etc/rc.d/rc.l2tpd start
 
 
This is a script designed for ~RedHat but has been altered so it will work on IPCop. The parameters are the same i.e.:
 
Usage: l2tpd {start|stop|status|restart|reload|try-restart}
 
 
5. Create Users
 
You can do some of the dial-up user creation through the GUI if you like but it does not configure everything that you need to configured to get L2TPD clients working, so you have to go down to the command line anyway. Also any tunnels you have created for users previously will be broken if you then create a new one in the GUI. Once you have created your first connection do not make any changes via the GUI.
 
Therefore it is VERY important to backup your working ipsec.conf file, as if you accidentally make a change via the IPCop GUI this will get trashed.
 
Generate Client Certificates
 
Each user will have their own X509 certificate. This effectively gives a double layer of security and if that user leaves the certificate as well as their username/password can be revoked. Also Win2k Clients out of the box do not support PSK's.
 
/var/ipcop/vpn/ipsec.secrets will have just one entry which looks like:
 
: RSA /var/ipcop/certs/hostkey.pem
 
If this exists already, i.e. you did something with the GUI, you won't need to change this file.
 
Populate IPCop VPN config file
 
First add the tunnel you want to create to IPCop's gui config file */var/ipcop/vpn/config*. You can create this with the IPCop GUI but you should not edit it as it will break all the other config.
 
1,on,RoadwarriorX509,MyMachine,host,cert,,,,192.168.1.0/255.255.255.0,,,,,,,,,,,,,,,,,Remote workers using x509,RED
 
You probably want to change the field with the network and netmask the first time you add a user but subsequent ones are going to be the same, so just copy and paste. Likewise you will probably not be altering the fields populated with 'RED', 'host' or 'cert'.
 
·         The first field is a sequence number
·         The second field is the certificate name
·         The third field is the common name
·         The penultimate field is the Comment
 
The following certificate generation sections appear in the appendices as the script create_roadwarrior_cert.sh
 
Create Host Certificates
 
export USERCERT=<Yourcertificatename>
export SSL_CERT=$(grep ROOTCERT_COUNTRY /var/ipcop/vpn/settings | cut -d= -f2)
export SSL_STATE=$(grep ROOTCERT_STATE /var/ipcop/vpn/settings | cut -d= -f2 | sed "s/^ *$/\./")
export SSL_CITY=$(grep ROOTCERT_CITY /var/ipcop/vpn/settings | cut -d= -f2 | sed "s/^ *$/\./")
export SSL_ORG=$(grep ROOTCERT_ORGANIZATION /var/ipcop/vpn/settings | cut -d= -f2)
export SSL_OU=$(grep ROOTCERT_OU /var/ipcop/vpn/settings | cut -d= -f2 | sed -e "s/^'\(.*\)'$/\1/" | sed "s/^ *$/\./")
export SSL_CN=$USERCERT
export SSL_EMAIL=$(grep ROOTCERT_EMAIL /var/ipcop/vpn/settings | cut -d= -f2)
 
/usr/bin/openssl req -nodes -newkey rsa:1024 \
-keyout /var/ipcop/certs/${USERCERT}key.pem \
-out /var/ipcop/certs/${USERCERT}req.pem <<EOF
$SSL_CERT
$SSL_STATE
$SSL_CITY
$SSL_ORG
$SSL_OU
$SSL_CN
$SSL_EMAIL
.
.
EOF
 
Sign the host certificate request
/usr/bin/openssl ca -days 999999 -batch -notext \
-in /var/ipcop/certs/${USERCERT}req.pem \
-out /var/ipcop/certs/${USERCERT}cert.pem
 
 
Convert to pkcs12 format certificate for windows
 
/usr/bin/openssl pkcs12 -export \
-inkey /var/ipcop/certs/${USERCERT}key.pem \
-in /var/ipcop/certs/${USERCERT}cert.pem \
-name ${USERCERT} \
-passout pass:somepassword \
-certfile /var/ipcop/ca/cacert.pem \
-caname "$(grep ROOTCERT_ORGANIZATION \
/var/ipcop/vpn/settings | cut -d= -f2) CA" \
-out /var/ipcop/certs/${USERCERT}.p12
 
rm /var/ipcop/certs/${USERCERT}key.pem
rm /var/ipcop/certs/${USERCERT}req.pem
rm /var/ipcop/certs/0[1-9].pem
 
 
Add username/password to chap-secrets
 
Users are simply added by doing the following (unless Radius is used) in either the CHAP or PAP secrets files, although in IPCop these are both symbolic links pointing to */var/ipcop/ppp/secrets*, add the following:
 
e.g.
# Secrets for authentication using CHAP
# client server secret IP addresses
duncan * "somepassword" 192.168.1.220/25
* duncan "somepassword" 192.168.1.220/25
 
 
Users IPSec set-up
 
If using a separate certificate for each dial-in user we need to create a separate tunnel for each user. Add the following to the /var/ipcop/vpn/ipsec.conf file:
 
conn RoadWarriorX509
left=xxx.xxx.xxx.xxx
leftnexthop=%defaultroute
leftprotoport=17/1701
leftcert=/var/ipcop/certs/hostcert.pem
right=%any
rightrsasigkey=%cert
rightprotoport=17/1701
dpddelay=30
dpdtimeout=120
dpdaction=clear
authby=rsasig
pfs=no
auto=add
 
 
Where xxx.xxx.xxx.xxx is you external ip address on your IPCop's Red Interface.
 
Note that auto is set to 'add' not 'start'. If auto was set to start it would try to bring up the ipsec tunnel as soon as ipsec initialiazed, this doesn't make sense as its not a permanent tunnel. By having auto set to add it is loaded into ipsec but won't come up until a Windows client starts a connection.
 
The final step is to reload the added user from the config file into ipsec process. This is done by restarting ipsec (you could use the reload config option but this doesn't seem to work as reliably).
 
ipsecctrl S
 
 
6. Radius PPP Plugin Install and Configuration
 
 
'RADIUS, or Remote Authentication Dial-In User Service, is a widely deployed protocol that enables companies to authenticate, authorize and account for remote users who want access to a system or service from a central network server.' - Radius, by Jonathan Hassell, Published by O'Reilly.
 
Radius can use lots of methods for storing dial-in user passwords. Some examples of these are:
 
·         radius user configuration file -
means you get extra benefits Radius offers for accounting but passwords stored in similar way to ppp's chap-secrets file.
·         passwd or shadow –
Radius server needs read access, file must be local to Radius (you wouldn't mount passwd/shadow file via NFS/SMB would you !).
·         smbpasswd –
Radius server needs read access (probably better choice than shadow!), file must be local to Radius server - (you wouldn't mount smbpasswd file via NFS/SMB would you!)
·         ldap –
Store users in a LDAP server. This is probably the preferred solution as ldap can be linked in with Samba, NIS, DNS etc. But requires more work to set-up.
 
IPCop 1.4.0 is distributed with ppp version 2.4.2. This supports a plugin to allow connection to a radius server. Although supported this plugin is not distributed with IPCop and must therefore be added. ~[Note: The Radius server used here for testing was ~FreeRadius but there are many others]
 
This code has been built from a machine containing the IPCop 1.4.0 source. The radius plugin source is included in the code that is used to build IPCop but this part of the code is not made. We therefore just have to go in to the directory pppd/plugins/radius/ and make the source. If you don't have access to a system with which to build the source you can find a compiled tar ball here [http://www.elminster.com/downloads/pppradius_ipcop140-b1.tar.bz2].
 
You can install this as follows:
 
tar -jvxf pppradius_ipcop140-b1.tar.bz2 -C /
 
This will install the following files:
 
/usr/lib/pppd/2.4.2/radattr.so
/usr/lib/pppd/2.4.2/radius.so
/usr/lib/pppd/2.4.2/radrealms.so
/etc/radiusclient/dictionary
/etc/radiusclient/dictionary.ascend
/etc/radiusclient/dictionary.compat
/etc/radiusclient/dictionary.merit
/etc/radiusclient/dictionary.microsoft
/etc/radiusclient/port-id-map
/etc/radiusclient/radiusclient.conf
/etc/radiusclient/servers
 
 
Configure these config files, see appendices for example:
 
/etc/radiusclient/radiusclient.conf
/etc/radiusclient/servers
 
 
In your Configure /etc/ppp/options.l2tpd file you will need to add the following line:
 
plugin radius.so
 
 
7. Appendices
 
There follows examples of the configuration files in full from an IPCop 1.4.0 install customised to run an L2TPD server. Some of these are repeated from above and some are optional (e.g. radius config).
 
 
rc.local
 
#!</>bin/sh
 
route add -net 192.168.0.0 netmask 255.255.255.0 gw 192.168.1.1 eth0
route add -net 10.0.0.0 netmask 255.255.255.0 gw 192.168.1.1 eth0
 
/etc/rc.d/rc.l2tpd start
 
 
rc.firewall.local
 
#!</>bin/sh
# Used for private firewall rules
# See how we were called.
 
case "$1" in
start)
## add your 'start' rules here
/sbin/iptables -t nat --append CUSTOMPREROUTING -i ipsec0 \
-p udp --sport 1701 --dport 1701 \
-j DNAT --to-destination 192.168.1.2
 
/sbin/iptables -A CUSTOMINPUT -i ppp+ \
-m state --state NEW -j ACCEPT -p ! icmp
 
/sbin/iptables -A CUSTOMFORWARD -i ppp+ \
-m state --state NEW -j ACCEPT
;;
 
stop)
## add your 'stop' rules here
/sbin/iptables -t nat --delete CUSTOMPREROUTING -i ipsec0 \
-p udp --sport 1701 --dport 1701 \
-j DNAT --to-destination 192.168.1.2
 
/sbin/iptables -D CUSTOMINPUT -i ppp+ \
-m state --state NEW -j ACCEPT -p ! icmp
 
/sbin/iptables -D CUSTOMFORWARD -i ppp+ \
-m state --state NEW -j ACCEPT
;;
*)
echo "Usage: $0 {start|stop}"
esac
 
l2tpd.conf
 
[global]
listen-addr = 192.168.1.2
 
[lns default]
ip range = 192.168.1.220-192.168.1.254
local ip = 192.168.1.99
;refuse chap = yes - use this for Radius
require chap =yes
refuse pap = yes
require authentication = yes
name = LinuxVPNserver
ppp debug = yes
pppoptfile = /etc/ppp/options.l2tpd
length bit = yes
 
options.l2tpd
ipcp-accept-local
ipcp-accept-remote
ms-dns 192.168.1.5
ms-dns 192.168.1.6
ms-wins 192.168.1.5
ms-wins 192.168.1.6
noccp
auth
crtscts
idle 1800
mtu 1410
mru 1410
nodefaultroute
#debug
lock
proxyarp
connect-delay 5000
 
;plugin radius.so
 
 
Note: 'Plugin' and 'refuse chap' lines are optional and should only be used if you are going to use Radius
 
chap-secrets
 
# Secrets for authentication using CHAP
# client server secret IP addresses
 
duncan * "somepassword" 192.168.1.220/25
* duncan "somepassword" 192.168.1.220/25
 
 
Note: This will will be empty, except comments, if you are using Radius
 
ipsec.secrets
 
: RSA /var/ipcop/certs/hostkey.pem
 
ipsec.conf
 
config setup
interfaces=%defaultroute
klipsdebug=none
plutodebug=none
plutoload=%search
plutostart=%search
uniqueids=yes
nat_traversal=yes
 
conn %default
keyingtries=0
disablearrivalcheck=no
 
# OE policy groups are disabled by default
conn block
auto=ignore
 
conn clear
auto=ignore
 
conn private
auto=ignore
 
conn private-or-clear
auto=ignore
 
conn clear-or-private
auto=ignore
 
conn packetdefault
auto=ignore
 
conn RoadwarriorX509
left=xxx.xxx.xxx.xxx
leftnexthop=%defaultroute
leftprotoport=17/1701
leftcert=/var/ipcop/certs/hostcert.pem
right=%any
rightrsasigkey=%cert
rightprotoport=17/1701
dpddelay=30
dpdtimeout=120
dpdaction=clear
authby=rsasig
pfs=no
auto=add
 
 
Note: Where xxx.xxx.xxx.xxx is you external IP address on your IPCop's Red Interface
 
radiusclient.conf
 
# General settings
# specify which authentication comes first respectively which
# authentication is used. possible values are: "radius" and "local".
# if you specify "radius,local" then the RADIUS server is asked
# first then the local one. if only one keyword is specified only
# this server is asked.
auth_order radius
 
# maximum login tries a user has (default 4)
login_tries 4
 
# timeout for all login tries (default 60)
# if this time is exceeded the user is kicked out