How to install L2TP vpn server on CentOS 7 linux

In today tutorial, we show you how to install L2TP vpn server on CentOS 7 linux.
L2tp is synonym of Layer Two Tunneling Protocol and is an extension of PPTP tunneling protocol for creating VPN tunnels.

Here is our environment:
OS: CentOS 7 linux on VMWare
Firewall: firewalld
SElinux: enforcing
IP address: 192.168.3.128

1- Install L2TP

There is two common packages for linux to support l2tp protocol. one is StrongSwan and another is xl2tpd. here we install xl2tpd and related packages:

# yum install epel-release
# yum install xl2tpd libreswan

2- Configure Kernel parameters

to allow vpn traffic goes through our server, we should enable some kernel features. put the following content in /etc/sysctl.conf:

# vim /etc/sysctl.conf
vm.swappiness = 0
net.ipv4.neigh.default.gc_stale_time=120
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.all.arp_announce=2
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_synack_retries = 2
net.ipv4.conf.lo.arp_announce=2
net.ipv4.ip_forward = 1
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.default.accept_source_route = 0

then make it permanent:

# sysctl -p

3- Configure IPsec

In our configuration, we want to use ipsec to enable l2tp traffic encryption. so open /etc/ipsec.d/l2tp_psk.conf and put the following content in it:

Note: mind about SPACES

# vim /etc/ipsec.d/l2tp_psk.conf
conn L2TP-PSK-NAT
     rightsubnet=vhost:%priv
     also=L2TP-PSK-noNAT
conn L2TP-PSK-noNAT
     authby=secret
     pfs=no
     auto=add
     keyingtries=3
     dpddelay=30
     dpdtimeout=120
     dpdaction=clear
     rekey=no
     ikelifetime=8h
     keylife=1h
     type=transport
     left=192.168.3.128
     leftprotoport=17/1701
     right=%any
     rightprotoport=17/%any

Note: remember to change 192.168.3.128 with your own IP address.
Here we configure l2tp to ask for a pre-shared key (PSK) from clients. we define this key like below:

# vim /etc/ipsec.secrets
192.168.3.128 %any: PSK "123456789"

and do some check on ipsec service:

# ipsec setup start
# ipsec verify

Output:

Version check and ipsec on-path [OK]
Libreswan 3.25 (netkey) on 3.10.0-1062.4.3.el7.x86_64
Checking for IPsec support in kernel [OK]
NETKEY: Testing XFRM related proc values
ICMP default/send_redirects [OK]
ICMP default/accept_redirects [OK]
XFRM larval drop [OK]
Pluto ipsec.conf syntax [OK]
Two or more interfaces found, checking IP forwarding [OK]
Checking rp_filter [ENABLED]
/proc/sys/net/ipv4/conf/eno16777728/rp_filter [ENABLED]
/proc/sys/net/ipv4/conf/tun0/rp_filter [ENABLED]
rp_filter is not fully aware of IPsec and should be disabled
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 'ip' command [OK]
Checking 'iptables' command [OK]
Checking 'prelink' command does not interfere with FIPS [OK]
Checking for obsolete ipsec.conf options [OK]

Note: red lines in above output are related to Reverse Path Filtering feautre of kernel and no need to be disabled.

Now we start ipsec service:

# systemctl enable ipsec

4- Configure xl2tpd

first, rename /etc/xl2tpd/xl2tpd.conf to a backup file:

# mv /etc/xl2tpd/xl2tpd.conf /etc/xl2tpd/xl2tpd.conf.old

then open /etc/xl2tpd/xl2tpd.conf and put these lines in it:

# vim /etc/xl2tpd/xl2tpd.conf
[global]
listen-addr = 192.168.3.128
ipsec saref = yes
[lns default]
ip range = 192.168.100.128-192.168.100.254
local ip = 192.168.100.99
require chap = yes
refuse pap = yes
require authentication = yes
name = LinuxVPNserver
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes

also make a backup of /etc/ppp/options.xl2tpd:

# mv /etc/ppp/options.xl2tpd /etc/ppp/options.xl2tpd.old

then put the following lines in it:

# vim /etc/ppp/options.xl2tpd
ipcp-accept-local
ipcp-accept-remote
ms-dns  8.8.8.8
ms-dns  4.2.2.4
noccp
#noauth
crtscts
idle 1800
mtu 1410
mru 1410
nodefaultroute
debug
lock
proxyarp
connect-delay 5000

Now we define our usernames and passwords for clients:

# vim /etc/ppp/chap-secrets
USERNAME test PASSWORD test

finally start xl2tp service:

# systemctl start xl2tpd
# systemctl enable xl2tpd
# systemctl status xl2tpd

5- Configure firewall

Here we use firewalld service. we need to allow ipsec, forward internal l2tpc ip range traffic to internet interface and do NAT:

# firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p gre -j ACCEPT
# firewall-cmd --permanent --zone=public --add-masquerade
# firewall-cmd --permanent --add-rich-rule='rule protocol value="esp" accept'
# firewall-cmd --permanent --add-rich-rule='rule protocol value="ah" accept'
# firewall-cmd --permanent --add-port=1701/udp
# firewall-cmd --permanent --add-port=500/udp 
# firewall-cmd --permanent --add-port=4500/udp 
# firewall-cmd --permanent --add-service="ipsec"
# firewall-cmd --reload

if you use CSF, create a file named /etc/csf/csfpre.sh and put these lines in it:

iptables -A INPUT -p gre -j ACCEPT
iptables -A OUTPUT -p gre -j ACCEPT
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s 192.168.100.0/24 -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o eno16777728 -j MASQUERADE

then open port 1701/udp and reload csf.
if you use iptables, just run above command and then save changes with iptables-save. also open port 1701/udp.

Note: remember to change eno16777728 with your own interface name

6- Configure SElinux

we prefer to keep selinux enabled. so to allow bringing up vpn interfaces, we should run the following command:

# setsebool -P daemons_use_tty 1

if you have disabled selinux, simply skip above command.