This article is about the layer 2 tunneling protocol (L2TP) with IPsec to provide end-to-end encryption in the layer 2 VPN because security features are not available in L2TP. The open source implementations of IPsec are StrongSwan and OpenSwan, both are supported on all Linux distributions. In this tutorial, OpenSwan is used to provide the security channel for L2TP VPN. Freeradius is a well-known open source tool which provides different types of authentication for users. Freeradius is used to authenticate the L2TP VPN user before establishing a secure channel. An android based client will be used for the L2TP based secure tunnel.
Installation of required packages
Following important packages will be installed on the Ubuntu 16.04 LTS.
- Freeradius Server/Client
- Poptop Server
- xl2tpd
- Openswan for IPsec
- MySQL Server/client
- Bison & Flex
- GMP development library
As shown below, most of the required packages are all available in the Ubuntu 16.04 LTS repository.
apt-get update
apt-get install -y mysql-server mysql-client freeradius-mysql pptpd xl2tpd
The following screenshot shows how the password for the user "root" of the MySQL database server is being set during the installation process.
The following packages are required for the OpenSwan installation from source on the Ubuntu 16.04 platform.
apt-get install -y build-essential libgmp3-dev bison flex
The Freeradius client and OpenSwan packages are not available in the repository, so both tools have been installed from source.
Installation of the Freeradius client
Download the latest Freeradius client from the following link:
wget https://github.com/FreeRADIUS/freeradius-client/archive/master.zip
unzip master.zip
mv freeradius-client-master freeradius-client
cd freeradius-client
First, run the configure script with the prefix switch and install the software using the make command.
./configure --prefix=/
make && make install
Installation of OpenSwan
The source code of the OpenSwan IPsec tool is available on the following link. Download the archive and unpack it.
wget https://download.openswan.org/openswan/openswan-latest.tar.gz
tar -xzf openswan-latest.tar.gz
cd openswan-*
Run the following command to compile and install OpenSwan.
make programs
make install
Configuration
Before we start with the configuration of the installed packages, the following base configurations (iptables and sysctl) are required on the Ubuntu platform.
Enter following iptables rules for both networks (10.20.30.0/24 & 10.10.10.0/24) on the terminal.
iptables -t nat -I POSTROUTING -s 10.20.30.0/24 -j SNAT --to 192.168.15.4
iptables -t nat -I POSTROUTING -s 10.10.10.0/24 -j SNAT --to 192.168.15.4
Above rules should be saved into the /etc/iptables.rc file to apply them at boot time.
chmod +x /etc/iptables.rc
sed -i "/iptables.rc/d" /etc/rc.local
sed -i "1a/etc/iptables.rc" /etc/rc.local
Add the following lines in the /etc/sysctl.conf file to enable forwarding on the Linux machine.
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.icmp_ignore_bogus_error_responses = 1
Run the following command to apply changes.
sysctl -p
Configuration of the Freeradius Server
Run the following command to change the password for freeradius.
sed -i "s/PASSWORD('radpass')/PASSWORD('test')/g" /etc/freeradius/sql/mysql/admin.sql
The following MySQL commands will configure the Freeradius server on Ubuntu.
mysql --protocol=tcp -h localhost -u root -ptest
create database radius # create DB radius
mysql --protocol=tcp -h localhost -u root -ptest radius < /etc/freeradius/sql/mysql/admin.sql
mysql --protocol=tcp -h localhost -u root -ptest radius < /etc/freeradius/sql/mysql/cui.sql
Adding a proper date to fix the invalid default value issue in /etc/freeradius/sql/mysql/cui.sql.
After correction in the /etc/freeradius/sql/mysql/cui.sql file and rerun above command to fix the above error.
mysql --protocol=tcp -h localhost -u root -ptest radius < /etc/freeradius/sql/mysql/ippool.sql
mysql --protocol=tcp -h localhost -u root -ptest radius < /etc/freeradius/sql/mysql/nas.sql
mysql --protocol=tcp -h localhost -u root -ptest radius < /etc/freeradius/sql/mysql/schema.sql
mysql --protocol=tcp -h localhost -u root -ptest radius < /etc/freeradius/sql/mysql/wimax.sql
Run the folowing sed command to change the default password of user "radius". In this tutorial, the password for the user "radius" is "test". Chose a secure password on your server.
sed -i "s/password = \"radpass\"/password = \"test\"/g" /etc/freeradius/sql.conf
Creating a soft link for the sql configuration in the modules directory of the Freeradius server.
ln -sf /etc/freeradius/sql.conf /etc/freeradius/modules/sql
Following files are not present on Ubuntu 16.04, therefore, create all required files with the described content.
- /etc/freeradius/modules/hourlylytraffic
- /etc/freeradius/modules/dailytraffic
- /etc/freeradius/modules/monthlytraffic
/etc/freeradius/modules/hourlytraffic
sqlcounter hourlytrafficcounter {
counter-name = Hourly-Traffic
check-name = Hourly-Traffic
sqlmod-inst = sql
key = User-Name
reset = 1h
query = "SELECT SUM(acctinputoctets + acctoutputoctets) DIV 1048576 FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) > '%b'"
}
/etc/freeradius/modules/dailytraffic
sqlcounter dailytrafficcounter {
counter-name = Daily-Traffic
check-name = Daily-Traffic
sqlmod-inst = sql
key = User-Name
reset = daily
query = "SELECT SUM(acctinputoctets + acctoutputoctets) DIV 1048576 FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) > '%b'"
}
/etc/freeradius/modules/monthlytraffic
sqlcounter monthlytrafficcounter {
counter-name = Monthly-Traffic
check-name = Monthly-Traffic
sqlmod-inst = sql
key = User-Name
reset = monthly
query = "SELECT SUM(acctinputoctets + acctoutputoctets) DIV 1048576 FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) > '%b'"
}
The following file is important for freeradius server configuration. Our running configurations are given below.
/etc/freeradius/sites-enabled/default
authorize {
preprocess
chap
mschap
digest
suffix
eap {
ok = return
}
files
sql
expiration
logintime
pap
hourlytrafficcounter
dailytrafficcounter
monthlytrafficcounter
}
authenticate {
Auth-Type PAP {
pap
}
Auth-Type CHAP {
chap
}
Auth-Type MS-CHAP {
mschap
}
digest
unix
eap
}
preacct {
preprocess
acct_unique
suffix
files
}
accounting {
detail
unix
radutmp
sql
exec
attr_filter.accounting_response
}
session {
radutmp
sql
}
post-auth {
sql
exec
Post-Auth-Type REJECT {
attr_filter.access_reject
}
}
pre-proxy {
}
post-proxy {
eap
}
Use the following command to restart the freeradius server and to verify the configuration.
/etc/init.d/freeradius restart
Configuration of the Freeradius client
Following command sets the hostname and secret in the "servers" file of the freeradius client.
echo -e "localhost\ttesting123" >> /etc/radiusclient/servers
Create the dictionary.microsoft configuration file for Windows based clients.
vi /etc/radiusclient/dictionary.microsoft
#
# Microsoft's VSA's, from RFC 2548
#
# \$Id: poptop_ads_howto_8.htm,v 1.8 2008/10/02 08:11:48 wskwok Exp \$
#
VENDOR Microsoft 311 Microsoft
BEGIN VENDOR Microsoft
ATTRIBUTE MS-CHAP-Response 1 string Microsoft
ATTRIBUTE MS-CHAP-Error 2 string Microsoft
ATTRIBUTE MS-CHAP-CPW-1 3 string Microsoft
ATTRIBUTE MS-CHAP-CPW-2 4 string Microsoft
ATTRIBUTE MS-CHAP-LM-Enc-PW 5 string Microsoft
ATTRIBUTE MS-CHAP-NT-Enc-PW 6 string Microsoft
ATTRIBUTE MS-MPPE-Encryption-Policy 7 string Microsoft
# This is referred to as both singular and plural in the RFC.
# Plural seems to make more sense.
ATTRIBUTE MS-MPPE-Encryption-Type 8 string Microsoft
ATTRIBUTE MS-MPPE-Encryption-Types 8 string Microsoft
ATTRIBUTE MS-RAS-Vendor 9 integer Microsoft
ATTRIBUTE MS-CHAP-Domain 10 string Microsoft
ATTRIBUTE MS-CHAP-Challenge 11 string Microsoft
ATTRIBUTE MS-CHAP-MPPE-Keys 12 string Microsoft encrypt=1
ATTRIBUTE MS-BAP-Usage 13 integer Microsoft
ATTRIBUTE MS-Link-Utilization-Threshold 14 integer Microsoft
ATTRIBUTE MS-Link-Drop-Time-Limit 15 integer Microsoft
ATTRIBUTE MS-MPPE-Send-Key 16 string Microsoft
ATTRIBUTE MS-MPPE-Recv-Key 17 string Microsoft
ATTRIBUTE MS-RAS-Version 18 string Microsoft
ATTRIBUTE MS-Old-ARAP-Password 19 string Microsoft
ATTRIBUTE MS-New-ARAP-Password 20 string Microsoft
ATTRIBUTE MS-ARAP-PW-Change-Reason 21 integer Microsoft
ATTRIBUTE MS-Filter 22 string Microsoft
ATTRIBUTE MS-Acct-Auth-Type 23 integer Microsoft
ATTRIBUTE MS-Acct-EAP-Type 24 integer Microsoft
ATTRIBUTE MS-CHAP2-Response 25 string Microsoft
ATTRIBUTE MS-CHAP2-Success 26 string Microsoft
ATTRIBUTE MS-CHAP2-CPW 27 string Microsoft
ATTRIBUTE MS-Primary-DNS-Server 28 ipaddr
ATTRIBUTE MS-Secondary-DNS-Server 29 ipaddr
ATTRIBUTE MS-Primary-NBNS-Server 30 ipaddr Microsoft
ATTRIBUTE MS-Secondary-NBNS-Server 31 ipaddr Microsoft
#ATTRIBUTE MS-ARAP-Challenge 33 string Microsoft
#
# Integer Translations
#
# MS-BAP-Usage Values
VALUE MS-BAP-Usage Not-Allowed 0
VALUE MS-BAP-Usage Allowed 1
VALUE MS-BAP-Usage Required 2
# MS-ARAP-Password-Change-Reason Values
VALUE MS-ARAP-PW-Change-Reason Just-Change-Password 1
VALUE MS-ARAP-PW-Change-Reason Expired-Password 2
VALUE MS-ARAP-PW-Change-Reason Admin-Requires-Password-Change 3
VALUE MS-ARAP-PW-Change-Reason Password-Too-Short 4
# MS-Acct-Auth-Type Values
VALUE MS-Acct-Auth-Type PAP 1
VALUE MS-Acct-Auth-Type CHAP 2
VALUE MS-Acct-Auth-Type MS-CHAP-1 3
VALUE MS-Acct-Auth-Type MS-CHAP-2 4
VALUE MS-Acct-Auth-Type EAP 5
# MS-Acct-EAP-Type Values
VALUE MS-Acct-EAP-Type MD5 4
VALUE MS-Acct-EAP-Type OTP 5
VALUE MS-Acct-EAP-Type Generic-Token-Card 6
VALUE MS-Acct-EAP-Type TLS 13
END-VENDOR Microsoft
vi /etc/radiusclient/dictionary.merit
#
# Experimental extensions, configuration only (for check-items)
# Names/numbers as per the MERIT extensions (if possible).
#
ATTRIBUTE NAS-Identifier 32 string
ATTRIBUTE Proxy-State 33 string
ATTRIBUTE Login-LAT-Service 34 string
ATTRIBUTE Login-LAT-Node 35 string
ATTRIBUTE Login-LAT-Group 36 string
ATTRIBUTE Framed-AppleTalk-Link 37 integer
ATTRIBUTE Framed-AppleTalk-Network 38 integer
ATTRIBUTE Framed-AppleTalk-Zone 39 string
ATTRIBUTE Acct-Input-Packets 47 integer
ATTRIBUTE Acct-Output-Packets 48 integer
# 8 is a MERIT extension.
VALUE Service-Type Authenticate-Only 8
Add the following lines to the /etc/radiusclient/dictionary file.
INCLUDE /etc/radiusclient/dictionary.merit
INCLUDE /etc/radiusclient/dictionary.microsoft
ATTRIBUTE Hourly-Traffic 1000 integer
ATTRIBUTE Daily-Traffic 1001 integer
ATTRIBUTE Monthly-Traffic 1002 integer
The following is the run configuration of the radius client.
/etc/radiusclient/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,local
# maximum login tries a user has
login_tries 4
# timeout for all login tries
# if this time is exceeded the user is kicked out
login_timeout 60
# name of the nologin file which when it exists disables logins. it may
# be extended by the ttyname which will result in
#a terminal specific lock (e.g. /etc/nologin.ttyS2 will disable
# logins on /dev/ttyS2)
nologin /etc/nologin
# name of the issue file. it's only display when no username is passed
# on the radlogin command line
issue /etc/radiusclient/issue
seqfile /var/run/freeradius/freeradius.pid
## RADIUS listens separated by a colon from the hostname. if
# no port is specified /etc/services is consulted of the radius
authserver localhost
# RADIUS server to use for accouting requests. All that I
# said for authserver applies, too.
acctserver localhost
# file holding shared secrets used for the communication
# between the RADIUS client and server
servers /etc/radiusclient/servers
# dictionary of allowed attributes and values just like in the normal
# RADIUS distributions
dictionary /etc/radiusclient/dictionary
# program to call for a RADIUS authenticated login
login_radius /sbin/login.radius
# file which specifies mapping between ttyname and NAS-Port attribute
mapfile /etc/radiusclient/port-id-map
# default authentication realm to append to all usernames if no
# realm was explicitly specified by the user
default_realm
# time to wait for a reply from the RADIUS server
radius_timeout 10
# resend request this many times before trying the next server
radius_retries 3
# local address from which radius packets have to be sent
bindaddr *
# program to execute for local login
# it must support the -f flag for preauthenticated login
login_local /bin/login
Following configuration (which is related to IPv6) in /etc/radiusclient/dictionary file should be commented out to run the radius client.
ATTRIBUTE NAS-Filter-Rule 92 string
ATTRIBUTE Originating-Line-Info 94 string
ATTRIBUTE NAS-IPv6-Address 95 string
ATTRIBUTE Framed-Interface-Id 96 string
ATTRIBUTE Framed-IPv6-Prefix 97 ipv6prefix
ATTRIBUTE Login-IPv6-Host 98 string
ATTRIBUTE Framed-IPv6-Route 99 string
ATTRIBUTE Framed-IPv6-Pool 100 string
ATTRIBUTE Error-Cause 101 integer
ATTRIBUTE EAP-Key-Name 102 string
#
# RFC6911 IPv6 attributes
#
ATTRIBUTE Framed-IPv6-Address 168 ipv6addr
ATTRIBUTE DNS-Server-IPv6-Address 169 ipv6addr
ATTRIBUTE Route-IPv6-Information 170 ipv6prefix
Configuration of the Poptop server
Add the following configuration in the /etc/pptpd.conf file.
localip 10.20.30.1
remoteip 10.20.30.2-254
Run following sed command on the /etc/ppp/pptpd-options file.
sed -i "/^ms-dns/d" /etc/ppp/pptpd-options
sed -i -e "/radius.so/d" -e "/radattr.so/d" /etc/ppp/pptpd-options
Add the following lines in /etc/ppp/pptpd-options file.
ms-dns 8.8.8.8
ms-dns 8.8.4.4
plugin /usr/lib/pppd/2.4.7/radius.so
plugin /usr/lib/pppd/2.4.7/radattr.so
Restart the pptpd service to apply the above changes.
service pptpd restart
Configuration of xl2tp
Include following configuration lines in the /etc/xl2tpd/xl2tpd.conf file as shown in following figure.
[global]
ipsec saref = yes
[lns default]
ip range = 10.10.10.2-10.10.10.255
local ip = 10.10.10.1
refuse chap = yes
refuse pap = yes
require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes
Configuration of OpenSwan
Add the following setting of the ipsec secret file in /etc/ipsec.secrets.
192.168.15.4 %any 0.0.0.0: PSK "test"
IPsec configuration for L2TP tunnel is included in /etc/ipsec.conf file.
version 2.0
config setup
nat_traversal=yes
virtual_private=%v4:192.168.0.0/16,%v4:10.0.0.0/8,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v4:!10.254.253.0/24
protostack=netkey
#protostack=mast # used for SAref + MAST only
interfaces="%defaultroute"
oe=off
conn psk-l2tp
pfs=no
auto=add
rekey=no
# overlapip=yes # for SAref + MAST
# sareftrack=yes # for SAref + MAST
type=transport
left=192.168.15.4
leftprotoport=17/1701
right=%any
rightprotoport=17/%any
rightsubnet=vhost:%priv,%no
authby=secret
Configuration of PPP server
Add the following configuration in /etc/ppp/options.xl2tpd file.
ipcp-accept-local
ipcp-accept-remote
ms-dns 8.8.8.8
ms-dns 8.8.4.4
noccp
auth
crtscts
idle 1800
mtu 1200
mru 1200
nodefaultroute
debug
lock
proxyarp
connect-delay 5000
plugin /usr/lib/pppd/2.4.7/radius.so
plugin /usr/lib/pppd/2.4.7/radattr.so
After successful configuration of all required packages, now restart all services to test L2TP VPN.
Restarting IPsec & xl2tp services.
The following figure shows that the freeradius server is running in daemon mode which is helpful to identify that the server is working.
Insert a user account in the MySQL database to test the configuration.
INSERT INTO radius.radcheck (username, attribute, op, value) VALUES ('username','User-Password',':=','userpassword');
The following command checks that the Freeradius server is working on localhost.
radtest username userpassword localhost 0 testing123
Configuration of L2TP Android client
Go to settings ==> More ==> VPN ==>Add VPN Network on android phone and create new L2TP PSK VPN as shown below.
After creation of new L2TP VPN, click on it and enter username/password (configured on the the freeradius server).
Following figure shows that L2TP VPN is connecting.
Following screens shows that L2TP VPN is successfully connected using an android client.
L2TP VPN Status
Freeradius shows the successful authentication of L2TP android client.
Following command shows the IPsec tunnel status
ip xfrm state
OpenSwan log (/var/log/auth.log) and xl2tp log (/var/log/syslog) also shows the status of L2TP VPN.
tail -f /var/log/auth.log
tail -f /var/log/syslog
In this tutorial, layer 2 tunneling protocol is used with IPSec and Freeradius to provide security and authentication mechanisms. An android based client is used to demonstrate the working of L2TP over IPsec.