首页 > Linux > VPS上基于Debian配置ocserv证书认证(兼容Cisco AnyConnect)

VPS上基于Debian配置ocserv证书认证(兼容Cisco AnyConnect)

2015年1月4日 LTNS     访问次数 182 发表评论 阅读评论

之前尝试了 VPS上基于Debian搭建和配置ocserv(兼容Cisco AnyConnect客户端) [以下简称 前文],ocserv服务端启用了推送路由的功能,大致上实现了 AnyConnect(或其他第三方)客户端翻WALL时的ip自动分流功能,特别适合未越狱的iOS设备等,所以现在日常使用基本上以 ocserv 为主、其他如 strongSwan 之类的全局VPN为辅了。

不过之前客户端通过用户名/密码的方式连接 ocserv服务端,为了更安全、更便捷地访问服务端,现在改用证书认证的方式。

现在 前文 已制作了 CA证书和服务端证书的基础上,继续制作客户端证书

cd   #回到当前用户的目录
certtool --generate-privkey --outfile user-key.pem
cat << _EOF_ >user.tmpl
	cn = "user"
	unit = "admins"
	expiration_days = 3650
	signing_key
	tls_www_client
	_EOF_
 
certtool --generate-certificate --load-privkey user-key.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem --template user.tmpl --outfile user-cert.pem

客户端证书 user-cert.pem 还不能直接使用,需通过 OpenSSL转换成 .p12格式

openssl pkcs12 -export -inkey user-key.pem -in user-cert.pem -name "client" -certfile ca-cert.pem -caname "VPN CA" -out user-cert.p12
#按提示设置证书使用密码,或直接回车不设密码
 
cp ca-cert.pem /etc/ssl/certs/   #复制各证书到指定目录下
cp server-cert.pem /etc/ssl/certs/
cp server-key.pem /etc/ssl/private/

然后修改配置文件 /etc/ocserv/ocserv.conf,内容如下

auth = "certificate"
max-clients = 16
max-same-clients = 10
tcp-port = 443
udp-port = 443
keepalive = 32400
dpd = 240
mobile-dpd = 1800
try-mtu-discovery = true
server-cert = /etc/ssl/certs/server-cert.pem
server-key = /etc/ssl/private/server-key.pem
ca-cert = /etc/ssl/certs/ca-cert.pem
tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT"
auth-timeout = 40
mobile-idle-timeout
cookie-timeout = 86400000
rekey-time = 86400000
rekey-method = ssl
use-utmp = true
use-occtl = true
pid-file = /var/run/ocserv.pid
socket-file = /var/run/ocserv-socket
run-as-user = nobody
run-as-group = nogroup
net-priority = 5
cgroup = "cpuset,cpu:test"
device = vpns
default-domain = www.example.com
ipv4-network = 10.10.0.0
ipv4-netmask = 255.255.255.0
dns = 8.8.8.8
dns = 208.67.222.222
ping-leases = false
output-buffer = 10
route = ip网段/子网掩码
route-add-cmd = "ip route add %{R} dev %{D}"
route-del-cmd = "ip route delete %{R} dev %{D}"
cisco-client-compat =true
custom-header = "X-DTLS-MTU: 1200"
custom-header = "X-CSTP-MTU: 1200"

注:各参数作用详见软件包里的示例配置文件里的详细说明,或者见参考文章,这里不再赘述。

重启 ocserv服务端

/etc/init.d/ocserv restart

最后在 Cisco AnyConnect等客户端选择证书方式,无需输入用户名和密码就可以连接成功。如有问题,可查看服务端日志文件 /var/log/syslog,或者运行如下调试命令实时跟踪

/etc/init.d/ocserv stop   #停止程序
ocserv -c /etc/ocserv/ocserv.conf -f -d 1

 
顺便提一下,相比 前文 中提到的用户名/密码的方式,我在 Nexus 4(4.4.4)上使用 Cisco官方的 Android客户端 通过证书认证的方式登录,不但联通3G、就是电信宽带也无法成功,只能改用 客户端OpenConnect,Cisco官方的 iOS客户端 则都正常。

另外,win7上试过 AnyConnect Secure Mobility Client V3.1和最新的V4.0,无论联通3G还是电信宽带都连接失败,改用 ocserv官网 推荐的 客户端openconnect-gui 就正常了(不过证书要改用 .pem格式的)。

总之,相比用户名/密码的方式,感觉证书方式对 Cisco AnyConnect的兼容性更差一些。

最后,建议把所有证书文件备份到本地电脑硬盘,这样万一将来VPS因故障需要重装系统时,无需重新制作各个客户端证书并一一通知对方更新了。

 
补充1:
ocserv 0.8.9程序似乎有bug,按照 官网教程 里的有效期 9999天制作出来的证书有效期截止日反而会过期

certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem
#反馈如下
Generating a self signed certificate...
X.509 Certificate Information:
        Version: 3
        Serial Number (hex): 01
        Validity:
                Not Before: Sat Jan 03 04:49:35 UTC 2015
                Not After: Thu Apr 13 22:21:19 UTC 2006
...

改成比如 7777天就正常了,然后重新制作 CA证书、服务端证书和客户端证书,否则会导致证书认证失败,日志中会有类似如下的出错记录

client certificate verification failed: The certificate is NOT trusted. The certificate chain uses expired certificate.

tlslib.c:372: error verifying client certificate: No certificate was found.

还可以对制作的服务端和客户端证书进行校验,在这个 帖子 里面 ocserv作者提及的校验命令是

certtool --verify --load-ca-certificate ca-cert.pem --infile user-cert.pem

但实际用下来却提示 verify选项无效。经网上搜索,找到的 另一个帖子 提及 verify选项在稳定版中尚不存在,需改用 verify-chain(或是更简单的缩写 -e

cd
cat server-cert.pem ca-cert.pem > serverchain.pem   #生成一个临时文件
certtool -e --load-ca-certificate ca-cert.pem --infile serverchain.pem
   #反馈如下两段内容
   Certificate[0]: O=MyCompany,CN=www.example.com
        Issued by: O=Big Corp,CN=VPN CA
        Verifying against certificate[1].
        Verification output: Verified.
 
   Certificate[1]: O=Big Corp,CN=VPN CA
        Issued by: O=Big Corp,CN=VPN CA
        Verification output: Verified.
rm -f serverchain.pem   #删除临时文件

 
补充2:
为方便客户端证书的制作,这里提供一个脚本如 ~/ccm.sh,供参考

#!/bin/bash
   read -p "Please input username:" user
   if [ "$user" = "" ]; then
	echo "Error! - you must input an username"
	echo "Exit!"
	exit 1
   fi
   echo "==========================="
   echo "Making ${user}-key.pem ..."
certtool --generate-privkey --outfile ${user}-key.pem
   echo "Modifying client.tmpl ..."
sed -i "1ccn = "${user}"" client.tmpl
   echo "Making ${user}-cert.pem ..."
certtool --generate-certificate --load-privkey ${user}-key.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem --template client.tmpl --outfile ${user}-cert.pem
   echo "Making ${user}-cert.p12 ..."
openssl pkcs12 -export -inkey ${user}-key.pem -in ${user}-cert.pem -name "client" -certfile ca-cert.pem -caname "ocserv CA" -out ${user}-cert.p12
   echo "========== done =========="

 
以及配套使用的模板文件 ~/client.tmpl

cn = client
unit = "users"
expiration_days = 3650
signing_key
tls_www_client

 
另外还提供一个验证用的脚本 ~/ccv.sh,供参考

#!/bin/bash
   read -p "Please input username:" user
   if [ "$user" = "" ]; then
	echo "Error! - you must input an username"
	echo "Exit!"
	exit 1
   fi
   echo "==========================="
   echo "Verifying ${user}-cert.pem ..."
cat ${user}-cert.pem ca-cert.pem > ${user}chain.pem
certtool --verify-chain --load-ca-certificate ca-cert.pem --infile ${user}chain.pem
rm -f ${user}chain.pem

 
修改脚本的权限

cd
chmod 755 ccm.sh     #修改权限
chmod 755 ccv.sh
./ccm.sh     #执行并按提示操作

 
补充3:
如要注销某个客户端证书,按照 官网教程 制作注销列表文件 crl.pem

cd
cat << _EOF_ >crl.tmpl
	crl_next_update = 999
	crl_number = 1
	_EOF_
 
cat user-cert.pem >>revoked.pem
certtool --generate-crl --load-ca-privkey ca-key.pem --load-ca-certificate ca-cert.pem --load-certificate revoked.pem --template crl.tmpl --outfile crl.pem

然后在配置文件 /etc/ocserv/ocserv.conf 中启用证书注销功能

# The revocation list of the certificates issued by the 'ca-cert' above.
crl = /root/crl.pem

 
如果不再有客户端证书需要注销了,则需重新生成一下注销列表文件

certtool --generate-crl --load-ca-privkey ca-key.pem --load-ca-certificate ca-cert.pem --template crl.tmpl --outfile crl.pem

最后重启一下 ocserv服务端。

 
 
参考文章
1. https://darknode.in/archives/install-and-config-ocserv-on-debian.html
2. http://brucebot.com/2014/11/how-to-setup-a-anyconnect-vpn-for-ios-with-certificate/
3. http://bao3.blogspot.com/2014/10/ocserv-085.html

 

分类: Linux 标签: , , , , , , ,
  1. idigital
    2015年1月9日14:18 | #1

    哇哦,真棒!

  2. F.
    2015年4月18日20:23 | #2

    我用账号密码一直都是没问题的,但一旦使用证书登录就会提示无法从证书中获取用户。博主知道这种是什么情况吗?

    ocserv[714]: worker: client certificate verification succeeded
    ocserv[714]: worker: 124.160.217.244 worker-auth.c:441: cannot obtain user from certificate DN: The requested data were not available.
    ocserv[714]: worker: 124.160.217.244 worker-auth.c:825: cannot read username (0.9.2342.19200300.100.1.1) from certificate
    ocserv[714]: worker: 124.160.217.244 worker-auth.c:1267: failed reading certificate info
    ocserv[707]: main: 124.160.217.244:32076 user '' disconnected

  3. LTNS
    2015年4月19日20:09 | #3

    @F.
    你在哪个平台上用的哪个客户端?

    我这里除了 iOS设备上可以使用 Cisco AnyConnect这个客户端的证书方式,其他如 Win7、Android平台上的都不行,只能改用 ocserv官网推荐的 OpenConnect,文中亦有提及

  4. F.
    2015年4月19日22:50 | #4

    @LTNS
    我是在android上用的,反复读了官方手册发觉客户端证书似乎要求一个UID,增加了之后,生成的新客户端证书就正常连接了。我手头暂时没有iOS可测试,不知道iOS下能不能用。Win上没打算用,因为shadowsocks已经挺好用了,再加上自签名证书这个事吧。。。

  5. benepsalm
    2015年5月7日10:50 | #5

    @F.
    您好! 请问uid是如何添加的 谢谢

  6. EraserKing
    2015年5月7日21:09 | #6

    @benepsalm
    在生成客户端证书的那一段里(cn = "user" unit = "admins")
    插一句uid = "anything you want"
    重新生成一次客户端证书即可。

  7. cesar
    2015年9月5日15:15 | #7

    #4的方法很有效,在IOS下工作正常。

  8. CzBiX
    2015年10月12日19:55 | #8

    @F.
    修改配置文件 cert-user-oid = 2.5.4.3 就好了

10 + 9 = (必填)