Creating a free VPN Server with Centos 6 and Libreswan with L2TP
Why Libreswan?
While I was trying to set up a vpn server with the version of openswan provided by the Centos repos, I ran into several issues trying to connect my macintosh to it. I tried using a newer version of openswan, and lo and behold, I ran into an IP XFRM broken error, as well as several other errors that I was unable to resolve. Quick googling revealed that these errors were due to bugs within openswan itself.
Compared to my troubles with openswan, Libreswan has worked mostly from the get-go. Every error I encountered was the result of my own flawed .config files. Thusly, all errors were issues I could resolve.
Why Centos 6?
I've been using Centos as my main linux operating system due to it's similarity to RHEL. [Red Hat Enterprise Linux]. I've also used ubuntu, but find myself preferring Centos because I am more familiar with the yum package manager.
I find myself writing this tutorial to further cement the knowledge of how to setup a VPN from scratch, and also provide support for apple devices. I have not tested this from an iPhone or Android device, so I am unsure of the stability. However, this setup should work with Windows clients as well.
The latest version of Libreswan. As of this writing, Libreswan is at version 3.8. You can find it here. You can also install libreswan via YUM, which isn't as much work as installing from source. The only downside to installing this way is that the centos repo does not always remain up to date with the source. Run the following command to see if libreswan is available from any installed repositories.
On my system, libreswan comes from the epel repo.
If available, run
sudo yum install libreswan
If libreswan is not available from any of your repositories, you may have to install from source.
After downloading the source code, untar the file and cd into it. You may want to view the readme, as it will explain some of the process.
You will probably want to change the install directory. In this case, the installation directory is specified by the DESTDIR? variable located in Makefile.inc
In my case, I wanted libreswan installed in the root directory.
Now, before we can install libreswan, there are dependencies that must be resolved for the code to compile correctly. They are as follows:
yum install nss-devel nspr-devel pkg-config pam-devel \
libcap-ng-devel libselinux-devel \
curl-devel gmp-devel flex bison gcc make \
fipscheck-devel unbound-devel gmp gmp-devel
The other dependencies required are usually already installed on the system, but just in case you find yourself running into an error about a missing package, here they are:
nss, iproute2, iptables, sed, awk, bash, cut
The python programming language will also need to be installed, if it isn't already.
After the installation of the dependencies, you are now ready to install libreswan. (This version of the installation uses the Linux builtin IPSec stack, NETKEY. For the other available installations, view the readme)
make programs
sudo make install
Note: Prior to installing libreswan, I'd had openswan installed. Removing openswan does NOT remove the ipsec command. Libreswan will, by default, put ipsec in /usr/local/sbin/ipsec
If you installed openswan first, you may have to remove the ipsec found in /sbin and link your ipsec back to where ipsec is expected to be found in your path.
If all goes well, you should have a shiny new installation of libreswan ready to be configured!
Packages required for a L2TP connection
For an L2TP connection, relevant packages need to be installed in order for the connection to establish correctly.
You will need the ppp and xl2tpd packages to set everything up correctly.
sudo yum install ppp xl2tpd
Once these are installed, all that remains is proper set up of the .conf files, sysctl, the firewall, the system itself, and your router.
Preparing To Set Up Your System
In order to successfully connect to your VPN from the outside world, you'll have to set up port forwarding. By default, a router only allows certain traffic through. Without opening the appropriate ports, you will be unable to connect.
Ports 17, 01701, 4500, and 500 will need to be forwarded to the static IP address assigned to your server. You will need to open these ports on your router, and in your iptables firewall.
#Allow ipsec traffic
iptables -A INPUT -m policy --dir in --pol ipsec -j ACCEPT
iptables -A FORWARD -m policy --dir in --pol ipsec -j ACCEPT
#Do not NAT VPN traffic
iptables -t nat -A POSTROUTING -m policy --dir out --pol none -j MASQUERADE
#Forwarding rules for VPN
iptables -A FORWARD -i ppp+ -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
#Ports for Openswan / xl2tpd
iptables -A INPUT -m policy --dir in --pol ipsec -p udp --dport 1701 -j ACCEPT
iptables -A INPUT -p udp --dport 500 -j ACCEPT
iptables -A INPUT -p udp --dport 4500 -j ACCEPT
#Save your configuration
iptables save
If you have failed to open up these ports, you will not see any logging information about incoming ipsec connects appear in /var/log/secure
Setting up sysctl
There are a number of settings in sysctl.conf that will need to be changed in order for ipsec to function properly. With one exception, these can be altered by adding small script to the /etc/rc.local file.
# Correct ICMP Redirect issues with OpenSWAN
for each in /proc/sys/net/ipv4/conf/*; do
echo 0 > $each/accept_redirects
echo 0 > $each/send_redirects
echo 0 > $each/rp_filter
done
For the other, go to the /etc/sysctl.conf file and open it in your editor. Enable IP Packet forwarding. It should now look like this:
# Controls IP packet forwarding
net.ipv4.ip_forward = 1
Run sysctl -p after editing the file to reload sysctl.
Setting up Libreswan/IPSec
Before we get IPSec up and running, we're going to have to set up the configuration files. With the right setup, we should be able to get it working the first time around, without having to do any major tinkering.
Note: If you installed libreswan from source you may have to run:
sudo ipsec initnss
You will also want to ensure you've configured sysctl and your firewall correctly.
Your results should look like this:
Verifying installed system and configuration files
Version check and ipsec on-path [OK]
Libreswan 3.8 (netkey) on 2.6.32-431.17.1.el6.i686
Checking for IPsec support in kernel [OK]
NETKEY: Testing XFRM related proc values
ICMP default/send_redirects [OK]
ICMP default/accept_redirects [OK]
Pluto ipsec.conf syntax [OK]
Hardware random device [N/A]
Two or more interfaces found, checking IP forwarding [OK]
Checking that pluto is running [OK]
Pluto listening for IKE on udp 500 [OK]
Pluto listening for IKE/NAT-T on udp 4500 [OK]
Pluto ipsec.secret syntax [OK]
Checking NAT and MASQUERADEing [TEST INCOMPLETE]
Checking 'ip' command [OK]
Checking 'iptables' command [OK]
Checking 'prelink' command does not interfere with FIPS [PRESENT]
Checking for obsolete ipsec.conf options [OK]
Opportunistic Encryption [DISABLED]
Go to your /etc/ipsec.conf file. It should look something a little bit like this:
# /etc/ipsec.conf - Libreswan IPsec configuration file
# This file: /etc/ipsec.conf
# Enable when using this configuration file with openswan instead of libreswan
# which IPsec stack to use, "netkey" (the default), "klips" or "mast".
# The interfaces= line is only required for the klips/mast stack
#interfaces="%defaultroute"
#interfaces="ipsec0=eth0 ipsec1=ppp0"
# If you want to limit listening on a single IP - not required for
# Do not set debug options to debug configuration issues!
# plutodebug / klipsdebug = "all", "none" or a combation from below:
# "raw crypt parsing emitting control kernel pfkey natt x509 dpd
# Note: "crypt" is not included with "all", as it can show confidential
# information. It must be specifically specified
# plutodebug="control parsing"
# Again: only enable plutodebug or klipsdebug when asked by a developer
# Normally, pluto logs via syslog. If you want to log to a file,
# specify below or to disable logging, eg for embedded systems, use
# the file name /dev/null
# Note: SElinux policies might prevent pluto writing to a log file at
#plutostderrlog=/var/log/pluto.log
# Enable core dumps (might require system changes, like ulimit -C)
# This is required for abrtd to work properly
# Note: SElinux policies might prevent pluto writing the core at
# exclude networks used on server side by adding %v4:!a.b.c.0/24
# It seems that T-Mobile in the US and Rogers/Fido in Canada are
# using 25/8 as "private" address space on their wireless networks.
# This range has not been announced via BGP (at least upto 2010-12-21)
virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v4:100.64.0.0/10,%v6:fd00::/8,%v6:fe80::/10
# For example connections, see your distribution's documentation directory,
# or the documentation which could be located at
# /usr/share/docs/libreswan-3.*/ or look at https://www.libreswan.org/
# There is also a lot of information in the manual page, "man ipsec.conf"
# You may put your configuration (.conf) file in the "/etc/ipsec.d/" directory
# by uncommenting this line
#include /etc/ipsec.d/*.conf
You may set up your connections in /etc/ipsec.conf or /etc/ipsec.d/ipsec.conf
You do not have to put a separate conf file in /etc/ipsec.d for your connections.
An L2TP connection that uses a pre-shared key for authentication should look somewhat like this:
rightsubnet=vhost:%priv,%no
#Dead peer detection to detect vanishing clients
#Place the internal IP address of your server here
#You can place your external ip address here
leftnexthop=%defaultroute
This is connection will allow any client that has a preshared key, and a username and password to connect to the vpn regardless of the connecting ip address. If you wish to restrict which ip addresses can connect, you may specify them with the right keyword.
%defaultroute is a valid keyword in this example conf file, but it should be replaced by either a valid hostname or IP address.
In the /etc/ipsec.secrets file, you should add an entry for your pre-shared key.
It should look a bit like this:
ServerIPHere %any: PSK "SomePasswordHere"
192.168.1.0 %any: PSK "r4co0n5"
If everything is configured properly, go ahead and turn on ipsec service.
Setting up XL2TPD and PPP
Unlike a pure IPSec configuration, where all you need are identical configuration files on the client and server, an L2TP setup requires just a little bit more legwork.
Open /etc/xl2tpd/xl2tpd.conf in your editor. It should look fairly similar to this:
; This is a minimal sample xl2tpd configuration file for use
; The idea is to provide an L2TP daemon to which remote Windows L2TP/IPsec
; clients connect. In this example, the internal (protected) network
; is 192.168.1.0/24. A special IP range within this network is reserved
; for the remote clients: 192.168.1.128/25
; (i.e. 192.168.1.128 ... 192.168.1.254)
; The listen-addr parameter can be used if you want to bind the L2TP daemon
; to a specific IP address instead of to all interfaces. For instance,
; you could bind it to the interface of the internal LAN (e.g. 192.168.1.98
; in the example below). Yet another IP address (local ip, e.g. 192.168.1.99)
; will be used by xl2tpd as its address on pppX interfaces.
; IMPORTANT: always set listen-addr to a specific address, to work around a
listen-addr = Your Server IP Address here
; requires openswan-2.5.18 or higher - Also does not yet work in combination
; with kernel mode l2tp as present in linux 2.6.23+
; Use refinfo of 22 if using an SAref kernel patch based on openswan 2.6.35 or
; when using any of the SAref kernel patches for kernels up to 2.6.35.
ip range = (IP range you want vpn clients to use)
local ip = (IP of VPN interface on server)
; leave chap unspecified for maximum compatibility with windows, iOS, etc
require authentication = yes
name = CentOSVPNserver (Or other name, as you desire)
pppoptfile = /etc/ppp/options.xl2tpd
Your config file should appear almost identical, save for the ip addresses and name of the server.
Now open /etc/ppp/options.xl2tpd
It should look something like this:It should look something like this:
# To allow authentication against a Windows domain EXAMPLE, and require the
# user to be in a group "VPN Users". Requires the samba-winbind package
# ntlm_auth-helper '/usr/bin/ntlm_auth --helper-protocol=ntlm-server-1 --require-membership-of="EXAMPLE\\VPN Users"'
# You need to join the domain on the server, for example using samba:
# http://rootmanager.com/ubuntu-ipsec-l2tp-windows-domain-auth/setting-up-openswan-xl2tpd-with-native-windows-clients-lucid.html
Now go to /etc/ppp/chap-secrets
# Secrets for authentication using CHAP
# client server secret IP addresses
username l2tpd password *
The name keyword in /etc/ppp/options.xl2tpd and the server name in /etc/ppp/chap-secrets should be the same. I ran into issues when the name and server were unspecified.
You can add as many usernames and passwords as you like in this file. To my knowledge, there is not a limit.
Now that these files are configured, you may turn on the xl2tpd daemon.
Once everything is configured, you may now start using your VPN!
On your server, on the command line enter:
ipsec auto --add "ConnectionNameHere"
This should make your connection available to your users. If something is set up incorrectly, it may spit out an error. (Some errors may be safely ignored.)
On a Macintosh running OS X (I am using 10.9.3), go to System Preferences -> Network
There should be a plus button toward the bottom of your services list. In the drop down list, choose VPN. Under VPN type, use L2TP over IPSec. Enter the public address of your router/server into the server address box, and the username you created in /etc/ppp/chap-secrets in the account name box.
Then click authentication settings. For user authentication, choose password. For machine authentication, choose shared secret.
Once you've entered all the relevant information, click connect. If you've done everything correctly, you'll connect in just a few moments.
If you can't connect to your vpn, there may be a mistake in one of your configuration files, or your firewall/router may have been set up incorrectly.
Make sure to double-check that your ports are open and forwarded to your server, and that you've entered everything correctly.
On the VPN Server:
/var/log/secure
On the Client:
/var/log/ppp.log
If you can't get past IPSec Phase 1, there is a problem on the server side.
If you are at IPSec Phase 2, yet the client keeps disconnecting immediately after you connect, you may have a problem in your /etc/ppp/options.xl2tpd and /etc/ppp/chap-secrets files.
When running ipsec verify, you may get an error about SELinux being enabled. There is a method to get IPSec to work with SELinux enabled, but I haven't the slightest idea how to go about doing that, as it is easier to work with SELinux disabled.
You can find out how to turn off SELinux here
If you still can't get your server running, try looking into your log files and googling some of the errors. https://www.libreswan.org
They have a maling list, and an irc FreeNode. Additionally, googling your error may lead you to other sites where users have encountered similar, or the same problems.
This tutorial would not been written without the various other tutorials out there on the net. I wrote this tutorial for my own personal use, after noticing that there were no Libreswan-specific tutorials out there on the net. (That I could find.) Most were either out-of-date, using a different version of openswan, using a different operating system, or otherwise flawed. (In that I kept running into issues) The tutorials I followed were a great help, even if it did take me 3 weeks to figure out just what the hell my issues were.
How To Setup an Openswan VPN Server on Centos 6
Using a Linux L2TP/IPsec VPN server with Mac OS X and iPhone
Configuring Openswan IPSec Server