Total Pageviews

Monday, 16 February 2015

在CentOS6/7下,编译ocserv vpn,以便在iphone/mac/android/windows上使用Cisco AnyConnect VPN客户端程序翻墙(我在debian8/ubuntu14.04/ubuntu15.04上也编译成功,并顺利翻墙。而且在debian8/ubuntu14.04/ubuntu15.04上,安装更简单)

在 CentOS 6下,安装ocserv(按此文,我安装成功,顺利翻墙)

AnyConnect是思科的安全远程接入解决方案,之前只有思科的设备才支持。
ocserv(OpenConnect server)是一个OpenConnect SSL VPN协议服务端,0.3.0版后兼容使用AnyConnect SSL VPN协议的终端。
官方主页:http://www.infradead.org/ocserv/

在iOS下的客户端推荐使用cisco AnyConnect,目前iOS使用VPN存在以下问题:
1、待机会断开
2、不能控制路由表

iOS使用APN存在以下问题:
1、不稳定,有时打不开页面
2、需要墙内墙外均部署服务器

AnyConnect相比有以下优势:
1、待机不会断开
2、能够下发路由表给客户端(未测试)
3、稳定
4、相比APN,只需要1台机器

经测试,从晚上2点多,待机到早上9点多,iPhone电量从18%掉到13%,AnyConnect还保持连接。
环境:CentOS 6.5 x64
ocserv需要3.1版以上的gnutls,gnutls需要2.7版以上的nettle
这两个在repo仓库里均没有,所以我们自己编译
首先保证系统里已安装openssl、gcc、make等常用软件
BTW:Ubuntu上好像可以用apt-get -t wheezy-backports从backports安装这些新版本(未测试)

1、编译nettle
安装gmp
yum install 
gmp gmp-devel m4 autogen -y (需先安装gmp,然后安装gmp-devel.如果是debian/ubuntu系统,则
apt-get install libgmp-dev libgmp3-dev autogen -y)
wget http://ftp.gnu.org/gnu/nettle/nettle-2.7.1.tar.gz
tar zxvf nettle-2.7.1.tar.gz 

cd nettle-2.7.1
./configure --
prefix=/usr
make
make install

(注:configure时,如果提示找不到gmp,则先运行:
export CPPFLAGS="-I/usr/local/include"
export LDFLAGS="-L/usr/local/lib"

然后./configure    这是for 32位系统。

for 64位系统:
export CPPFLAGS="-I/usr/include"
export LDFLAGS="-L/usr/lib64"

然后./configure )

2、编译unbound
安装expat-devel
yum install expat-devel

(在debian/ubuntu os下,则:
apt-get install libexpat1 libexpat-gst -y
apt-get install libexpat1-dev -y )
wget http://unbound.nlnetlabs.nl/downloads/unbound-1.4.22.tar.gz
tar zxvf unbound-1.4.22.tar.gz 

cd unbound-1.4.22
./configure 

make && make install
ldconfig
mkdir -p /etc/unbound && unbound-anchor -a "/etc/unbound/root.key"

tar Jxvf gnutls-3.2.15.tar.xz
cd gnutls-3.2.15
export LD_LIBRARY_PATH=/usr/lib/:/usr/lib64/ NETTLE_CFLAGS="-I/usr/include/" NETTLE_LIBS="-L/usr/lib64/ -lnettle" HOGWEED_CFLAGS="-I/usr/include" HOGWEED_LIBS="-L/usr/lib64/ -lhogweed" LIBGNUTLS_CFLAGS="-I/usr/include/" LIBGNUTLS_LIBS="-L/usr/lib64/ -lgnutls" (这是一条命令)
./configure --
prefix=/usr
make 
make install
ldconfig

(注:编译gnutls之前需要运行以下命令设置系统变量,再运行./configure --prefix=/usr,同时要把这些命令加进系统启动里:
32bit
export LD_LIBRARY_PATH=/usr/local/lib/:/usr/local/lib64/
export NETTLE_CFLAGS='-I/usr/local/include/'
export NETTLE_LIBS='-L/usr/local/lib/ -lnettle'
export HOGWEED_CFLAGS='-I/usr/local/include'
export HOGWEED_LIBS='-L/usr/local/lib/ -lhogweed'
export LIBGNUTLS_CFLAGS='-I/usr/local/include/'
export LIBGNUTLS_LIBS='-L/usr/local/lib/ -lgnutls'

64bit
export LD_LIBRARY_PATH=/usr/lib/:/usr/lib64/ NETTLE_CFLAGS='-I/usr/include/' NETTLE_LIBS='-L/usr/lib64/ -lnettle' HOGWEED_CFLAGS='-I/usr/include' HOGWEED_LIBS='-L/usr/lib64/ -lhogweed' LIBGNUTLS_CFLAGS='-I/usr/include/' LIBGNUTLS_LIBS='-L/usr/lib64/ -lgnutls' )
4、编译ocserv
wget ftp://ftp.infradead.org/pub/ocserv/ocserv-0.9.2.tar.xz (不建议安装
ocserv-0.3.2.tar.xz,此版本太老了,编译容易出错)
tar Jxvf ocserv-0.9.2.tar.xz
 cd ocserv-0.9.2
./configure
make 
make install

(遇到“找不到库文件”的解决办法:
1. ocserv:error while loading shared libraries: libgnutls.so.28: cannot open shared object file: No such file or directory

ln -s /usr/local/lib/libgnutls.so.28 /usr/lib64/

2. observ: error while loading shared libraries: libnettle.so.4: cannot open shared object file: No such file or directory:

ln -s /usr/local/lib64/libnettle.so.4 /usr/lib64/

3. ocserv: error while loading shared libraries: libhogweed.so.2: cannot open shared object file: No such file or directory:

ln -s /usr/local/lib64/libhogweed.so.2 /usr/lib64/ )

5、配置ocserv
创建ca证书和服务器证书(参考http://www.infradead.org/ocserv/manual.html#heading5
certtool --generate-privkey --outfile ca-key.pem

新建文件ca.tmpl,内容如下:(这里,cn和organization的值可以随便填写)
cn = "brite VPN"
organization = "brite"
serial = 1
expiration_days = 3650
ca
signing_key
cert_signing_key
crl_signing_key

certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem
certtool --generate-privkey --outfile server-key.pem

新建文件server.tmpl,内容如下:(这里,cn的值不能随便写。)
cn = "服务器的公网ip"
organization = "brite"
serial = 2
expiration_days = 3650
signing_key
encryption_key #only if the generated key is an RSA one
tls_www_server

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 (这两行是一条命令)

把证书复制到ocserv的配置目录
mkdir -p /usr/local/etc/ocserv/
cp server-cert.pem /usr/local/etc/ocserv/ && cp server-key.pem /usr/local/etc/ocserv/

复制配置文件样本,还在ocserv的解压目录中
cp doc/sample.config /usr/local/etc/ocserv/ocserv.conf

cp doc/sample.passwd /usr/local/etc/ocserv/ocpasswd

编辑配置文件:
nano /usr/local/etc/ocserv/ocserv.conf
修改如下:
auth = "plain[
passwd=/usr/local/etc/ocserv/ocpasswd]"
#ocserv支持多种认证方式,这是自带的密码认证,使用ocpasswd创建密码文件
#ocserv还支持证书认证,可以通过Pluggable Authentication Modules (PAM)使用radius等认证方式.

修改ocserv所监听的TCP/UDP端口
tcp-port = 999
udp-port = 9001 (可以不改UDP端口)
server-cert = /usr/local/etc/ocserv/server-cert.pem
server-key = /usr/local/etc/ocserv/server-key.pem

max-same-clients = 10
#同一个用户最多同时登陆数

#default-domain = example.com
 
ipv4-network = 192.168.10.0 
#分配给VPN客户端的IP段
dns = 8.8.8.8
#route = 192.168.1.0/255.255.255.0
#route = 192.168.5.0/255.255.255.0
#route = default
route参数留空表示所有流量均走VPN server。
也注释掉noroute那行。
#ocserv可以给客户端下发路由表。比如可以把公司内网IP段、所有国外IP走VPN出去。

创建认证用的用户文件
ocpasswd -c /usr/local/etc/ocserv/ocpasswd your-username   (运行此命令,会提示你设置你自己的密码)

允许转发:
修改/etc/sysctl.conf,
net.ipv4.ip_forward=1
sysctl -p


iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o venet0 -j MASQUERADE
#IP段和venet0接口要根据自己的情况修改。
或者运行iptables -t nat -A POSTROUTING -j MASQUERADE也可。

(如果你是在centos7下,则还需进行如下操作:
systemctl stop firewalld
systemctl disable firewalld
yum erase firewalld

yum install iptables-services -y (如果运行下面2条命令出错,则先安装iptables-services)
systemctl enable iptables
systemctl start iptables

这段内容的意思是停止firewalld而启用iptables.我之前没有停止firewalld,弄得我在客户端机器上,一直连不上ocserv  vpn服务器。

因为centos7默认不开放非常用的端口,所以还需运行iptables命令,开放tcp端口999和udp端口9001如下
iptables -I INPUT -p tcp -m tcp --dport 999 -j ACCEPT,意思是开放tcp端口999.
iptables -I INPUT -p udp -m udp --dport 9001 -j ACCEPT,意思是开放udp端口9001.

iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

service iptables save
service iptables restart )

最后运行ocserv即可:
ocserv -c /usr/local/etc/ocserv/ocserv.conf
(这条命令是运行在后台的。)

(在iOS上安装Cisco AnyConnect vpn,即可连接VPN服务器.cisco-client-compat = true可以确保 oc­serv 同 Cisco Any­Con­nect for i­OS 的兼容性,若不启用会导致证书登陆报出 GnuTLS error: No certificate was found 这样的错误。

使用 openssl 将用户证书转换为 .p12 格式,以避免使用 cert­tool 转换时与 Cisco Any­Con­nect for i­OS 的兼容性问题。
将用户证书 user.p12 放置到某种 Web 服务器的网页目录下,使得用户证书可以通过 URL 访问得到,随后打开 Cisco Any­Con­nect for i­OS,依次点击“诊断”、“证书”、“导入用户证书”,输入 user.p12 的完整 URL 即可。)
Android上也有Cisco AnyConnect vpn(需要root),不过Android可选择的方法太多.
Windows、MAC OS也有Cisco 
AnyConnect vpn客户端。
在配置Cisco AnyConnect vpn客户端时,所输入的服务器地址后,记得加上TCP端口号

参考:
http://www.infradead.org/ocserv/manual.html
http://www.cisco.com/web/CN/solutions/trends/byod_smart_solution/pdf/at_a_glance_c45_578609.pdf
教程完毕。

pkg-config寻找包的依赖关系时没有找到对应的.pc文件,告诉它地址就好了:
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH

应该装到了lib64这里了,所以改了下
export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig:$PKG_CONFIG_PATH
-----------------------------------------------------------

在 CentOS6上配置 Cisco AnyConnect VPN

为什么选择 Cisco AnyConnect VPN ?

它是 iOS 端目前最好的 xx 解决方案:
  • 激活后全局有效
  • 自动重连,即使锁屏后重开也不会掉线
  • 可导入路由配置
开始动手吧~
首先安装所有依赖包:
安装 Nettle:
安装 unbound:
安装后执行程序将会出现动态库文件找不到的问题:unbound-anchor: error while loading shared libraries: libunbound.so.2: cannot open shared object file: No such file or directory
这是因为系统默认没有找/usr/local/lib目录下的库文件,为了一劳永逸,我们把将路径加入到配置文件中:
echo '/usr/local/lib' > /etc/ld.so.conf.d/local-libraries.conf && ldconfig
生成配置文件:unbound-anchor -a "/etc/unbound/root.key",这是为了消除之后编译gnutls时遇到的警告信息:
安装 gnutls:
这时会遇到Libnettle 2.7 was not found.错误,其实还是路径问题,pkg-config寻找包的依赖关系时没有找到对应的.pc文件,告诉它地址就好了:export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH。继续编译~
安装 LibNL:
终于该主角上场了,安装 Ocserv:
一切都非常顺利,yeah!
---------------------------------------
 架设OpenConnect Server,给iPhone提供更顺畅的网络生活

OpenConnet Server(ocserv)是朋友给我的建议,它通过实现Cisco的AnyConnect协议,用DTLS作为主要的加密传输协议。我认为它的主要好处在于——
  • AnyConnect的VPN协议默认使用UDP DTLS作为数据传输,但如果有什么网络问题导致UDP传输出现问题,它会利用最初建立的TCP TLS通道作为备份通道,降低VPN断开的概率。
  • AnyConnect作为Cisco新一代的VPN解决方案,被用于许多大型企业,这些企业依赖它提供正常的商业运作,这些正常运作对应的经济效益(读作GDP),是我们最好的伙伴。
  • OpenConnet的架设足够麻烦,我的意思是,如果你不是大型企业,你会用AnyConnect的概率无限趋近于零。再者,如果它足够简单,我就不用写这篇文章了。
至于它的自定义路由表支持,我觉得都是次要了。
介绍到此,让我们按步骤干好事情。
(下文选用最新的Ubuntu 14.04 LTSOCServ 0.9.0.1作为标准环境,但我会尽量提供不依赖版本的步骤与建议。)

编译OCserv

官方站点找最新的OpenConnect Server版本。
curl -O ftp://ftp.infradead.org/pub/ocserv/ocserv-0.9.0.1.tar.xz
tar Jxvf ocserv-0.9.0.1.tar.xz
cd ocserv-0.9.0
看下README文件提及的编译依赖。理论上只有libgnutls-dev和libreadline-dev是必须的,但我们还是把可选的功能都带上。
(顺便一提,如果你在Ubuntu 14.04或更早版本上,libgnutls-dev的版本还是2.x,需要用libgnutls28-dev获取3.x的GnuTLS才能支持OCserv。)

apt-get install build-essential pkg-config libgnutls28-dev libreadline-dev libseccomp-dev libpam0g-dev libwrap0-dev libnl-nf-3-dev autogen

apt-get install gnutls-bin -y (注意:一定不要忘了安装gnutls-bin,否则你运行certtool时,会遇到提示:command not found.)
(注意:从debian8起,才默认有libgnutls28-dev libseccomp-dev libpam0g-dev libwrap0-dev libnl-nf-3-dev这些包.所以建议在debian8或ubuntu14.04以上的系统安装ocserv.不建议在debian7或debian7以下的系统安装ocserv.)

编译并安装。
./configure
(在我测试的环境里,最终报告只有systemd和dbus的结果为no,如果你发现其他项目显示no,不必担心,你的环境可能安装了可选的包导致出现不同结果。目前只有libgnutls28-dev是必须的模块。)
make
make install

配置OCserv

我们希望做到的,是无需用户名与密码的客户端证书验证登陆。但在此之前,让我们先测通更简单的密码登录模式。首先让我们把CA证书与服务器证书生成好,具体步骤官方文档也有——
mkdir certificates
cd certificates

创建ca.tmpl,按需填写,这里的cn和organization可以随便填。
cn = "Your CA name"
organization = "Your fancy name"
serial = 1
expiration_days = 3650
ca
signing_key
cert_signing_key
crl_signing_key

生成CA密钥:
certtool --generate-privkey --outfile ca-key.pem

生成CA证书:
certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem

同理,我们用CA签名,生成服务器证书。先创建server.tmpl模板。这里的cn项必须对应你最终提供服务的hostname或公网IP,建议用公网IP,否则AnyConnect客户端将无法正确导入证书。
cn = "服务器的public IP"
organization = "Your fancy name"
expiration_days = 3650
signing_key
encryption_key
tls_www_server

生成Server密钥:
certtool --generate-privkey --outfile server-key.pem

生成Server证书:
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

将CA,Server证书与密钥复制到以下文件夹
sudo cp ca-cert.pem /etc/ssl/certs/my-ca-cert.pem
sudo cp server-cert.pem /etc/ssl/certs/my-server-cert.pem
sudo cp server-key.pem /etc/ssl/private/my-server-key.pem

剩下的就是OCServ配置文件了。同样的,参考官方文档是最佳选项,但为了方便起见,这是你需要注意的一些设置。回到ocserv-0.9.0的文件夹下,将配置文件复制到OCserv默认读取的位置。
sudo mkdir /etc/ocserv
sudo cp doc/sample.config /etc/ocserv/ocserv.conf

nano /etc/ocserv/ocserv.conf
确保以下配置正确
# 登陆方式,先用密码登录
auth = "plain[/etc/ocserv/ocpasswd]"
# 允许同时连接的客户端数量
max-clients = 4
# 限制同一客户端的并行登陆数量
max-same-clients = 2
# 服务监听的TCP/UDP端口
tcp-port = 9000
udp-port = 9001
# 自动优化VPN的网络性能
try-mtu-discovery = true
# 服务器证书与密钥
server-cert = /etc/ssl/certs/my-server-cert.pem
server-key = /etc/ssl/private/my-server-key.pem
# 客户端连上vpn后使用的dns
dns = 8.8.8.8
# 注释掉所有的route,让服务器成为gateway
#route = 192.168.1.0/255.255.255.0
# 启用cisco客户端兼容性支持
cisco-client-compat = true

创建一个登陆用的用户名与密码:
sudo ocpasswd -c /etc/ocserv/ocpasswd your-username
这样OCserv就基本配置好了。但如果你和我一样强化过服务器安全,还得为服务器上开些端口才行。以Linode的安全配置为例,我们需要运行如下的iptables命令。
打开OCserv对应的TCP/UDP端口
iptables -A INPUT -p tcp --dport 9000 -j ACCEPT
iptables -A INPUT -p udp --dport 9001 -j ACCEPT

启用NAT:
iptables -t nat -A POSTROUTING -j MASQUERADE

完成之后导入新配置并检查配置正确:
sudo iptables-restore < /etc/iptables.firewall.rules
sudo iptables -L
sudo iptables -t nat -L
如果你之前没有配置服务器启动时自动导入这个设置
sudo nano /etc/network/if-pre-up.d/firewall
输入以下内容
#!/bin/sh
/sbin/iptables-restore < /etc/iptables.firewall.rules

最后我们需要打开IPv4的流量转发。
sudo nano /etc/sysctl.conf
启用此项
net.ipv4.ip_forward=1
并刷新配置
sudo sysctl -p 

测试OCserv

在服务器端启动OpenConnect Server:
sudo ocserv -f -d 1
如果服务没错误,是时候来测测客户端了。假设你使用iOS,下载Cisco AnyConnect
在Connections下加入新的VPN配置,在服务器地址栏目上填入对应的IP/Hostname和TCP端口(我们的例子就是1.2.3.4:9000)
然后到设置标签页下暂时禁用“阻止不信任的服务器”选项。首次连接,AnyConnect会提示你这是不信任证书,如果你之前的服务器证书模板的 cn没写错的话(我们的例子是1.2.3.4),你可以接受并导入该证书(可在诊断标签页的证书菜单里的服务器证书列表看到)。以后即便启用“阻止不信任 的服务器”选项,也不会报错了(和SSH首次登陆类似)。
确定VPN连接正常并可以科学上网后,我们可以接着提高网络生活质量。

自动化OCserv

假如现有的配置有哪里让人不大满意,大概是这两点——
  1. OCserv的服务最好会自动跑,进程挂了也自动恢复。
  2. AnyConnect每次都要输入密码很麻烦,最好用客户端证书验证。
为OCserv写个简单的upstart脚本。
cd /etc/init.d
sudo ln -s /lib/init/upstart-job ocserv
cd /etc/init
sudo nano ocserv.conf
放入以下内容
#!upstart
description "OpenConnect Server"
start on runlevel [2345]
stop on runlevel [06]
respawn
respawn limit 20 5
script
    exec start-stop-daemon --start --pidfile /var/run/ocserv.pid --exec /usr/local/sbin/ocserv -- -f >> /dev/null 2>&1
end script
这样就可以用以下方式启动/暂停服务
sudo service ocserv start
sudo service ocserv stop

为AnyConnect建个客户端证书
和服务器端证书的步骤基本相同。回到之前的certificates文件夹。
创建user.tmpl
cn = "some random name"
unit = "some random unit"
expiration_days = 365
signing_key
tls_www_client

生成User密钥:
certtool --generate-privkey --outfile user-key.pem

生成User证书:
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

然后要将证书和密钥转为PKCS12的格式。按说certtool也能做到,但不知为何,当前的AnyConnect iOS版并不接受certtool生成的p12文件,于是我们只能用openssl:

openssl pkcs12 -export -inkey user-key.pem -in user-cert.pem -certfile ca-cert.pem -out user.p12

然后我们要通过URL将user.p12文件导入AnyConnect,具体位置在诊断标签页的证书栏目下。如果你的服务器已经有Nginx/Apache服务,只要传到一个可以访问的URL路径下即可。如果没有,请参照Nginx官网Linode的Nginx入门教程
导入成功之后,将对应的VPN设置的高级设置部分的证书栏目,改为导入的这张证书。
最后我们要调整下OCserv的配置——
nano /etc/ocserv/ocserv.conf
修改以下内容
# 改为证书登陆,注释掉原来的登陆模式
auth = "certificate"
# 证书认证不支持这个选项,注释掉这行:
listen-clear-file = /var/run/ocserv-conn.socket
# 启用证书验证
ca-cert = /etc/ssl/certs/my-ca-cert.pem
cert-user-oid = 2.5.4.3
重启OCserv服务,确认VPN无需密码就可以正常登陆。

小结

这篇笔记是在完成配置之后靠回忆写下的,仅仅做到“可用”,没做更多优化与安全配置。如有什么疏漏(很可能有,毕竟环境不可能完全一致),欢迎在留言栏相互协助。祝各位的iPhone生活美满~
参考阅读:
FROM  http://bitinn.net/11084/
 --------------------------------------

Debian下搭建Ocserv vpn,并启用证书验证

安装依赖:
apt-get install build-essential autogen pkg-config
apt-get install libtalloc-dev libreadline-dev libpam0g-dev libhttp-parser-dev libpcl1-dev
apt-get install libgnutls28-dev libev-dev
apt-get install libprotobuf-c-dev libhttp-parser-dev gnutls-bin
# 0.11.8版本后如果系统也为Debian8可能需要
apt-get install -t jessie-backports libgeoip-dev
# 如果为Debian9则直接
apt-get install libgeoip-dev
# ocserv 0.12.0开始需要添加一个新的依赖(该依赖在0.12.0以前为可选),不然预编译的时候会出警告告诉你worker进程无法独立运行.而如果忽略该警告的话安装后无法使用Anyconnect连接
apt-get install libseccomp-dev
ocserv编译(目前最新版):
wget https://gitlab.com/openconnect/ocserv/-/archive/1.1.2/ocserv-1.1.2.tar.gz
tar Jxvf ocserv-1.1.2.tar.xz
cd ocserv-1.1.2
./configure --prefix=/usr --sysconfdir=/etc
make && make install

在预编译前如果需要ocserv支持更多的路由表需要编辑src/vpn.h(新版本以后已经不需要了):

#define DEFAULT_CONFIG_ENTRIES 200 // 默认96,iOS Anyconnect客户端最多支持到200条路由表
配置证书:
CA模板,创建ca.tmpl,按需填写,这里的cn和organization可以随便填。
cn = "Your CA name"
organization = "Your fancy name"
serial = 1
expiration_days = 3650
ca
signing_key
cert_signing_key
crl_signing_key


生成CA密钥:

certtool --generate-privkey --outfile ca-key.pem


生成CA证书:

certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem
同理,我们用CA签名,生成服务器证书。先创建server.tmpl模板。这里的cn项必须对应你服务器的hostname或公网IP,建议用公网ip,否则AnyConnect客户端将无法正确导入证书。
cn = "服务器的公网IP"
organization = "Your fancy name"
expiration_days = 3650
signing_key
encryption_key
tls_www_server


生成Server密钥:

certtool --generate-privkey --outfile server-key.pem

生成Server证书:

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

将CA,Server证书与密钥复制到以下文件夹:
cp ca-cert.pem /etc/ssl/certs/my-ca-cert.pem
cp server-cert.pem /etc/ssl/certs/my-server-cert.pem
cp server-key.pem /etc/ssl/private/my-server-key.pem

生成证书认证需要的客户端证书:

######创建user.tmpl

cn = "some random name"
unit = "some random unit"
expiration_days = 365
signing_key
tls_www_client


生成User密钥:

certtool --generate-privkey --outfile user-key.pem


生成User证书:

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
openssl pkcs12 -export -inkey user-key.pem -in user-cert.pem -certfile ca-cert.pem -out user.p12

将生成的客户端证书拷贝到可以在线下载的地址或者其他你可以导入到客户端的地方,比如我直接放到nginx的默认目录下以方便直接下载

cp user.p12 /var/www/html
ocserv配置文件:

配置文件放置在/etc/ocserv/ocserv.conf 以下只保留重要内容

auth = "certificate"

tcp-port = 443 #端口可自定义,如果ISP对udp限制较高可尝试注释掉udp端口
udp-port = 443

# Keepalive in seconds
keepalive = 32400

# MTU discovery (DPD must be enabled)
try-mtu-discovery = true

cookie-timeout = 86400

mobile-dpd = 1800

server-cert = /etc/ssl/certs/my-server-cert.pem
server-key = /etc/ssl/private/my-server-key.pem
ca-cert = /etc/ssl/certs/my-ca-cert.pem

cert-user-oid = 2.5.4.3

dns = 8.8.8.8

网络:
iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE # 如果是ovz的服务器网卡应该为venet0
iptables -I INPUT -p tcp --dport 443 -j ACCEPT # 端口应与ocserv配置中配置的端口对应
iptables -I INPUT -p udp --dport 443 -j ACCEPT

现在直接使用:

ocserv

就可以启用服务,需要查看日志的话可以使用:

ocserv -f -d 1

在iOS端安装Anyconnect,导入证书就可以了。

from https://moonagic.com/setup-ocserv-on-debian/

-------------------------------------------


在iphone上使用OpenConnect SSL VPN翻墙

我都没有越狱,7.1 发布后更是没有机会去越狱了。
幸福的是 AnyConnect 改变了我窘迫的现状。
  1. 不会断线
  2. 可以给客户端下发走 VPN 的路由表
  3. 稳定
So,我们来聊一聊如何通过 Ocserv 在 Ubuntu 13.10 搭建你的 AnyConnect。
这里不选择 12.04 的原因是他的包比较旧,需要你很折腾才能编译 Ocserv,另外 14.04 已经 On the way 了。
PS.如果想要在 Ubuntu 12.04 上安装,那么需要参考这文章安装 NettleGnutls

安装 Ocserv

下载 Ocserv 0.3.2
wget ftp://ftp.infradead.org/pub/ocserv/ocserv-0.3.2.tar.xz
tar Jxvf ocserv-0.3.2.tar.xz
cd ocserv-0.3.2

安装依赖:
apt-get install build-essential libwrap0-dev libpam0g-dev libdbus-1-dev 
libreadline-dev libnl-route-3-dev libprotobuf-c0-dev libpcl1-dev
 libopts25-dev autogen libgnutls28 libgnutls28-dev  libseccomp-dev 
apt-get install gnutls-bin -y (注意:一定不要忘了安装gnutls-bin,否则你运行certtool时,会遇到提示:command not found.)
编译
./configure --prefix=/usr  
make 
make install

生成证书

这里你需要先仔细阅读官方的文档 简单的来说,如下几步
创建工作文件夹
mkdir CA
cd CA
生成 CA 证书
certtool --generate-privkey --outfile ca-key.pem
vim ca.tmpl

#输入一下内容

cn = "VPN CA"
organization = "Big Corp"
serial = 1
expiration_days = 3650
ca
signing_key
cert_signing_key
crl_signing_key

#保存退出文件编辑

certtool --generate-self-signed --load-privkey ca-key.pem \
--template ca.tmpl --outfile ca-cert.pem
生成本地服务器证书
certtool --generate-privkey --outfile server-key.pem
nano  server.tmpl

# 输入以下内容
cn = "服务器的公网ip"
organization = "MyCompany"
serial = 2
expiration_days = 3650
encryption_key
signing_key
tls_www_server

#保存退出文件编辑

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
生成之后
server-cert.pem 放到/etc/ssl/certs server-key.pem 放到/etc/ssl/private

配置文件

工作目录是最初解压出来的 ocserv-0.3.2
sudo mkdir /etc/ocserv && \ 
sudo cp doc/sample.config /etc/ocserv/ && \
 sudo mv /etc/ocserv/sample.conf /etc/ocserv/ocserv.conf
编辑配置文件
vim /etc/ocserv/ocserv.conf
修改如下
auth = "plain[/etc/ocserv/ocpasswd]"
#ocserv支持多种认证方式,这是自带的密码认证,使用ocpasswd创建密码文件
#ocserv还支持证书认证,可以通过Pluggable Authentication Modules (PAM)使用radius等认证方式

#证书路径
server-cert = /etc/ssl/certs/server-cert.pem
server-key = /etc/ssl/private/server-key.pem

#同一个用户最多同时登陆数
max-same-clients = 10 

#运行组
run-as-group = nogroup

#分配给VPN客户端的IP段
ipv4-network = 10.10.0.0

#DNS
dns = 8.8.8.8
dns = 8.8.4.4

#注释掉route的字段,这样表示所有流量都通过 VPN 发送
#route = 192.168.1.0/255.255.255.0
#route = 192.168.5.0/255.255.255.0

创建用户

sudo ocpasswd -c /etc/ocserv/ocpasswd username
#username为你要添加的用户名

修改系统配置,允许转发

vim /etc/sysctl.conf
#修改这行
net.ipv4.ip_forward = 1
#保存退出
sysctl -p
修改 iptables 规则 你可以参考 Linode 的文章 来配置 iptables

*filter

#  Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT -d 127.0.0.0/8 -j REJECT

#  Accept all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#  Allow all outbound traffic - you can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT

#  Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL).
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
#  Allow SSH connections
#
#  The -dport number should be the same port number you set in sshd_config
#
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

#  Allow ping
-A INPUT -p icmp -j ACCEPT

#  Log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

-A INPUT -j DROP

COMMIT
特别需要主意的是,一定不要存在这样的一句话 不然能连上也是哪里都不能访问……
-A FORWARD -j DROP #不要存在这句
在你的 /etc/rc.local 的exit 前面加上这句 来开启 NAT
iptables -t nat -A POSTROUTING -j MASQUERADE
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu 

Debug

现在我们可以开启服务器试试了
sudo ocserv -c /etc/ocserv/ocserv.conf -f -d 1
如果你出现了这样的错误
DBUS connection error (Connection ":1.225" is not allowed to own the service "org.infradead.ocserv" due to security policies in the configuration file)Cannot create command handler
那么你需要这样处理
sudo cp ocserv-0.3.2/doc/dbus/org.infradead.ocserv.conf /etc/dbus-1/system.d/
Thanks to sskaje
拿起你的 iPhone,下载思科的 AnyConnect 客户端
然后输入你的服务器地址,以及你的用户名密码。 出现问题可以看debug的返回信息,如果信息不详细,可以把 1 改成 10
另外也可以通过 ifconfig 来看下你的设备名,我的是 vpns3,然后通过 tcpdump 抓包来看下数据
sudo tcpdump -i vpns3 -vv

配置启动文件

现在我们需要一个脚本来管理 Ocserv
你可以在这里找到, Thanks to Tony
把这个文件复制到 /etc/init.d/ocserv
然后
sudo chmod 755 /etc/init.d/ocserv
sudo update-rc.d ocserv defaults
就可以开机启动了。
你也可以通过
/etc/init.d/ocserv start
这样子来管理。

下发路由

我想这个功能是最激动人心的,因为我们手机如果长期连接,那么肯定是某些服务走 VPN,而国内的网站可以走手机自己的网络体验最好。
但是这里的一个问题是,AnyConnect 有下发路由表的 64 条数限制。
所以我们只能保证下某几个常用的服务是可用的,比如 Google Facebook 以及 Twitter
编辑配置文件
sudo vim /etc/ocserv/ocserv.conf
找到 route = 的字段
你可以使用我的路由表,把这些复制到里面。 保存后重新启动 VPN 服务器,就可以了。
/etc/init.d/ocserv restart
另外这里也有一个我写的 ruby 脚本,用来转换 72.52.99.0/24 > 72.52.99.0/255.255.255.0 这样格式的路由 CIDR to Wildcard mask。
这样你可以自行通过 nslookup
nslookup www.google.com
这样来获取服务器的A地址,然后转换成我们需要的格式。

from http://blog.zhowkev.in/2014/03/20/anyconnect-iphone/
--------------------------------------------------

 OpenConnect on Ubuntu vps

 OpenConnect is an open source implementation of Cisco’s AnyConnect SSL VPN which is natively supported by iOS(You can create profile with Apple Configurator).

OpenConnect VPN Server can be found on http://www.infradead.org/ocserv/ and downloaded from ftp://ftp.infradead.org/pub/ocserv/, manual http://www.infradead.org/ocserv/manual.html

Let’s build it on Ubuntu 13.10!
  
wget ftp://ftp.infradead.org/pub/ocserv/ocserv-0.3.0.tar.xz
tar Jxvf ocserv-0.3.0.tar.xz
cd ocserv-0.3.0

Dependencies:  
apt-get install libwrap0-dev libpam0g-dev libdbus-1-dev libreadline-dev \
  libnl-route-3-dev libprotobuf-c0-dev libpcl1-dev libopts25-dev \
  autogen libgnutls28 libgnutls28-dev  libseccomp-dev
apt-get install gnutls-bin -y (注意:一定不要忘了安装gnutls-bin,否则你运行certtool时,会遇到提示:command not found.)

OpenConnect requires GNUTLS 3.0+ which is libgnutls28 in Ubuntu;
libhttp-parser-dev is offered in Ubuntu Trusty(14.04)

Let’s configure it as simple as possible like:
./configure
...
configure:
Summary of build options:
  version:              0.3.0
  Host type:            x86_64-unknown-linux-gnu
  Install prefix:       /opt/ocserv
  Compiler:             gcc
  CFlags:               -g -O2 -Wall

  PAM auth backend:     yes
  TCP wrappers:         yes
  systemd:              no
  (socket activation)
  dbus:                 yes
  readline:             yes
  libnl3:               yes
  local protobuf-c:     no
  local PCL library:    no
  local libopts:        no
  local http-parser:    yes

Optional programs:
  occtl:                yes

configure:

Experimental options:
  seccomp:              no
  Anyconnect compat:    yes

Then make:
   
root@sskaje:~/build/ocserv-0.3.0# make
make  all-recursive
make[1]: Entering directory `/root/build/ocserv-0.3.0'
Making all in gl
make[2]: Entering directory `/root/build/ocserv-0.3.0/gl'
make  all-recursive
make[3]: Entering directory `/root/build/ocserv-0.3.0/gl'
make[4]: Entering directory `/root/build/ocserv-0.3.0/gl'
make[4]: Nothing to be done for `all-am'.
make[4]: Leaving directory `/root/build/ocserv-0.3.0/gl'
make[3]: Leaving directory `/root/build/ocserv-0.3.0/gl'
make[2]: Leaving directory `/root/build/ocserv-0.3.0/gl'
Making all in src
make[2]: Entering directory `/root/build/ocserv-0.3.0/src'
make  all-recursive
make[3]: Entering directory `/root/build/ocserv-0.3.0/src'
make[4]: Entering directory `/root/build/ocserv-0.3.0/src'
  CC       ocserv-args.o
In file included from ocserv-args.c:43:0:
ocserv-args.h:61:3: error: #error option template version mismatches autoopts/options.h header
# error option template version mismatches autoopts/options.h header
   ^
ocserv-args.h:62:3: error: unknown type name ‘Choke’
   Choke Me.
   ^
ocserv-args.h:62:11: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token
   Choke Me.
           ^
ocserv-args.h:78:3: warning: data definition has no type or storage class [enabled by default]
} teOptIndex;
   ^
ocserv-args.h:78:3: warning: type defaults to ‘int’ in declaration of ‘teOptIndex’ [-Wimplicit-int]
ocserv-args.c:303:29: error: ‘INDEX_OPT_VERSION’ undeclared here (not in a function)
   {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
                             ^
ocserv-args.c:317:29: error: ‘INDEX_OPT_HELP’ undeclared here (not in a function)
   {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
                             ^
ocserv-args.c:329:29: error: ‘INDEX_OPT_MORE_HELP’ undeclared here (not in a function)
   {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
                             ^
ocserv-args.c:490:5: warning: suggest parentheses around arithmetic in operand of ‘|’ [-Wparentheses]
     + OPTPROC_MISUSE ),
     ^
make[4]: *** [ocserv-args.o] Error 1
make[4]: Leaving directory `/root/build/ocserv-0.3.0/src'
make[3]: *** [all-recursive] Error 1
make[3]: Leaving directory `/root/build/ocserv-0.3.0/src'
make[2]: *** [all] Error 2
make[2]: Leaving directory `/root/build/ocserv-0.3.0/src'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/root/build/ocserv-0.3.0'
make: *** [all] Error 2

To solve this:  
./configure --prefix=/usr --enable-local-libopts --enable-libopts-install
make
make install

Create config folder and copy sample config:
mkdir /opt/ocserv/etc/
cp doc/sample.* /opt/ocserv/etc/
  
cd /opt/ocserv/;
cp /etc/ipsec.d/crls/crl.pem etc/
cp /etc/ipsec.d/cacerts/cacert.pem etc/

config file like…(I’ll upload it later)
Add User(Plain):
  
cd /opt/ocserv/;
./bin/ocpasswd -c etc/passwd -g GROUPNAME sskaje

Start & Stop:
  
root@sskaje:/opt/ocserv# cd /opt/ocserv/;
root@sskaje:/opt/ocserv# ./sbin/ocserv -c etc/config
root@sskaje:/opt/ocserv# ps -ef|grep ocserv
root     16583     1  0 14:38 ?        00:00:00 ./sbin/ocserv -c etc/config
root     16584 16583  0 14:38 ?        00:00:00 ./sbin/ocserv -c etc/config
root     16586 19163  0 14:38 pts/0    00:00:00 grep --color=auto ocserv
root@sskaje:/opt/ocserv# ./bin/occtl  stop now
Server scheduled to stop
root@sskaje:/opt/ocserv# ps -ef|grep ocserv
root     16590 19163  0 14:38 pts/0    00:00:00 grep --color=auto ocserv

iOS Connect

This time, you need to have Cisco AnyConnect installed on your iDevice, Apple Configurator is not necessory.
I added a ‘0.0.0.0/0.0.0.0′ route but does not yet work for me.

Trouble Shooting

Debug foreground
  
root@sskaje:/opt/ocserv# ./sbin/ocserv -c etc/config  -d -f
listening (TCP) on 0.0.0.0:8443...
listening (TCP) on [::]:8443...
listening (UDP) on 0.0.0.0:8443...
listening (UDP) on [::]:8443...
ocserv[16335]: [main] initialized ocserv 0.3.0
ocserv[16336]: sec-mod initialized (socket: /var/run/ocserv-socket.16335)
DBUS connection error (Connection ":1.225" is not allowed to own the service "org.infradead.ocserv" due to security policies in the configuration file)Cannot create command handler.

If you see this error, you need to copy dbus config files to /etc:
cp /root/build/ocserv-0.3.0/doc/dbus/org.infradead.ocserv.conf /etc/dbus-1/system.d/

from https://sskaje.me/2014/02/openconnect-ubuntu/
----------------------------------------------------

 Install Ocserv on CentOS 6.5

Ocserv is a Cisco AnyConnect compatible server, it had been designed for OpenConnect, but the author made it Cisco AnyConnect compatible later.
In pre-iOS 7 era, Apple gave users an ability to trigger VPN as a global one, that means once you need to access the Internet, VPN could be connected automatically. After iOS 7 was released, Apple has disabled this feature, even though VPN still could be triggered by URL or destination, but solely by specific ones, not global any more.
Despite the compatible of Cisco AnyConnect, ocserv is not certified by Cisco and there are some known issues like mismatch MTU.
To install ocserv on CentOS 6, you must install some the latest version softwares including GnuTLS, Nettle and LibNL.

Preparation

First of all, install some RPM packages that will be required afterward:
yum install autoconf automake gcc libtasn1-devel zlib zlib-devel trousers trousers-devel gmp-devel gmp xz texinfo libnl-devel libnl tcp_wrappers-libs tcp_wrappers-devel tcp_wrappers dbus dbus-devel ncurses-devel pam-devel readline-devel bison bison-devel flex gcc automake autoconf wget
Install Nettle:
wget http://www.lysator.liu.se/~nisse/archive/nettle-2.7.tar.gz
tar xvf nettle-2.7.tar.gz
cd nettle-2.7
./configure --prefix=/opt/
make && make install
cd ..

Install the latest GnuTLS, this version comes with a fix of security flaw:
wget ftp://ftp.gnutls.org/gcrypt/gnutls/v3.2/gnutls-3.2.12.tar.xz
tar Jxvf gnutls-3.2.12.tar.xz
cd gnutls-3.2.12
export LD_LIBRARY_PATH=/opt/lib/:/opt/lib64/
NETTLE_CFLAGS="-I/opt/include/" NETTLE_LIBS="-L/opt/lib64/ -lnettle" HOGWEED_CFLAGS="-I/opt/include" HOGWEED_LIBS="-L/opt/lib64/ -lhogweed" ./configure --prefix=/opt/
make && make install
cd ..

Install the Latest LibNL:
wget http://www.carisma.slowglass.com/~tgr/libnl/files/libnl-3.2.24.tar.gz
tar xvf libnl-3.2.24.tar.gz
cd libnl-3.2.24
./configure --prefix=/opt/
make && make install
cd ..

Install Ocserv

The latest version of ocserv is 0.8.0[1], if you want a git version, you might need to compile a recent version of automake and autoconf.

wget ftp://ftp.infradead.org/pub/ocserv/ocserv-0.8.0.tar.xz
tar Jxvf ocserv-0.8.0.tar.xz
cd ocserv-0.8.0

export LIBGNUTLS_CFLAGS="-I/usr/include/" LIBGNUTLS_LIBS="-L/usr/lib64/ -lgnutls" LIBNL3_CFLAGS="-I/usr/include" LIBNL3_LIBS='-L/usr/lib64/ -lnl-3 -lnl-route-3'
./configure --prefix=/usr
make 
make install

You may need to:
export LD_LIBRARY_PATH=/usr/lib/:/usr/lib64/


every time you run ocserv as the libraries it linked with are in /opt/ rather than a standard path.
I found DTLS (connecting through UDP) may cause a MTU issue, the value on server side is lower than client side, this may stop some sites or images from loading correctly. So I use custom-headers to lock the MTU on client side to 1200. [2]
custom-header = "X-DTLS-MTU: 1200"
custom-header = "X-CSTP-MTU: 1200"

If you need to route all traffic like I do, comment all lines begins with ‘route’. You may also want some of traffic to remain un-routed, then you could add another customer header
custom-header = "X-CSTP-Split-Exclude: 8.8.8.8/255.255.255.0"
And, comment the following line, I found if I leave it uncommented, Cisco AnyConnect on iOS will not connect properly.
#cisco-client-compat = true
Last, remember to set up IPv4 forward on your CentOS – edit /etc/sysctl.conf
net.ipv4.ip_forward = 1
and
sysctl -p
iptables -t nat -A POSTROUTING -j MASQUERADE

That’s it. Hope you enjoy the AnyConnect on your iPhone or Android devices.
Here is a sample configuration file.
# User authentication method. Could be set multiple times and in that case
# all should succeed.
# Options: certificate, pam.
#auth = "certificate"
auth = "plain[/etc/ocserv/passwd]"
#auth = "pam"

# A banner to be displayed on clients
#banner = "Welcome"
# Use listen-host to limit to specific IPs or to the IPs of a provided hostname.
#listen-host = [IP|HOSTNAME]
# Limit the number of clients. Unset or set to zero for unlimited.
max-clients = 1024
# Limit the number of client connections to one every X milliseconds
# (X is the provided value). Set to zero for no limit.
#rate-limit-ms = 100
# Limit the number of identical clients (i.e., users connecting multiple times)
# Unset or set to zero for unlimited.
max-same-clients = 0
# TCP and UDP port number
tcp-port = 443
udp-port = 443
# Keepalive in seconds
keepalive = 32400
# Dead peer detection in seconds
dpd = 90
# MTU discovery (DPD must be enabled)
try-mtu-discovery = false
# The key and the certificates of the server
# The key may be a file, or any URL supported by GnuTLS (e.g.,
# tpmkey:uuid=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx;storage=user
# or pkcs11:object=my-vpn-key;object-type=private)
#
# There may be multiple certificate and key pairs and each key
# should correspond to the preceding certificate.
server-cert = /path/to/crt_file
server-key = /path/to/key_file
# Diffie-Hellman parameters. Only needed if you require support
# for the DHE ciphersuites (by default this server supports ECDHE).
# Can be generated using:
# certtool --generate-dh-params --outfile /path/to/dh.pem
#dh-params = /path/to/dh.pem
# If you have a certificate from a CA that provides an OCSP
# service you may provide a fresh OCSP status response within
# the TLS handshake. That will prevent the client from connecting
# independently on the OCSP server.
# You can update this response periodically using:
# ocsptool --ask --load-cert=your_cert --load-issuer=your_ca --outfile response
# Make sure that you replace the following file in an atomic way.
#ocsp-response = /path/to/ocsp.der
# In case PKCS #11 or TPM keys are used the PINs should be available
# in files. The srk-pin-file is applicable to TPM keys only (It's the storage
# root key).
#pin-file = /path/to/pin.txt
#srk-pin-file = /path/to/srkpin.txt
# The Certificate Authority that will be used
# to verify clients if certificate authentication
# is set.
#ca-cert = ./alphassl.crt
# The object identifier that will be used to read the user ID in the client certificate.
# The object identifier should be part of the certificate's DN
# Useful OIDs are:
# CN = 2.5.4.3, UID = 0.9.2342.19200300.100.1.1
#cert-user-oid = 0.9.2342.19200300.100.1.1
# The object identifier that will be used to read the user group in the client
# certificate. The object identifier should be part of the certificate's DN
# Useful OIDs are:
# OU (organizational unit) = 2.5.4.11
#cert-group-oid = 2.5.4.11
# A revocation list of ca-cert is set
#crl = /path/to/crl.pem
# GnuTLS priority string
tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT"
# To enforce perfect forward secrecy (PFS) on the main channel.
#tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA"
# The time (in seconds) that a client is allowed to stay connected prior
# to authentication
auth-timeout = 40
# The time (in seconds) that a client is not allowed to reconnect after
# a failed authentication attempt.
#min-reauth-time = 2
# Cookie validity time (in seconds)
# Once a client is authenticated he's provided a cookie with
# which he can reconnect. This option sets the maximum lifetime
# of that cookie.
cookie-timeout = 86400000
# ReKey time (in seconds)
# ocserv will ask the client to refresh keys periodically once
# this amount of seconds is elapsed. Set to zero to disable.
rekey-time = 86400000
# Script to call when a client connects and obtains an IP
# Parameters are passed on the environment.
# REASON, USERNAME, GROUPNAME, HOSTNAME (the hostname selected by client),
# DEVICE, IP_REAL (the real IP of the client), IP_LOCAL (the local IP
# in the P-t-P connection), IP_REMOTE (the VPN IP of the client). REASON
# may be "connect" or "disconnect".
#connect-script = /usr/bin/myscript
#disconnect-script = /usr/bin/myscript
# UTMP
use-utmp = true
# D-BUS usage. If disabled occtl tool cannot be used. If enabled
# then ocserv must have access to register org.infradead.ocserv
# D-BUS service. See doc/dbus/org.infradead.ocserv.conf
use-dbus = false
# PID file. It can be overriden in the command line.
pid-file = /var/run/ocserv.pid
# The default server directory. Does not require any devices present.
#chroot-dir = /path/to/chroot
# socket file used for IPC, will be appended with .PID
# It must be accessible within the chroot environment (if any)
socket-file = /var/run/ocserv-socket
# The user the worker processes will be run as. It should be
# unique (no other services run as this user).
run-as-user = nobody
run-as-group = daemon
# Set the protocol-defined priority (SO_PRIORITY) for packets to
# be sent. That is a number from 0 to 6 with 0 being the lowest
# priority. Alternatively this can be used to set the IP Type-
# Of-Service, by setting it to a hexadecimal number (e.g., 0x20).
# This can be set per user/group or globally.
#net-priority = 3
# Set the VPN worker process into a specific cgroup. This is Linux
# specific and can be set per user/group or globally.
#cgroup = "cpuset,cpu:test"
# Network settings
device = vpns
# The default domain to be advertised
#default-domain = example.com
ipv4-network = 10.18.240.0
ipv4-netmask = 255.255.255.0
# dns = 192.168.2.1
#dns = 192.168.1.1
#dns = fe80::1
dns = 203.80.96.10
dns = 8.8.8.8
dns = 8.8.4.4
# The NBNS server (if any)
#nbns = 192.168.2.3
# The IPv6 subnet prefix
#ipv6-network = fe80::
#ipv6-prefix = 16
# The domains over which the provided DNS should be used. Use
# multiple lines for multiple domains.
#split-dns = example.com
# Prior to leasing any IP from the pool ping it to verify that
# it is not in use by another (unrelated to this server) host.
ping-leases = false
# Leave empty to assign the default MTU of the device
# mtu =
# Unset to enable bandwidth restrictions (in bytes/sec). The
# setting here is global, but can also be set per user or per group.
#rx-data-per-sec = 40960
#tx-data-per-sec = 40960
# The number of packets (of MTU size) that are available in
# the output buffer. The default is low to improve latency.
# Setting it higher will improve throughput.
output-buffer = 10
#route = 192.168.1.0/255.255.255.0
#route = 192.168.5.0/255.255.255.0
# Configuration files that will be applied per user connection or
# per group. Each file name on these directories must match the username
# or the groupname.
# The options allowed in the configuration files are dns, nbns,
# ipv?-network, ipv?-netmask, ipv6-prefix, rx/tx-per-sec, iroute and route.
#
# Note that the 'iroute' option allows to add routes on the server
# based on a user or group. The syntax depends on the input accepted
# by the commands route-add-cmd and route-del-cmd (see below).
#config-per-user = /etc/ocserv/config-per-user/
#config-per-group = /etc/ocserv/config-per-group/
# The system command to use to setup a route. %R will be replaced with the
# route/mask and %D with the (tun) device.
#
# The following example is from linux systems. %R should be something
# like 192.168.2.0/24 (so iroute in this system has different syntax than route)
route-add-cmd = "ip route add %R dev %D"
route-del-cmd = "ip route delete %R dev %D"
#
# The following options are for (experimental) AnyConnect client
# compatibility.
# Client profile xml. A sample file exists in doc/profile.xml.
# This file must be accessible from inside the worker's chroot.
# The profile is ignored by the openconnect client.
#user-profile = profile.xml
# Unless set to false it is required for clients to present their
# certificate even if they are authenticating via a previously granted
# cookie. Legacy CISCO clients do not do that, and thus this option
# should be set for them.
cisco-client-compat = true
#Advanced options
# Option to allow sending arbitrary custom headers to the client after
# authentication and prior to VPN tunnel establishment.
#custom-header = "X-My-Header: hi there"
custom-header = "X-DTLS-MTU: 1200"
custom-header = "X-CSTP-MTU: 1200"

Update:

[1] 23/Jun/2014 – Updated to 0.8.0
[2] Or you can let iptables determine a correct MTU value instead of a fixed one:
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

路由表配置参考
https://github.com/rankjie/anyconnect-gfw-list/blob/master/gfwiplist.txt


关于使用证书免密码登录
网上大多是在说怎么用gnutls里面的certtool通过模板生成证书,而且都不怎么关注具体鉴权问题
配置项是cert-user-oid  这个oid表明了ocserv应该从客户端证书的哪个地方取用户名,在多用户的时候或者需要做管理的时候还是需要分开用户名,而不是一份客户端证书大家共用.


下面有一个脚本说明了openssl如何生成客户端证书
https://gist.github.com/LimeQM/db93c17cc54e9b13e33e#file-createclientcert-sh

--------------------------------------------------------------------------------

OCSERV 0.8.5 使用


注1:本文不包含ocserv的编译、安装,请自行研习
*注2:本文将包含ocserv的证书认证配置,不包含pam (radius)认证
*注3:本文将包含win,mac 端的使用,移动端相对简单,不做介绍

ocserv是OpenConnect SERVer的缩写,基本上就是cisco anyyconnect的开源兼容服务器软件,好处就是这个软件使用的是SSL VPN方式,通常会用DTLS这一层,支持服务器端推送32条路由,实现国内国外按需区分路由;同时各种客户端会长连接方式,一直后台待命,省时省电。我就不废话了。

我的配置是采用了全证书的方式进行,因此不需要用户名密码,如果您要对客户端进行限制,计时方面可以采用证书有效时间;流量限制方面可以使用iptables针对IP进行限制;同时在线人数上如果是多台服务器的话,相互间无法限制(cookie/session分布于不同服务器),如果仅一台服务器话就可以在配置文件搞定。我的完全配置如下,如果你要复制配置文件可以到这里

#第一行用以指定认证方式,我是证书
auth = "certificate"
#Added @05-10-2014 #加入这个后就可以使用occtl了 #occtl reload && occtl stop now use-occtl = true occtl-socket-file = /var/run/occtl.socket
# seccomp default : true #关闭这个可以提高性能,牺牲一丁点安全,更可以避免无法启动的情况(遇到过的都知道那痛苦) use-seccomp = false # listen-host = 0.0.0.0
 #最大客户端数量,根据你的服务器IP地址分配多少以及性能设置,自用的话不必很大 max-clients = 36
 #这个看英文就知道意思了,你可以加以限制 max-same-clients = 4 tcp-port = 443 udp-port = 443 keepalive = 32400 dpd = 60 mobile-dpd = 1800 #故意为空 mobile-idle-timeout = deny-roaming = false #这个MTU选项一定要打开 try-mtu-discovery = true server-cert = server-cert.pem server-key = server-key.pem ca-cert = ca-cert.pem tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT" auth-timeout = 40 rekey-time = 172800 rekey-method = ssl use-utmp = true pid-file = /var/run/ocserv.pid socket-file = /var/run/ocserv-socket
 #下面这个profile是预置用户文件,可以实现按需或者多个VPN网址自动陈列配置 user-profile = /usr/local/etc/ocserv/profile.xml run-as-user = nobody run-as-group = nogroup
 #这个优先级,我设定为5,一共是0-6优先级,可以在网络传输时优先传递,也支持TOS方式的16进制 net-priority = 5 cgroup = "cpuset,cpu:test"
 #设备名称,你可以自己写一个名字 device = CiscoSSL
 #这个是关于无用IP地址如何回收的 predictable-ips = true default-domain = 你的默认域名(与你的证书里的一定要一样,否则奇葩bug) ipv4-network = 192.168.100.1 ipv4-netmask = 255.255.255.0 dns = 208.67.222.222 ping-leases = false cisco-client-compat = true #这下面是以route = 开头的自定义路由,以实现路由自动区分我省掉了,同样可以在github上下载我慢慢调整好的路由。
https://gist.github.com/bao3/bc717ec2294257209c30
在启动ocserv之前,我们需要有自己的证书以及发给客户的证书,这将包括根证书系列、服务器证书系列、客户证书系列,既然已经安装了ocserv那就一定安装了gnutls的certtool则生成证书就可以用我的模板来进行: https://gist.github.com/bao3/e43f960395d0737664bc 请看清以上链接中的4个文件,一个是ca.tmpl模板,用以生成根证书;一个是server.tmpl用以生成服务器证书;另一个是client.tmpl用以生成客户端证书的模板;最重要的是 cert-client.sh,这是一个脚本,以后你的朋友如果跟你要VPN服务器用,你就可以直接 ./cert-client.sh friend,这样就全自动生成你朋友的一个单独证书,并且打包成 *.p12格式,并且会等待让你输入证书的密码,这个密码是必须的,否则在iOS上是无法导入的,切记。 请分别下载以上4个文件,并将其中的@abc.org改成你自己的网址,然后就可以自行签发了: 首先生成CA根证书:
certtool --generate-privkey --outfile ca-key.pem 
certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem 
接着生成服务器证书:
certtool --generate-privkey --outfile server-key.pem  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
接下来是给客户签发证书,前面的脚本就有作用了,以后你会经常使用这个脚本,极其简单:
./cert-client.sh 你想要指定的文件名称
然后你输入一个密码后,就会生成三个文件 *-key.pem, *-cert.pem, *.cert.p12,大多数平台都只需要最后一个文件 ,同样在其他地方导入这个文件时,也需要输入密码(你在生成时输入的那个)。 证书我默认是10年的有效期,基本上如果我能力足够的话我会一直持续提供服务,你自己可以定义一个短的,至于要取消一个证书,就需要用到 revoke,这个你参考一下就可以了:
$ cat << _EOF_ >crl.tmpl crl_next_update = 9999 crl_number = 1 _EOF_ $ cat user-cert.pem >>revoked.pem $ certtool --generate-crl --load-ca-privkey ca-key.pem --load-ca-certificate ca.pem --load-certificate revoked.pem --template crl.tmpl --outfile crl.pem
接下来就是如何在客户端使用了,本来这东西要使用是非常简单地,可是麻烦是在于客户端思科是不开放的!不过好心的我还是会放出下载的,例如: mac os x http://ftp.rrzn.uni-hannover.de/pub/local/anyconnect/anyconnect-macosx-i386-3.1.05182-k9.dmg windows https://ftp.rush.edu/users/vpn-client/anyconnect-win-3.1.05182-pre-deploy-k9.msi Linux可以使用openconnect。 win下证书导入 如果是win8,直接以管理员身份打开 *.cert.p12,导入;如果导入后发现不能用,那就跟win7一样来操作 1 打开 mmc,然后按ctrl+M 出现功能单元选择,找到证书,然后点添加,就会看到下图
然后在windows上就可以直接连接了。没啥特别的。
from  http://bao3.blogspot.com/2014/10/ocserv-085.html
----------------------------------------------------------
本文的主要目的是介绍基于证书认证的免登录免密码的 Anyconnect VPN 的架构搭建方式。ocserv 服务器需要三个服务证书,包含 CA 根证书、CA 发布的吊销凭证和服务器的 server.crt 域名证书。

各个证书之间的关系脉络 

这一部分是针对不了解 ssl 证书的读者的,如果你知道这是什么就大方的跳过吧。

Server.crt

服务器证书是用来保证互联网数据传输的安全,同时提供服务器身份的凭证。我们最常接触到的就是 https 网站,通过可信(公认)的第三方对服务器的域名使用权进行公证,高级的服务器证书同时还可以认证域名所有者的身份以此来防止钓鱼网站的出现。如果你想知道更多的内容就维基百科一下吧。
我们要使用到的服务器证书可以在 StartSSL 这一类的机构申请,也可以自签 CA 后再签发。我已经拥有泛域名证书,所以在搭建服务的时候可以直接使用该证书,以保证在任意端都信任服务。
如果不想自行购买证书也可以自行签发,但是需要在手机中导入自行生成的根证书。只是个人使用的情况下倒是没有什么问题,但是要共享给他人使用则需要他人也要导入根证书,这一点对于他人来说是非常危险和麻烦的。
吐槽一下,像 12306 这么大的网站却自行签发 CA 证书并强迫用户买票的时候导入其自行签发的根证书的做法实在是太奇葩了。对于普通用户来说可能不知道这意味着什么,对于了解一些的人来说想想都觉得恐怖。另外,他们自行签发的证书,其内容竟然还有 user:test 这样的字段,真不知道是外包给什么样的业余团队做的项目。

CA 根证书 

服务器证书是服务器的身份凭证,而 CA 根证书是用来签发下属证书并验证其身份及有效性的。
我们所要搭建的服务建构,是不需要用户名和密码的,这就类似与我们平常接触到的网银 U 盾,拥有极高的便利性和安全性。我们通常的做法是自行签发根证书,并通过该根证书签发用户证书,以用户证书作为用户的身份凭证。所以 ocserv 服务需要加载该自签 CA 证书。

CRL 吊销凭证

CRL 吊销凭证是用来公布已经吊销的证书的信息,如果没有该证书,我们所签发的用户证书将永远有效,这在安全方面和管理方面也是个问题。

用户证书 

在签发好用户证书之后还需要将其变换为各个终端间通用的 PKCS12 格式,以保证在 Android 系统或 iOS 系统上都可以使用。

OpenSSL 自签 CA 并发行证书 

我发现网上的一些教程使用 certtool 这个工具,但是使用下来发现其依赖包太老旧了,如果要更新的话又要对系统做大手术,于是乎放弃了,何况现在 OpenSSL 已经几乎成为了标准工具,兼容性上会好一点。
具体自签 CA 建站一类的教程太多了,我只在这里记录下一些需要注意的东西。
另外,我也尝试过建立基于 ECC 加密的证书链,但是 ocserv 还没有支持,这个坑我已探过了。

自签 CA

  1. 准备工作
    cd $DIR
    mkdir -p ssl/CA
    cd ssl/CA
    mkdir newcerts
    mkdir private
    touch index.txt
    echo "01" > serial
    
  2. 生成 CA 的公钥密码对,这个最好复杂一点,至少需要 4096bit,8192bit 也不错。
    openssl genrsa -out private/cakey.pem 8192
    
  3. 自签 CA 证书,这里面需要使用 HASH 函数做认证,默认使用 SHA1,但是该函数太不安全了,Google 最近默认设定使用该函数的证书都不安全了!另外加上 -utf8 参数使其支持中文信息。
    openssl req -new -x509 -days 3652 -sha512 -utf8 -key private/cakey.pem -out cacert.pem
    
  4. 欣赏一下杰作:
    openssl req -noout -text -in cacert.pem
    
  5. 重新设定一下个人 CA 的配置
    cd ..
    cp /etc/ssl/openssl.cnf ./
    vmi openssl.cnf        #根据需求修改配置
    

使用自签 CA 签发的 server.crt(如果自己有证书就不用了)

  1. 生成 RSA 公钥密码对,这个简单一点也行,就 4096bit 吧!
    mkdri server
    cd server
    openssl genrsa -out server.key 4096
    
  2. 生成证书申请文件,这个是必须的步骤,不过到时候写一个脚本就简单了
    openssl req -new -sha512 -key -utf8 server.key -out server.csr
    
  3. CA 签名,对于浏览器来说,超过五年的证书就不会被信任,所以可以设定在五年以内,不过不知道 ocserv 会不会有同样的策略。 另外前面已经定制了 openssl.cnf 在上级目录中了,所以这一步就简单多了。
    openssl ca -config ../openssl.cnf -utf8 -in server.csr -out server.crt
    
  4. 把 server.crt 和server.key部署到服务器上愉快的玩耍吧!

使用自签 CA 签发用户证书 

这一步的内容其实和上面的服务器证书差不多,就不重复了,在这里上一点干货!
  1. 首先建立 clients 目录并进入
    mkdir ../clients
    cd ../clients
    
  2. 建立自动创建用户证书的脚本
    touch newClient
    chmod +x newClient
    
    #! /bin/bash
    #! /usr/bin/expect -f
    CFG="-config ../openssl.cnf"
    SUBJ="-subj /C=CN/O='QMZ Ltd'/CN='${1}'/emailAddress='${2}'"
    KEY_CMD="openssl genrsa -out ${1}.key 2048"
    REQ_CMD="openssl req -new ${CFG} -key $1.key -out $1.req ${SUBJ}"
    CRT_CMD="openssl ca ${CFG} -in ${1}.req -out ${1}.crt"
    P12_CMD="openssl pkcs12 -export -inkey ${1}.key -in ${1}.crt -name \"${1}'s Client Certification for QMZ\" -certfile /home/zqm/web/qmz_certification/ca/cacert.pem -out ${1}.p12"
    if [ ! -e "${1}.crt" ];then
    eval $KEY_CMD
    eval $REQ_CMD
    eval $CRT_CMD
    fi
    eval $P12_CMD
    ./sendFile $2 $1.p12
    rm $1.req
    view rawCreateClientCert.sh hosted with ❤ by GitHub
    # 通过这个脚本就可以自动建立用户证书,并打包成 pkcs12 格式。
    ./newClient USERNAME MAIL@ADDRESS.com
    
  3. 倒数第二句是通过 MailGun 自动发送到用户的地址,这是第二个干货!
    #!/bin/bash
    FILE=`basename $2`
    USER_NAME=`basename $FILE .pfx`
    API_KEY="${YOUR_API_KEy}"
    DOMAIN="${YOUR_DOMAIN}"
    USER="${YOUR_USERNAME} <no-reply@${DOMAIN}>"
    SUBJECT="${YOUR_SUBJECT}"
    HTML="<html><p>${USER_NAME},您好!</p><br /><p>您所收到的邮件是<a href=\"https://qmz.me\">QMZ.me</a>为您生成的证书文件,作为使用<a href=\"https://qmz.me\">QMZ.me</a>为您所提供的<b>部分服务</b>的身份凭证。</p><p><b>${FILE}</b>文件是我们为您生成的身份证书,用于您在使用我们的服务时,提供给我们身份凭据。</p><br /><p><i>请将上面的证书导入您的终端。</i></p><br /><br /><p><b>请不要回复此邮件,QMZ收不到任何该地址的邮件回复!</b><p></html>"
    ATTACHMENT="${2}"
    CMD="curl -s --user 'api:${API_KEY}'"
    CMD="${CMD} https://api.mailgun.net/v2/${DOMAIN}/messages"
    CMD="${CMD} -F from='${USER}'"
    CMD="${CMD} -F to='${1}'"
    CMD="${CMD} -F subject='${SUBJECT}'"
    CMD="${CMD} --form-string html='${HTML}'"
    CMD="${CMD} -F attachment=@${ATTACHMENT}"
    #echo $CMD
    eval $CMD
    把其中 ${YOUR_××××} 的内容和邮件内容修改为你的信息就可以使用了。
  4. 这样一来就搭建好了一个自动生成用户证书、打包成 pkcs12 格式、再发送到用户邮件的工具链了。
-----------------------------------------------------------------

在RASPBERRY PI 上搭建OCSERV VPN(操作系统建议选择debian8,因为
debian7上,有一些库文件默认是不存在的,而debian8上,无此问题)
(按此文,我安装成功,顺利翻墙)

  • Raspberry Pi 比较特殊点有些地方需要改进.
稍加修改,使用最新版本的ocserv-0.10.8,编译liblz4,开启Compression(lz4)
apt-get install -y build-essential pkg-config texinfo libhogweed2 libgmp3-dev gettext libxml2-dev libgeos++-dev libpq-dev libbz2-dev libreadline-dev libtool automake libgnutls28-dev libseccomp-dev libpam0g-dev libwrap0-dev libnl-nf-3-dev libhttp-parser-dev libdbus-1-dev libprotobuf-c0-dev libprotobuf-c0 libpcl1-dev libopts25-dev autogen
apt-get install gnutls-bin -y (注意:一定不要忘了安装gnutls-bin,否则你运行certtool时,会遇到提示:command not found.)
apt-get install unbound-anchor -y 
mkdir /etc/unbound 
unbound-anchor -a "/etc/unbound/root.key"
mkdir lz4
LZ4_VERSION=`curl -s "https://github.com/Cyan4973/lz4/releases/latest" | sed -n 's/^.*tag\/\(.*\)".*/\1/p'` 
curl -SL "https://github.com/Cyan4973/lz4/archive/$LZ4_VERSION.tar.gz" -o lz4.tar.gz
tar zxvf lz4.tar.gz -C lz4 --strip-components=1 
cd lz4 
make -j"$(nproc)" && make install
ln -s /usr/local/lib/liblz4.* /usr/lib/ 
cd .. 
wget ftp://ftp.infradead.org/pub/ocserv/ocserv-0.10.8.tar.xz 
tar Jxvf ocserv-0.10.8.tar.xz 
cd ocserv-0.10.8 
./configure 
make 
make install
  • 编译ocserv成功后,运行以下命令测试下是否安装成功:
  • ocserv -h
  • 附上一些配置文件:
ocserv.conf的内容:
#auth = "certificate"
auth = "plain[passwd=/opt/ocserv/etc/ocpasswd]"
enable-auth = certificate
max-clients = 1024
max-same-clients = 0
tcp-port = 4443
udp-port = 4443
keepalive = 32400
dpd = 120
mobile-dpd = 1800
try-mtu-discovery = true
compression = true
server-cert = /opt/ocserv/ca/server-cert.pem
server-key = /opt/ocserv/ca/server-key.pem
ca-cert = /opt/ocserv/ca/ca-cert.pem
cert-user-oid = 2.5.4.3
#listen-host-is-dydns = true

tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-VERS-SSL3.0"
auth-timeout = 40
min-reauth-time = 120
cookie-timeout = 300
deny-roaming = false
rekey-time = 172800
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 = daemon
device = vpns
output-buffer = 23000
# default-domain = example.com
ipv4-network = 10.0.2.0
ipv4-netmask = 255.255.255.0
dns = 8.8.8.8
dns = 8.8.4.4
ping-leases = false
cisco-client-compat = true

route = 10.20.30.0/255.255.255.0 #vpn服务器端内网的网段
no-route = 0.0.0.0/0.0.0.0 #默认其它流量不指向vpn,只当访问对端内网时指向vpn
no-route和router按实际需求添加。
ocserv-up.sh的内容:
!/bin/bash

#vars
OCSERV_CONFIG="/opt/ocserv/etc/config"

# turn on IP forwarding
#sysctl -w net.ipv6.conf.all.forwarding=1 > /dev/null 2>&1
sysctl -w net.ipv4.ip_forward=1 > /dev/null 2>&1

#get gateway and profiles
gw_intf_oc=`ip route show 0/0 | sort -k 7 | head -n 1 | sed -n 's/^default.* dev \([^ ]*\).*/\1/p'`
ocserv_tcpport=`sed -n 's/^tcp-.*=[ \t]*//p' $OCSERV_CONFIG`
ocserv_udpport=`sed -n 's/^udp-.*=[ \t]*//p' $OCSERV_CONFIG`
ocserv_ip4_work_mask=`sed -n 's/^ipv4-.*=[ \t]*//p' $OCSERV_CONFIG|sed 'N;s|\n|/|g'`

# turn on NAT over default gateway and VPN
if !(iptables-save -t nat | grep -q "$gw_intf_oc (ocserv)"); then
iptables -t nat -A POSTROUTING -s $ocserv_ip4_work_mask ! -d $ocserv_ip4_work_mask -m comment --comment "$gw_intf_oc (ocserv)" -j MASQUERADE
fi

if !(iptables-save -t filter | grep -q "$gw_intf_oc (ocserv2)"); then
iptables -A FORWARD -d $ocserv_ip4_work_mask -m comment --comment "$gw_intf_oc (ocserv2)" -j ACCEPT
fi

if !(iptables-save -t filter | grep -q "$gw_intf_oc (ocserv3)"); then
iptables -A INPUT -p tcp --dport $ocserv_tcpport -m comment --comment "$gw_intf_oc (ocserv3)" -j ACCEPT
fi

if [ "$ocserv_udpport" != "" ]; then
    if !(iptables-save -t filter | grep -q "$gw_intf_oc (ocserv4)"); then
        iptables -A INPUT -p udp --dport $ocserv_udpport -m comment --comment "$gw_intf_oc (ocserv4)" -j ACCEPT
    fi
fi

if !(iptables-save -t filter | grep -q "$gw_intf_oc (ocserv5)"); then
iptables -A FORWARD  -s $ocserv_ip4_work_mask -m state --state RELATED,ESTABLISHED -m comment --comment "$gw_intf_oc (ocserv5)" -j ACCEPT
fi

# turn on MSS fix
# MSS = MTU - TCP header - IP header
if !(iptables-save -t mangle | grep -q "$gw_intf_oc (ocserv6)"); then
iptables -t mangle -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment --comment "$gw_intf_oc (ocserv6)" -j TCPMSS --clamp-mss-to-pmtu
fi
/opt/ocserv/etc/ocserv-down.sh:

#del iptables

iptables-save | grep 'ocserv' | sed 's/^-A P/iptables -t nat -D P/' | sed 's/^-A FORWARD -p/iptables -t mangle -D FORWARD -p/' | sed 's/^-A/iptables -D/' | bash
/etc/init.d/ocserv的内容:
#!/bin/sh
### BEGIN INIT INFO
# Provides:          ocserv
# Required-Start:    $network $remote_fs $syslog
# Required-Stop:     $network $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: ocserv
# Description:       OpenConnect VPN server compatible with
#                    Cisco AnyConnect VPN.
### END INIT INFO

# Author: liyangyijie <liyangyijie@gmail.com>

# PATH should only include /usr/ if it runs after the mountnfs.sh script
PATH=/opt/ocserv/sbin:/opt/ocserv/bin:/sbin:/usr/sbin:/bin:/usr/bin
DESC=ocserv
NAME=ocserv
DAEMON=/opt/ocserv/sbin/ocserv
DAEMON_ARGS=""
CONFFILE="/opt/ocserv/etc/config"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
SERVER_UP="/opt/ocserv/etc/ocserv-up.sh"
SERVER_DOWN="/opt/ocserv/etc/ocserv-down.sh"

# Exit if the package is not installed
[ -x $DAEMON ] || exit 0

: ${USER:="root"}
: ${GROUP:="root"}

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

# Show details
VERBOSE="yes"

#
# Function that starts the daemon/service
#
do_start()
{
    # Add server up script
    [ -x ${SERVER_UP} ] && . ${SERVER_UP}

    # Take care of pidfile permissions
    mkdir /var/run/$NAME 2>/dev/null || true
    chown "$USER:$GROUP" /var/run/$NAME
    export LD_LIBRARY_PATH=/opt/local/lib

    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER:$GROUP --exec $DAEMON --test > /dev/null \
        || return 1
    start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER:$GROUP --exec $DAEMON -- \
        -c "$CONFFILE" $DAEMON_ARGS \
        || return 2
}

#
# Function that stops the daemon/service
#
do_stop()
{
    # Add server down script
    [ -x ${SERVER_DOWN} ] && . ${SERVER_DOWN}

    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred
    start-stop-daemon --stop --quiet --retry=KILL/5 --pidfile $PIDFILE --exec $DAEMON
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    # Wait for children to finish too if this is a daemon that forks
    # and if the daemon is only ever run from this initscript.
    # If the above conditions are not satisfied then add some other code
    # that waits for the process to drop all resources that could be
    # needed by services started subsequently.  A last resort is to
    # sleep for some time.
    start-stop-daemon --stop --quiet --oknodo --retry=KILL/5 --exec $DAEMON
    [ "$?" = 2 ] && return 2
    # Many daemons don't delete their pidfiles when they exit.
    rm -f $PIDFILE
    return "$RETVAL"
}


case "$1" in
    start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
        do_start
        case "$?" in
            0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
            2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
    ;;
    stop)
    [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
    do_stop
    case "$?" in
    0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
    debug)
        DAEMON_ARGS="-f -d 2"
        [ "$2" != "" ] && DAEMON_ARGS="-f -d $2"
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
        do_start
        case "$?" in
            0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
            2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
    ;;
    status)
        status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
    ;;
    restart|force-reload)
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
            0|1)
                do_start
                case "$?" in
                    0) log_end_msg 0 ;;
                    1) log_end_msg 1 ;; # Old process is still running
                    *) log_end_msg 1 ;; # Failed to start
                esac
            ;;
            *)
            # Failed to stop
            log_end_msg 1
            ;;
        esac
    ;;
    *)
    echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload|debug}" >&2
    exit 3
    ;;
esac
  • 开机启动服务:
update-rc.d ocserv defaults 99
  • 如果要使用证书认证,可以使用以下脚本一键生成,将生成的p12后缀文件在客户端导入即可
#!/bin/bash

AUTHOR="Maple"
VPN="Cisco SG for Maple"
DOMAIN="miao.hu"
CLIENT="user"

cd /opt/ocserv
mkdir ca
cd ca

cat << EOF > ca.tmpl
cn = "$VPN"
organization = "$AUTHOR"
serial = 1
expiration_days = 1000
ca
signing_key
cert_signing_key
crl_signing_key
EOF

cat << EOF > server.tmpl
cn = "服务器的公网IP"
organization = "$AUTHOR"
serial = 2
expiration_days = 1000
signing_key
encryption_key
tls_www_server
EOF

certtool --generate-privkey --outfile ca-key.pem
certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem
certtool --generate-privkey --outfile server-key.pem
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

cat << EOF > user.tmpl
cn = "$CLIENT"
serial = 1824
expiration_days = 1000
signing_key
tls_www_client
EOF

certtool --generate-privkey --outfile user-key.pem
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
openssl pkcs12 -export -clcerts -in user-cert.pem -inkey user-key.pem -out user.p12
  • 其它问题: 如果ocserv所安装的服务器采用wlan0连接外网的话,可能会出现一启用vpn网络就断开的情况,则需要编辑/etc/defaults/ifplugd
...
INTERFACES="auto"
HOTPLUG_INTERFACES="eth0 wlan0"
------------------------

Setup OpenConnect VPN Server for Cisco AnyConnect on Ubuntu 14.04 x64

OpenConnect server, also known as ocserv, is a VPN server that communicates over SSL. By design, its goal is to become a secure, lightweight, and fast VPN server. OpenConnect server uses the OpenConnect SSL VPN protocol. At the time of writing, it also has experimental compatibility with clients that use the AnyConnect SSL VPN protocol.
This article will show you how to install and setup ocserv on Ubuntu 14.04 x64.

Installing ocserv

Since Ubuntu 14.04 does not ship with ocserv, we will have to download the source code and compile it. The latest stable version of ocserv is 0.9.2.
Download ocserv from the official site.
wget ftp://ftp.infradead.org/pub/ocserv/ocserv-0.9.2.tar.xz
tar -xf ocserv-0.9.2.tar.xz
cd ocserv-0.9.2
Next, install the compile dependencies.
apt-get install build-essential pkg-config libgnutls28-dev libwrap0-dev libpam0g-dev libseccomp-dev libreadline-dev libnl-route-3-dev
Compile and install ocserv.
./configure
make
make install

Configuring ocserv

A sample config file is placed under the directory ocser-0.9.2/doc. We will use this file as a template. At first, we have to make our own CA cert and server cert.
cd ~
apt-get install gnutls-bin
mkdir certificates
cd certificates
We create a CA template file (ca.tmpl) with the content similar to the following. You can set your own "cn" and "organization".
cn = "VPN CA" 
organization = "Big Corp" 
serial = 1 
expiration_days = 3650
ca 
signing_key 
cert_signing_key 
crl_signing_key 
Then, generate a CA key and CA cert.
certtool --generate-privkey --outfile ca-key.pem
certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem
Next, create a local server certificate template file (server.tmpl) with the the content below. Please pay attention to the "cn" field, it must be hostname or IP address of your server.
cn = "服务器的公网ip"
organization = "MyCompany" 
expiration_days = 3650 
signing_key 
encryption_key
tls_www_server
Then, generate the server key and certificate.
certtool --generate-privkey --outfile server-key.pem
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
Copy the key, certificate, and config file to the ocserv config directory.
mkdir /etc/ocserv
cp server-cert.pem server-key.pem /etc/ocserv
cd ~/ocserv-0.9.2/doc
cp sample.config /etc/ocserv/config
cd /etc/ocserv
Edit the config file under /etc/ocserv. Uncomment or modify the fields described below.
auth = "plain[/etc/ocserv/ocpasswd]"

try-mtu-discovery = true

server-cert = /etc/ocserv/server-cert.pem
server-key = /etc/ocserv/server-key.pem

dns = 8.8.8.8

# comment out all route fields
#route = 10.10.10.0/255.255.255.0
#route = 192.168.0.0/255.255.0.0
#route = fef4:db8:1000:1001::/64
#no-route = 192.168.5.0/255.255.255.0

cisco-client-compat = true
Generate a user that will be used to login to ocserv.
ocpasswd -c /etc/ocserv/ocpasswd username
Enable NAT.
iptables -t nat -A POSTROUTING -j MASQUERADE
Enable IPv4 forwarding. Edit the file /etc/sysctl.conf.
net.ipv4.ip_forward=1
Apply this modification.
sysctl -p /etc/sysctl.conf

Start ocserv and connect using Cisco AnyConnect

First, start ocserv.
ocserv -c /etc/ocserv/config
Then, install Cisco AnyConnect on any of your devices, such as iPhone, iPad, or an Android device. Since we used a self-signed server key and certificate, we have to uncheck the option which prevents insecure servers. This option is located in the settings of AnyConnect. At this point, we can setup a new connection with the domain name or IP address of our ocserv and the username/password that we created.
Connect and enjoy!
from https://www.vultr.com/docs/setup-openconnect-vpn-server-for-cisco-anyconnect-on-ubuntu-14-04-x64
------------

OCserv on Ubuntu 16.04 for iOS 9 AnyConnect Client

OCserv is the OpenConnect VPN server. From Ubuntu 16.04 onward, OCserv is included in the standard Ubuntu repositories, so you do not need to compile it from source. In this tutorial the iOS 9 client, which could be an iPad or an iPhone, will connect to the VPN server using the Cisco AnyConnect VPN client.

Install packages on server

Set up your Ubuntu 16.04 server as explained in the basic tutorials, e.g., Ten Basic Tasks to Set Up a VPS.
Log on to your server and install the OCserv package:
sudo apt-get install ocserv
We will also need the GnuTLS package, since we use the GnuTLS utilities to generate our public key infrastructure (keys and certificates):
sudo apt-get install gnutls-bin

Make CA certificate and server certificate

The GnuTLS certificate tool (certtool) allows you to specify the fields for your certificates in a configuration template file.
Start by creating a configuration template file for your Certificate Authority (CA) certificate:
cd /etc/ocserv
sudo vi ca.tmpl
Press the i key on your keyboard to enter insert mode.
Enter the following fields into the CA configuration file, customizing the values as you prefer:
cn = "My CA" 
organization = "My Org" 
serial = 1 
expiration_days = 3650
ca
signing_key
cert_signing_key
crl_signing_key
Now generate a key and certificate for your CA, using the CA configuration template file you just created:
sudo certtool --generate-privkey --outfile ca-key.pem
sudo certtool --generate-self-signed --load-privkey ca-key.pem \
    --template ca.tmpl --outfile ca-cert.pem
Now create a server certificate template file:
sudo vi server.tmpl
Enter the following fields into the server configuration file. Note that in the common name (cn) field, youmust specify your actual server IP address or hostname :
cn = "server public ip"
organization = "My Org" 
expiration_days = 3650 
signing_key 
encryption_key
tls_www_server
Generate the server key and certificate, using the configuration template file:
sudo certtool --generate-privkey --outfile server-key.pem
sudo 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

Configure the OpenConnect VPN server

Edit the OCserv sample configuration file that is provided in /etc/ocserv:
sudo vi ocserv.conf
#auth = "pam[gid-min=1000]"
auth = "plain[/etc/ocserv/ocpasswd]"

#server-cert = /etc/ssl/certs/ssl-cert-snakeoil.pem
#server-key = /etc/ssl/private/ssl-cert-snakeoil.key
server-cert = /etc/ocserv/server-cert.pem
server-key = /etc/ocserv/server-key.pem

#try-mtu-discovery = false
try-mtu-discovery = true

#dns = 192.168.1.2
dns = 8.8.8.8

# Comment out all route fields
#route = 10.10.10.0/255.255.255.0
#route = 192.168.0.0/255.255.0.0
#route = fef4:db8:1000:1001::/64
#no-route = 192.168.5.0/255.255.255.0

cisco-client-compat = true

Create user id and password

Generate a user id and password that you will use to authenticate from AnyConnect to OCserv. For example, if you want your user id to be fred:
sudo ocpasswd -c /etc/ocserv/ocpasswd fred
You will be prompted to enter a password twice. The password will not be displayed on your terminal。

Enable IP packet forwarding

Allow forwarding in the Linux kernel by editing the system control configuration file:
sudo vi /etc/sysctl.conf
Delete the # sign at the start to uncomment the line:
net.ipv4.ip_forward=1
Make this change active now:
sudo sysctl -p

Open firewall

Open the server firewall for SSL:
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 443 -j ACCEPT
Enable network address translation (NAT):
sudo iptables -t nat -A POSTROUTING -j MASQUERADE
Assuming you have already installed iptables-persistent, reconfigure it to make your changes persist across server reboots:
sudo dpkg-reconfigure iptables-persistent

Start OpenConnect VPN server

Check that nothing is already listening on port 443:
sudo lsof -i
Note: The reason for this is that the first time I tried to start OCserv, I got an error listen() failed: Address already in use. The command sudo lsof -i then showed systemd listening to port 443 on IPv6. I do not know why systemd was doing this. The command systemctl -all list-sockets showed the related unit as ocserv.socket. The solution was to issue the command sudo systemctl stop ocserv.socket.
Start OCserv:
sudo ocserv -c /etc/ocserv/ocserv.conf
Check that it is now listening on port 443 with the command:
sudo netstat -tulpn | grep 443

Make CA certificate available for download

Your iPad or iPhone needs to be able to validate the server certificate. To allow it to do this, you must install your CA certificate on the iPad or iPhone as a trusted root certificate. The first step in this is to make the CA certificate available for download from your server.
Open the firewall so that you can reach the server from a browser:
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Install Apache:
sudo apt-get install apache2
Copy the CA certificate into the web root folder:
sudo cp /etc/ocserv/ca-cert.pem /var/www/html

Download and install CA certificate

Now go to your iOS device (iPad or iPhone).
Open the Safari browser.
Browse to the location of the CA certificate at your server’s IP address. For example, if your server is located at 123.45.67.89, then in Safari you would browse to:
http://123.45.67.89/ca-cert.pem
Follow the prompts to install the CA certificate as a “Profile” on your iOS 9 device.
Once the “Profile” (i.e., certificate) is installed, tap on Done.

Install AnyConnect on iOS

On your iPad or iPhone, open the the App Store, and search for Cisco AnyConnect:
Install AnyConnect on your iOS device.
--------------------------------------------

安装OpenConnectServer

2.1下载源码

从这里查看ocserv的最新版本号,你不需要点到FTP里看,只要安装格式替换链接路径就行了。比如现在最新的版本是0.10.8,那么你就把地址写成这样: ftp://ftp.infradead.org/pub/ocserv/ocserv-0.10.8.tar.xz ,好,我们现在来下载源码:

2.2 安装依赖

下载解压好了代码,就需要安装一些依赖了,些是需要的,有些则是可选的,这里我们尽可能的安装所有依赖,万一将来用得着呢!毕竟也就十来兆的大小。
如果没有什么问题,那就可以安装了,比如我这里的结果是这样的:

2.3 编译安装

使用make命令来编译和安装:

3、配置OpenConnectServer

3.1准备证书

安装证书工具 apt-get install gnutls-bin
在此目录下创建一个名为 ca.tmpl 的CA证书模板,写入如下语句:
使用 certtool --generate-privkey --outfile ca-key.pem 生成CA密钥;
使用certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem 生成CA证书;
然后我们生成服务器证书,这里注意cn项必须对应你服务器的域名或IP,模板名称是 server.tmpl ,内容如下:
使用 certtool --generate-privkey --outfile server-key.pem 生成密钥;
使用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 生成server证书;
把证书移动到合适的地方:

3.2 准备配置文件

我们把配置文件放到ocserv默认读取的位置:
配置文件可以参考官方手册来写,不过这里我们重点要确保以下条目正确:

3.3 测试服务器

现在,我们就可以来测试一下服务器了,使用命令来创建一个测试账号:
开启NAT转发;
使用 iptables -t nat -L 来验证转发是否开启成功:
这时,我们就可以使用 ocserv -f -d 1 命令来启动下服务啦!
打开你手机上的Cisco Anyconnect新建一个VPN,添加服务器IP就是你的vps的 IP:端口
好了,如果你看到如下信息,那服务器应该已经能够正常运行了:

3.4 优化OpenConnectServer

好了,既然服务器已经可以跑起来,那么我们就可以优化它了,首先,来写个启动脚本——毕竟,不能每次都用调试模式启动不是吗?
如果你和我一样使用的是 Ubuntu 15.04 而不是旧版,那么你需要参考这篇文章来找回一下upstart才能使用下边的脚本。
在配置文件中写入如下脚本:
这样,我们就可以使用 service ocserv start 和 service ocserv stop来控制服务了。

3.5 创建客户端证书,省的老输入密码

写入如下内容:
将证书和密钥转为PKCS12的格式,好导入Anyconnect:
期间会要求你输入证书名字和密码。
然后你需要把这个证书放到一个可以被直接访问的地方,然后通过URL将user.p12文件导入AnyConnect,具体位置在诊断标签页的证书栏目下,导入成功之后,将对应的VPN设置的高级设置部分的证书栏目,改为导入的这张证书。
现在,为了让服务器能够认得这张证书,我们再来修改一下配置: