架设L2TP/IPSec + MySQL + FreeRADIUS认证VPN
接上次那篇PPTP的文,这篇讲下如何搭建L2TP VPN。平台依然是CentOS 5.6 x86,源码方式安装。
说实在的搭建L2TP over IPSec VPN让人头痛不少,主要是因为需要好几个内核模块支持。因而如果你使用的是OpenVZ的VM的话基本上可以忽略这篇文章-2.6.32以下的内核不支持IPSec虚拟化。
如果是Xen的话,在确定能用PPTP的基础上(包括IP转发,etc),执行以下命令确认必需的模块都存在(xfrm_user可能编入了内核,所以没有检测):
modprobe af_key && modprobe ah4 && modprobe esp4 && modprobe ipcomp && modprobe xfrm4_tunnel && echo "All IPSec modules are loaded"
如果出现All IPSec modules are loaded
则该VM有所有需要的内核模块,否则不能建L2TP over IPSec。
6月21日更新:最近搞了个日本的VPS,执行上面命令发现模块都存在但是都没加载,而且连ppp的也没有(lsmod | grep -w 'af_key|ah4|esp4|ipcomp|xfrm4_tunnel|ppp_generic|ppp_mppe |ppp_deflate'
),结果在/etc/sysconfig/modules
里面手工添加了。
成功之后下载需要的软件包
首先安装一些编译需要的软件包:
yum install bison flex lsof gmp gmp-devel libpcap libpcap-devel
然后下载OpenSwan、xl2tpd和rp-l2tp。
OpenSwan: http://www.openswan.org/code/
xl2tpd: http://www.xelerance.com/services/software/xl2tpd/
rp-l2tp: http://sourceforge.net/projects/rp-l2tp
OpenSwan编译安装:make programs && make install
xl2tpd:make && make install
rp-l2tp我们只需要其中的l2tp-control,执行以下命令:
make
cp handlers/l2tp-control /usr/local/sbin/
mkdir /var/run/xl2tpd
ln -s /usr/local/sbin/l2tp-control /var/run/xl2tpd/l2tp-control
写IPSec的配置文件:
需要修改的地方:
protostack=auto
改成protostack=netkey
最后加上
# sample VPN connections, see /etc/ipsec.d/examples/
include /etc/ipsec.d/l2tp-psk.conf #添加l2tp配置
# Disable Opportunistic Encryption
include /etc/ipsec.d/no_oe.conf #添加oe配置
注意缩进!上面添加的几行必须是紧靠左边(左边不能有空格)。
然后新建l2tp-psk.conf
和no_oe.conf
(来自https://suoluo.org/2010/04/4/)
nano /etc/ipsec.d/no_oe.conf
conn block
auto=ignore
conn private
auto=ignore
conn private-or-clear
auto=ignore
conn clear-or-private
auto=ignore
conn clear
auto=ignore
conn packetdefault
auto=ignore
nano /etc/ipsec.d/l2tp-psk.conf
conn L2TP-PSK-NAT
rightsubnet=vhost:%no,%priv
also=L2TP-PSK-noNAT
conn L2TP-PSK-noNAT
#
# 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 Preshared Key. Disable Perfect Forward Secrecy.
#
# PreSharedSecret needs to be specified in /etc/ipsec.secrets as YourIPAddress %any: "sharedsecret"
authby=secret
pfs=no
auto=add
keyingtries=1
# we cannot rekey for %any, let client rekey
rekey=no
#
left=74.117.63.108
leftnexthop=%defaultroute
#
# For updated Windows 2000/XP clients, to support old clients as well, use leftprotoport=17/%any
leftprotoport=17/1701
#
# The remote user.
#
right=%any
# Using the magic port of "0" means "any one single port". This is a work around required for Apple OSX clients that use a randomly
# high port, but propose "0" instead of their port.
rightprotoport=17/%any
同样的要注意缩进。在两个conn之间的语句要向右缩进一格。 设置预置密钥:
nano /etc/ipsec.secrets:
YOUR.SERVER.IP.ADDRESS %any: PSK "YourSharedSecret"
最后修改/etc/sysctl.conf:
# Settings for OpenSwan IPSec implementation
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.core.xfrm_larval_drop = 1
测试下IPSec:
/etc/init.d/ipsec start
ipsec verify
如果是类似如下结果就可以继续了(不能有Failed,N/A可以)。
Checking your system to see if IPsec got installed and started correctly:
Version check and ipsec on-path [OK]
Linux Openswan U2.6.33/K2.6.18-194.11.4.el5xen (netkey)
Checking for IPsec support in kernel [OK]
SAref kernel support [N/A]
NETKEY: Testing XFRM related proc values [OK]
[OK]
[OK]
Testing against enforced SElinux mode [OK]
Checking that pluto is running [OK]
Pluto listening for IKE on udp 500 [OK]
Pluto listening for NAT-T on udp 4500 [OK]
Two or more interfaces found, checking IP forwarding [OK]
Checking NAT and MASQUERADEing
Checking for 'ip' command [OK]
Checking /bin/sh is not /bin/dash [OK]
Checking for 'iptables' command [OK]
Opportunistic Encryption Support [DISABLED]
pluto listening那个与lsof有关,如果显示failed检查是否装了lsof。
测试通过后修改xl2tpd的配置:
如果你的ipsec verify结果中间也有SAref kernel support [N/A]
的话,在xl2tpd里面就必须关掉saref,否则tail /var/log/secure
会出现ERROR: netlink_get_spi for comp.0@server ip failed with errno 22: Invalid argument
。
[global]
listen-addr = your.server.ip.address
;
; 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+
ipsec saref = no
[lns default]
ip range = 192.168.100.101-192.168.100.151
local ip = 192.168.100.1
refuse chap = yes
refuse pap = yes
require authentication = yes
name = l2tpd
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes
修改ppp配置:
require-mschap-v2
ms-dns 8.8.8.8
ms-dns 208.67.222.222
asyncmap 0
auth
crtscts
lock
hide-password
modem
debug
name l2tpd
proxyarp
lcp-echo-interval 30
lcp-echo-failure 4
plugin /usr/local/lib/pppd/2.4.5/radius.so
plugin /usr/local/lib/pppd/2.4.5/radattr.so
radius-config-file /usr/local/etc/radiusclient/radiusclient.conf
建立xl2tpd的init script:
#!/bin/sh
#
# xl2tpd This shell script takes care of starting and stopping l2tpd.
#
# chkconfig: - 80 30
# description: Layer 2 Tunnelling Protocol Daemon (RFC 2661)
#
# processname: /usr/sbin/xl2tpd
# config: /etc/xl2tpd/xl2tpd.conf
# pidfile: /var/run/xl2tpd.pid
### BEGIN INIT INFO
# Provides: xl2tpd
# Required-Start: $local_fs $network $syslog
# Required-Stop: $local_fs $network $syslog
# Default-Start:
# Short-Description: start|stop|status|restart|try-restart|reload|force-reload xl2tpd server
# Description: control xl2tpd server
### END INIT INFO
#Servicename
SERVICE=xl2tpd
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
if [ ${NETWORKING} = "no" ]
then
exit 0
fi
[ -x /usr/local/sbin/$SERVICE ] || exit 0
RETVAL=0
start() {
echo -n "Starting $SERVICE: "
if [ ! -d /var/run/xl2tpd ]
then
mkdir /var/run/xl2tpd
fi
daemon /usr/local/sbin/$SERVICE
RETVAL=$?
echo
if [ $RETVAL -eq 0 ];then
touch /var/lock/subsys/$SERVICE
else
exit 7;
fi
return 0;
}
stop() {
echo -n "Stopping $SERVICE: "
killproc $SERVICE
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
rm -f /var/run/xl2tpd/$SERVICE
rm -f /var/lock/subsys/$SERVICE
fi
echo
return $RETVAL
}
restart() {
stop
start
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status $SERVICE
RETVAL=$?
;;
restart|reload)
restart
;;
condrestart)
[ -f /var/lock/subsys/$SERVICE ] && restart || :
;;
*)
echo "Usage: $SERVICE {start|stop|status|restart|reload|condrestart}"
exit 1
esac
最后对应的iptables的配置:
-A INPUT -p udp -m state --state NEW -m udp --dport 500 -j ACCEPT
-A INPUT -p udp -m state --state NEW -m udp --dport 1701 -j ACCEPT
-A INPUT -p udp -m state --state NEW -m udp --dport 4500 -j ACCEPT
大功告成!
参考: