架设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.confno_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

大功告成!

参考:

http://b.gkp.cc/2010/06/19/setup-ipsec-l2tp-on-centos-55/

https://suoluo.org/2010/04/4/