ocserv: 兼容Cisco Anyconnect的开源服务端
ocserv(OpenConnect Server)是由GnuTLS的作者Nikos Mavrogiannopoulos开发的一个能够兼容Cisco Anyconnect的开源服务端(SSL VPN),支持*nix/BSD平台,最早是作为OpenConnect(Linux下的兼容Cisco ASA的开源客户端)对应的服务端,在后续版本(0.3.0开始)中加入了对Cisco Anyconnect客户端的支持。
由于这个软件还很新,没有进入各个发行版的repo里面,所以需要编译源码安装。
下载地址:http://www.infradead.org/ocserv/download.html,最新的版本是0.3.1。
ocserv使用GnuTLS作为SSL的library,所以编译时需要对应的dev包。Debian stable里面带的版本太老(2.12.20),而ocserv需要的包版本在2.15以上,所以需要从backports安装:
apt-get -t wheezy-backports install libgnutls28-dev
在Debian Jessie下编译时,需要安装以下的包(不包括PAM,GSSAPI或者RADIUS):
apt-get install pkg-config autogen libgnutls28-dev libwrap0-dev libsystemd-dev libseccomp-dev liblz4-dev libreadline-dev libnl-nf-3-dev libtalloc-dev libprotobuf-c-dev libpcl1-dev libopts25-dev libhttp-parser-dev
Radius支持需要在http://freeradius.org/freeradius-client/下载1.1.7版本的freeradius-client编译并安装(Debian自带的是1.1.6,ocserv要求1.1.7及以上)。
接着就可以编译了。
./configure --prefix=/usr --sysconfdir=/etc && make && make install
会编译并安装到/usr
下。
由于是SSL VPN,首先要建立服务器端的证书。以下直接摘取ocserv网站上的内容:
生成CA证书
certtool --generate-privkey --outfile ca-key.pem
cat << _EOF_ > ca.tmpl
cn = "VPN CA"
organization = "Big Corp"
serial = 1
expiration_days = 9999
ca
signing_key
cert_signing_key
crl_signing_key
_EOF_
certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem
生成本地服务器证书
certtool --generate-privkey --outfile server-key.pem
cat << _EOF_ > server.tmpl
cn = "www.example.com"
o = "MyCompany"
serial = 2
expiration_days = 9999
signing_key
encryption_key #only if the generated key is an RSA one
tls_www_server
_EOF_
certtool --generate-certificate --load-privkey server-key.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem --template server.tmpl --outfile server-cert.pem
生成之后把服务器证书放到/etc/ssl/certs
,私钥放到/etc/ssl/private
。
接下来是配置文件,建立/etc/ocserv
并把doc/sample.config
拷到该文件夹下,改名为ocserv.conf
:
mkdir /etc/ocserv && cp doc/sample.config /etc/ocserv/ && mv /etc/ocserv/sample.conf /etc/ocserv/ocserv.conf
接着修改该文件。
ocserv自0.9.0之后支持直接连接radius认证,需要freeradius-client支持,然后在配置文件中打开auth = "radius[/etc/radiusclient/radiusclient.conf]"
。freeradius-client的配置方法与radiusclient-ng一致。
server-cert
和server-key
分别指向之前生成的证书和服务器私钥。run-as-group
改为nogroup
。
ipv4-network为分配客户端的子网网段,比如ipv4-network=192.168.1.0
即为192.168.1.1-255的子网。(配合子网掩码) dns为推送给客户端的dns。
route为推送给客户端的路由表,如果采用split-tunnel-policy tunnelall
模式(所有流量通过VPN)的话删掉该行即可。
user-profile
改为user-profile = /etc/ocserv/profile.xml
,并且去掉cisco-client-compat = true
的注释。
ocserv的配置文件到这里就算修改完毕了,然后是/etc/ocserv/profile.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<anyconnectprofile xmlns='"http://schemas.xmlsoap.org/encoding/"' xmlns:xsi='"http://www.w3.org/2001/XMLSchema-instance"' xsi:schemalocation='"http://schemas.xmlsoap.org/encoding/' anyconnectprofile.xsd></anyconnectprofile>
<clientinitialization>
<usestartbeforelogon>false</usestartbeforelogon>
<strictcertificatetrust>false</strictcertificatetrust>
<restrictpreferencecaching>false</restrictpreferencecaching>
<restricttunnelprotocols>IPSec</restricttunnelprotocols>
<bypassdownloader>true</bypassdownloader>
<windowsvpnestablishment>AllowRemoteUsers</windowsvpnestablishment>
<certenrollmentpin>pinAllowed</certenrollmentpin>
<certificatematch>
<keyusage>
<matchkey>Digital_Signature</matchkey>
</keyusage>
<extendedkeyusage>
<extendedmatchkey>ClientAuth</extendedmatchkey>
</extendedkeyusage>
</certificatematch>
</clientinitialization>
<serverlist>
<hostentry>
<hostname>Server Profile Name</hostname>
<hostaddress>server.ip.address</hostaddress>
</hostentry>
</serverlist>
接下来是启动脚本,我用skeleton改写了一个很简单的放到/etc/init.d/ocserv:
#!/bin/sh
### BEGIN INIT INFO
# Provides: ocserv
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
### END INIT INFO
# Copyright Rene Mayrhofer, Gibraltar, 1999
# This script is distibuted under the GPL
PATH=/bin:/usr/bin:/sbin:/usr/sbin
DAEMON=/usr/sbin/ocserv
PIDFILE=/var/run/ocserv.pid
DAEMON_ARGS="-c /etc/ocserv/ocserv.conf"
case "$1" in
start)
if [! -r $PIDFILE]; then
echo -n "Starting OpenConnect VPN Server Daemon: "
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --
$DAEMON_ARGS > /dev/null
echo "ocserv."
else
echo -n "OpenConnect VPN Server is already running.
"
exit 0
fi
;;
stop)
echo -n "Stopping OpenConnect VPN Server Daemon: "
start-stop-daemon --stop --quiet --pidfile $PIDFILE --exec $DAEMON
echo "ocserv."
rm -f $PIDFILE
;;
force-reload|restart)
echo "Restarting OpenConnect VPN Server: "
$0 stop
sleep 1
$0 start
;;
status)
if [! -r $PIDFILE]; then
# no pid file, process doesn't seem to be running correctly
exit 3
fi
PID=`cat $PIDFILE | sed 's/ //g'`
EXE=/proc/$PID/exe
if [-x "$EXE"] &&
[ "`ls -l "$EXE" | cut -d'>' -f2,2 | cut -d' ' -f2,2`" =
"$DAEMON" ]; then
# ok, process seems to be running
exit 0
elif [-r $PIDFILE]; then
# process not running, but pidfile exists
exit 1
else
# no lock file to check for, so simply return the stopped status
exit 3
fi
;;
*)
echo "Usage: /etc/init.d/ocserv {start|stop|restart|force-reload|status}"
exit 1
;;
esac
exit 0
update-rc.d ocserv defaults
设成开机启动。DAEMON_ARGS中可以加入–http-debug -d来打开调试信息。
最后在iptables中打开tcp和udp的443端口即可。ocserv使用tcp的443端口认证,udp用于传输数据。
在Windows(3.1.05182)和iOS(3.0.12119)上测试AnyConnect客户端成功。
本文参考了ocserv的网站以及mailing list。