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设置的高级设置部分的证书栏目,改为导入的这张证书。
现在,为了让服务器能够认得这张证书,我们再来修改一下配置:
这样,我们使用 service ocserv start 来启动它即可!
from https://www.logcg.com/archives/1343.html
---------------------------------------

使用 ocserv 搭建企业级 OpenConnect VPN 网关并使用 Let's Encrypt 证书

(按照此文,我成功利用ocserv VPN翻墙)

安装 ocserv:

网上许多方法都是通过手动编译源代码包的方式安装,然而现在至少对于 Debian 系的系统来说已经有了编译好的软件包了,详情见 Distribution Status,对于 Debian 系服务器来说(比如本例的 Ubuntu)直接一条指令即可(非常感谢维护这个包的:Aron Xu,Liang Guo 和 Mike Miller):

$ sudo apt install ocserv -y

我们需要打开系统的转发功能,在 /etc/sysctl.conf 中加入如下行:

net.ipv4.ip_forward=1
$ sysctl -p

打开 NAT 功能:

iptables -t nat -A POSTROUTING -j MASQUERADE

配置 Let’s Encrypt 证书

ocserv 需要 SSL 证书(用来加密连接流量,保证连接安全,放心,这一步不复杂),网上许多教程中使用的是自签发证书,方法复杂且容易被 MITM 攻击,好在现在有 Let’s Encrypt 可以免费为自己域名添加证书,本例中使用 certbot 来获取一个 Let’s Encrypt 证书。

下载certbot,方法很多,在本例中为:

apt-get update -y && apt-get install certbot -y

certbot certonly  -d urdomain.com --standalone

稍等片刻应该可以看到类似如下的输出(记住证书存放的地址,后面会用到):

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/urdomain.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/urdomain.com/privkey.pem

配置 ocserv:

默认安装好后在/etc/ocserv/下有一个很长的配置文件ocserv.conf,着重注意以下配置字段:

# 登录方式,使用用户名密码登录,密码文件稍后生成
auth = "plain[passwd=/etc/ocserv/ocpasswd]"

# 允许同时连接的客户端数量
max-clients = 12

# 限制同一客户端的并行登陆数量
max-same-clients = 16

# 服务监听的 TCP/UDP 端口(默认为 443)
tcp-port = 24430
udp-port = 24430

# 自动优化 MTU,尝试改善网络性能
try-mtu-discovery = true

# 服务器证书与密钥,就是上一步中生成的证书和私钥的位置
server-cert = /etc/letsencrypt/live/urdomain.com/fullchain.pem
server-key = /etc/letsencrypt/live/urdomain.com/privkey.pem

# 服务器域名
default-domain = urdomain.com

# 客户端连上 vpn 后使用的 DNS server.
dns = 8.8.8.8

# 注释掉所有的 route 和 no-route,让服务器成为 gateway
#route = 192.168.1.0/255.255.255.0
#no-route = 192.168.5.0/255.255.255.0

# 启用 Cisco 客户端兼容性支持
cisco-client-compat = true

由于使用用户名密码认证,我们需要生成一个密码文件,指令如下:

$ ocpasswd -c /etc/ocserv/ocpasswd  ur-username

配置好后启动 VPN:

$ ocserv -c /etc/ocserv/ocserv.conf

服务器端搭建完成。

在客户端程序anyconnect里,输入服务器地址时,输入vps-public-ip:24430即可,不必输入urdomain.com:24430

(ocserv 程序在安装后会使用 443 端口导致开启临时网页服务器的时候失败,读者给出的建议如下:

在进行 certbot 获取证书之前,先以管理员权限修改 /lib/systemd/system/ocserv.socket 配置文件,将其中的两个443端口号修改为其他未被占用的端口号后,再运行 certbot 即可,这样做的好处是,可以利用 certbot 的自动证书续期功能。

另外,/lib/systemd/system/ocserv.socket 中指定的端口号无需与 /etc/ocserv/ocserv.conf 中的端口号保持一致。在使用 OpenConnect 或者 AnyConnect 客户端时,使用在 /lib/systemd/system/ocserv.socket 中指定的端口号即可。

非常感谢这位读者的邮件,欢迎大家在测试的时候进行尝试)

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

Install OpenConnect VPN Server with Trusted Certificate from Let's Encrypt

OpenConnect VPN server, or ocserv, is an SSL VPN server compatible with Cisco AnyConnect. It can easily be installed in a cheap OpenVZ Virtual Private Server (VPS) with TUN capability. However, most online tutorials for installing OpenConnect VPN server rely on certtool to generate a self-signed certificate via OpenSSL. Afterwards, since the self-signed certificate is not trusted by operating systems, either the VPN client must be configured to skip certificate checking, or the self-signed certificate must be imported as a trusted certificate on the VPN client machine. Both practices are insecure. Bypassing certificate checking would allow an attacker to impose as the VPN server. Importing a trusted certificate does not seem wrong at first, but in case the private key is compromised, an attacker would be able to impose as any server to the client, including online shopping and bank websites, using a certificate signed by that private key. Remember that the self-signed certificate's private key is stored on the VPS filesystem, it is much less secure than Hardware Security Modules used at real CAs to store private keys, and therefore it is a bad idea to trust such certificates in client machines.

Let's Encrypt is a free, automated, and open Certificate Authority (CA). It allows anyone to obtain a domain-verified certificate within minutes, and without paying anything. Certificates from Let's Encrypt are trusted by most modern operating systems. They are ideal for securing an OpenConnect VPN server.

This article explains how to request a proper trusted certificate from Let's Encrypt for use with ocserv, how to install OpenConnect VPN Server and use the Let's Encrypt certificate, and how to configure Cisco AnyConnect client to connect to ocserv. These steps are verified with an OpenVZ Ubuntu 16.04 64bit VPS provided by SecureDragon. It is required to enable TUN devices for the VPS, typically through a button in SolusVM or other control panel provided by the hosting company.

Request Let's Encrypt Certificate for OpenConnect VPN Server

Before requesting a certificate from Let's Encrypt, you must have a Virtual Private Server with an IPv4 address, and have a domain name (could be subdomain) resolved to the server so that you are able to ping the server via the domain name.

After the requirements above are met, the first step is to install certbot, a program for requesting Let's Encrypt certificates. Executing the following commands as root installs certbot:

apt-get update
apt-get install certbot

Then, we can proceed to request a certificate:

certbot certonly -d urdomain.com --standalone 

It is necessary to stop any process running on TCP port 80 or 443 when running the above command, including Apache, nginx, Python or NodeJS web servers, and ocserv if you have installed it already. See certbot site for more information on how to request a certificate without stopping your web server.

You will see the following message if the certificate is obtained successfully:


To install ocserv, execute the following as root:

apt-get install ocserv

Then, edit /etc/ocserv/ocserv.conf:

auth = "plain[passwd=/etc/ocserv/ocpasswd]"
tcp-port = 24430
udp-port = 24430
run-as-user = nobody
run-as-group = daemon
socket-file = /var/run/ocserv-socket
server-cert = /etc/letsencrypt/live/urdomain.com/fullchain.pem
server-key = /etc/letsencrypt/live/urdomain.com/privkey.pemmax-clients = 8
max-same-clients = 12
try-mtu-discovery = true
device = vpns
ipv4-network = 192.168.90.0ipv4-netmask = 255.255.255.0
dns = 8.8.8.8
cisco-client-compat = true

Options server-cert and server-key should point to the certificate paths shown in certbot output.

(If you want to change ocserv's listening port number to avoid conflicts with websites running on port 443:

  1. In /etc/ocserv/ocserv.conf, set tcp-port and udp-port to the desired port number.
  2. In /lib/systemd/system/ocserv.socket, set ListenStream and ListenDatagram to the same port number.
  3. Run systemctl daemon-reload to inform systemd that the port number has been changed.)

Next step is creating usernames and passwords with ocpasswd:

ocpasswd -c /etc/ocserv/ocpasswd  ur-username

Setup NAT Routing 

ocserv has been configured and is ready for connections, but if you try at this moment, Cisco AnyConnect clients can only communicate with the VPN server, but would not be able to reach the Internet. It is necessary to setup Network Address Translation (NAT) in order to gain Internet access:

iptables -t nat -A POSTROUTING -j MASQUERADE
apt-get install iptables-persistent

If apt-get install iptables-persistent has no effect, run dpkg-reconfigure iptables-persistent instead. Answer YES at the following dialog, so that the iptables settings will be re-applied automatically if the server reboots.

我们还需要打开系统的转发功能,在 /etc/sysctl.conf 中加入如下行:

net.ipv4.ip_forward=1
$ sysctl -p

Finally, start the ocserv vpn server:

ocserv -c /etc/ocserv/ocserv.conf

the ocserv server-end is installed successfully.

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

ocserv配合udp-broadcast-relay实现LAN游戏联机

手机上遇到个局域网联机游戏, 不支持输入IP, 使用 OpenVPN 搭建后, 无法进行 UDP 广播, 使用 SoftEther VPN 搭建的 OpenVPN, 不知道什么原因, 疯狂走网速, 发现 AnyConnect 配合 udp-broadcast-relay 可以实现LAN游戏联机, 搭建时使用的机器系统为 CentOS 7.
  1. 搭建 AnyConnect
    1. 安装 OCSERV
       yum install epel-release -y
       yum install ocserv -y
      
    2. 生成证书
       mkdir CA
       cd CA
       
       certtool --generate-privkey --outfile ca-key.pem 
       cat << _EOF_ >ca.tmpl 
       cn = "VPN CA" 
       organization = "Big Corp" 
       serial = 1 
       expiration_days = -1 
       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 = "服务器的公网IP"
    3. organization = "MyCompany" 
       expiration_days = -1 
       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
       
       cp ca-cert.pem /etc/pki/ocserv/cacerts/ca.crt
       cp server-cert.pem /etc/pki/ocserv/public/server.crt
       cp server-key.pem /etc/pki/ocserv/private/server.key
      
    4. 配置 OCSERV
       vim /etc/ocserv/ocserv.conf
      
      修改后内容如下
       # User authentication method. Could be set multiple times and in 
       # that case all should succeed. To enable multiple methods use
       # multiple auth directives. Available options: certificate, 
       # plain, pam, radius, gssapi.
       #
       # Note that authentication methods cannot be changed with reload.
       
       # certificate:
       #  This indicates that all connecting users must present a certificate.
       #
       # pam[gid-min=1000]:
       #  This enabled PAM authentication of the user. The gid-min option is used 
       # by auto-select-group option, in order to select the minimum valid group ID.
       #
       # plain[passwd=/etc/ocserv/ocpasswd,otp=/etc/ocserv/users.otp]
       #  The plain option requires specifying a password file which contains
       # entries of the following format.
       # "username:groupname1,groupname2:encoded-password"
       # One entry must be listed per line, and 'ocpasswd' should be used
       # to generate password entries. The 'otp' suboption allows to specify
       # an oath password file to be used for one time passwords; the format of
       # the file is described in https://code.google.com/p/mod-authn-otp/wiki/UsersFile
       #
       # radius[config=/etc/radiusclient/radiusclient.conf,groupconfig=true,nas-identifier=name,override-interim-updates=false]:
       #  The radius option requires specifying freeradius-client configuration
       # file. If the groupconfig option is set, then config-per-user will be overriden,
       # and all configuration will be read from radius. The 'override-interim-updates' if set to
       # true will ignore Acct-Interim-Interval from the server and 'stats-report-time' will be considered.
       #
       # gssapi[keytab=/etc/key.tab,require-local-user-map=true,tgt-freshness-time=900]
       #  The gssapi option allows to use authentication methods supported by GSSAPI,
       # such as Kerberos tickets with ocserv. It should be best used as an alternative
       # to PAM (i.e., have pam in auth and gssapi in enable-auth), to allow users with
       # tickets and without tickets to login. The default value for require-local-user-map
       # is true. The 'tgt-freshness-time' if set, it would require the TGT tickets presented
       # to have been issued within the provided number of seconds. That option is used to
       # restrict logins even if the KDC provides long time TGT tickets.
       
       auth = "plain[/etc/ocserv/ocpasswd]"
       #auth = "pam"
       #auth = "pam[gid-min=1000]"
       #auth = "plain[passwd=./sample.passwd,otp=./sample.otp]"
       #auth = "certificate"
       #auth = "radius[config=/etc/radiusclient/radiusclient.conf,groupconfig=true]"
       
       # Specify alternative authentication methods that are sufficient
       # for authentication. That is, if set, any of the methods enabled
       # will be sufficient to login.
       #enable-auth = "certificate"
       #enable-auth = "gssapi"
       #enable-auth = "gssapi[keytab=/etc/key.tab,require-local-user-map=true,tgt-freshness-time=900]"
       
       # Accounting methods available:
       # radius: can be combined with any authentication method, it provides
       #      radius accounting to available users (see also stats-report-time).
       #
       # pam: can be combined with any authentication method, it provides
       #      a validation of the connecting user's name using PAM. It is
       #      superfluous to use this method when authentication is already
       #      PAM.
       #
       # Only one accounting method can be specified.
       #acct = "radius[config=/etc/radiusclient/radiusclient.conf]"
       
       # Use listen-host to limit to specific IPs or to the IPs of a provided 
       # hostname.
       #listen-host = [IP|HOSTNAME]
       
       # When the server has a dynamic DNS address (that may change),
       # should set that to true to ask the client to resolve again on
       # reconnects.
       #listen-host-is-dyndns = true
       
       # TCP and UDP port number
       tcp-port = 4443
       udp-port = 4443
       
       # Accept connections using a socket file. It accepts HTTP
       # connections (i.e., without SSL/TLS unlike its TCP counterpart),
       # and uses it as the primary channel. That option cannot be
       # combined with certificate authentication.
       #listen-clear-file = /var/run/ocserv-conn.socket
       
       # The user the worker processes will be run as. It should be
       # unique (no other services run as this user).
       run-as-user = ocserv
       run-as-group = ocserv
       
       # socket file used for IPC with occtl. You only need to set that,
       # if you use more than a single servers.
       #occtl-socket-file = /var/run/occtl.socket
       
       # socket file used for server IPC (worker-main), will be appended with .PID
       # It must be accessible within the chroot environment (if any), so it is best
       # specified relatively to the chroot directory.
       socket-file = ocserv.sock
       
       # The default server directory. Does not require any devices present.
       chroot-dir = /var/lib/ocserv
       
       ### All configuration options below this line are reloaded on a SIGHUP.
       ### The options above, will remain unchanged. Note however, that the 
       ### server-cert, server-key, dh-params and ca-cert options will be reloaded
       ### if the provided file changes, on server reload. That allows certificate
       ### rotation, but requires the server key to remain the same for seamless
       ### operation. If the server key changes on reload, there may be connection
       ### failures during the reloading time.
       
       # Whether to enable seccomp/Linux namespaces worker isolation. That restricts the number of 
       # system calls allowed to a worker process, in order to reduce damage from a
       # bug in the worker process. It is available on Linux systems at a performance cost.
       # The performance cost is roughly 2% overhead at transfer time (tested on a Linux 3.17.8).
       # Note however, that process isolation is restricted to the specific libc versions
       # the isolation was tested at. If you get random failures on worker processes, try
       # disabling that option and report the failures you, along with system and debugging
       # information at: https://gitlab.com/ocserv/ocserv/issues
       isolate-workers = true
       
       # A banner to be displayed on clients
       #banner = "Welcome"
       
       # Limit the number of clients. Unset or set to zero for unlimited.
       #max-clients = 1024
       max-clients = 16
       
       # Limit the number of identical clients (i.e., users connecting 
       # multiple times). Unset or set to zero for unlimited.
       max-same-clients = 0
       
       # 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
       
       # Stats report time. The number of seconds after which each
       # worker process will report its usage statistics (number of
       # bytes transferred etc). This is useful when accounting like
       # radius is in use.
       #stats-report-time = 360
       
       # Keepalive in seconds
       keepalive = 32400
       
       # Dead peer detection in seconds.
       # Note that when the client is behind a NAT this value
       # needs to be short enough to prevent the NAT disassociating
       # his UDP session from the port number. Otherwise the client
       # could have his UDP connection stalled, for several minutes.
       dpd = 90
       
       # Dead peer detection for mobile clients. That needs to
       # be higher to prevent such clients being awaken too 
       # often by the DPD messages, and save battery.
       # The mobile clients are distinguished from the header
       # 'X-AnyConnect-Identifier-DeviceType'.
       mobile-dpd = 1800
       
       # If using DTLS, and no UDP traffic is received for this
       # many seconds, attempt to send future traffic over the TCP
       # connection instead, in an attempt to wake up the client
       # in the case that there is a NAT and the UDP translation
       # was deleted. If this is unset, do not attempt to use this
       # recovery mechanism.
       switch-to-tcp-timeout = 25
       
       # MTU discovery (DPD must be enabled)
       try-mtu-discovery = true
       
       # 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)
       #
       # The server-cert file may contain a single certificate, or
       # a sorted certificate chain.
       #
       # There may be multiple server-cert and server-key directives,
       # but each key should correspond to the preceding certificate.
       server-cert = /etc/pki/ocserv/public/server.crt
       server-key = /etc/pki/ocserv/private/server.key
       
       # 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, TPM or encrypted keys are used the PINs should be available
       # in files. The srk-pin-file is applicable to TPM keys only, and is the 
       # storage root key.
       #pin-file = /path/to/pin.txt
       #srk-pin-file = /path/to/srkpin.txt
       
       # The password or PIN needed to unlock the key in server-key file.
       # Only needed if the file is encrypted or a PKCS #11 object. This
       # is an alternative method to pin-file.
       #key-pin = 1234
       
       # The SRK PIN for TPM.
       # This is an alternative method to srk-pin-file.
       #srk-pin = 1234
       
       # The Certificate Authority that will be used to verify
       # client certificates (public keys) if certificate authentication
       # is set.
       ca-cert = /etc/pki/ocserv/cacerts/ca.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
       
       # The revocation list of the certificates issued by the 'ca-cert' above.
       # See the manual to generate an empty CRL initially. The CRL will be reloaded
       # periodically when ocserv detects a change in the file. To force a reload use
       # SIGHUP.
       #crl = /path/to/crl.pem
       
       # Uncomment this to enable compression negotiation (LZS, LZ4).
       #compression = true
       
       # Set the minimum size under which a packet will not be compressed.
       # That is to allow low-latency for VoIP packets. The default size
       # is 256 bytes. Modify it if the clients typically use compression
       # as well of VoIP with codecs that exceed the default value.
       #no-compress-limit = 256
       
       # GnuTLS priority string; note that SSL 3.0 is disabled by default
       # as there are no openconnect (and possibly anyconnect clients) using
       # that protocol. The string below does not enforce perfect forward
       # secrecy, in order to be compatible with legacy clients.
       #
       # Note that the most performant ciphersuites are the moment are the ones
       # involving AES-GCM. These are very fast in x86 and x86-64 hardware, and
       # in addition require no padding, thus taking full advantage of the MTU.
       # For that to be taken advantage of, the openconnect client must be
       # used, and the server must be compiled against GnuTLS 3.2.7 or later.
       # Use "gnutls-cli --benchmark-tls-ciphers", to see the performance
       # difference with AES_128_CBC_SHA1 (the default for anyconnect clients)
       # in your system.
       
       tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-VERS-SSL3.0"
       
       # More combinations in priority strings are available, check
       # http://gnutls.org/manual/html_node/Priority-Strings.html
       # E.g., the string below enforces perfect forward secrecy (PFS) 
       # on the main channel.
       #tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA:-VERS-SSL3.0:-ARCFOUR-128"
       
       # That option requires the established DTLS channel to use the same
       # cipher as the primary TLS channel. This cannot be combined with
       # listen-clear-file since the ciphersuite information is not available
       # in that configuration. Note also, that this option implies that
       # dtls-legacy option is false; this option cannot be enforced
       # in the legacy/compat protocol.
       #match-tls-dtls-ciphers = true
       
       # The time (in seconds) that a client is allowed to stay connected prior
       # to authentication
       auth-timeout = 240
       
       # The time (in seconds) that a client is allowed to stay idle (no traffic)
       # before being disconnected. Unset to disable.
       #idle-timeout = 1200
       
       # The time (in seconds) that a client is allowed to stay connected
       # Unset to disable.
       #session-timeout = 86400
       
       # The time (in seconds) that a mobile client is allowed to stay idle (no
       # traffic) before being disconnected. Unset to disable.
       #mobile-idle-timeout = 2400
       
       # The time (in seconds) that a client is not allowed to reconnect after 
       # a failed authentication attempt.
       min-reauth-time = 300
       
       # Banning clients in ocserv works with a point system. IP addresses
       # that get a score over that configured number are banned for
       # min-reauth-time seconds. By default a wrong password attempt is 10 points,
       # a KKDCP POST is 1 point, and a connection is 1 point. Note that
       # due to difference processes being involved the count of points
       # will not be real-time precise.
       #
       # Score banning cannot be reliably used when receiving proxied connections
       # locally from an HTTP server (i.e., when listen-clear-file is used).
       #
       # Set to zero to disable.
       max-ban-score = 50
       
       # The time (in seconds) that all score kept for a client is reset.
       ban-reset-time = 300
       
       # In case you'd like to change the default points.
       #ban-points-wrong-password = 10
       #ban-points-connection = 1
       #ban-points-kkdcp = 1
       
       # Cookie timeout (in seconds)
       # Once a client is authenticated he's provided a cookie with
       # which he can reconnect. That cookie will be invalided if not
       # used within this timeout value. On a user disconnection, that
       # cookie will also be active for this time amount prior to be
       # invalid. That should allow a reasonable amount of time for roaming
       # between different networks.
       cookie-timeout = 300
       
       # If this is enabled (not recommended) the cookies will stay
       # valid even after a user manually disconnects, and until they
       # expire. This may improve roaming with some broken clients.
       #persistent-cookies = true
       
       # Whether roaming is allowed, i.e., if true a cookie is
       # restricted to a single IP address and cannot be re-used
       # from a different IP.
       deny-roaming = false
       
       # 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 (note
       # that, some clients fail if rekey is disabled).
       rekey-time = 172800
       
       # ReKey method
       # Valid options: ssl, new-tunnel
       #  ssl: Will perform an efficient rehandshake on the channel allowing
       #       a seamless connection during rekey.
       #  new-tunnel: Will instruct the client to discard and re-establish the channel.
       #       Use this option only if the connecting clients have issues with the ssl
       #       option.
       rekey-method = ssl
       
       # Script to call when a client connects and obtains an IP.
       # The following 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_REAL_LOCAL (the local
       # interface IP the client connected), IP_LOCAL (the local IP
       # in the P-t-P connection), IP_REMOTE (the VPN IP of the client),
       # IPV6_LOCAL (the IPv6 local address if there are both IPv4 and IPv6
       # assigned), IPV6_REMOTE (the IPv6 remote address), IPV6_PREFIX, and
       # ID (a unique numeric ID); REASON may be "connect" or "disconnect".
       # In addition the following variables OCSERV_ROUTES (the applied routes for this
       # client), OCSERV_NO_ROUTES, OCSERV_DNS (the DNS servers for this client),
       # will contain a space separated list of routes or DNS servers. A version
       # of these variables with the 4 or 6 suffix will contain only the IPv4 or
       # IPv6 values.
       
       # The disconnect script will receive the additional values: STATS_BYTES_IN,
       # STATS_BYTES_OUT, STATS_DURATION that contain a 64-bit counter of the bytes 
       # output from the tun device, and the duration of the session in seconds.
       
       #connect-script = /usr/bin/ocserv-script
       #disconnect-script = /usr/bin/ocserv-script
       
       # UTMP
       # Register the connected clients to utmp. This will allow viewing
       # the connected clients using the command 'who'.
       #use-utmp = true
       
       # Whether to enable support for the occtl tool (i.e., either through D-BUS,
       # or via a unix socket).
       use-occtl = true
       
       # PID file. It can be overriden in the command line.
       pid-file = /var/run/ocserv.pid
       
       # 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
       #
       
       # The name to use for the tun device
       device = vpns
       
       # Whether the generated IPs will be predictable, i.e., IP stays the
       # same for the same user when possible.
       predictable-ips = true
       
       # The default domain to be advertised
       default-domain = example.com
       
       # The pool of addresses that leases will be given from. If the leases
       # are given via Radius, or via the explicit-ip? per-user config option then 
       # these network values should contain a network with at least a single
       # address that will remain under the full control of ocserv (that is
       # to be able to assign the local part of the tun device address).
       #ipv4-network = 192.168.1.0
       #ipv4-netmask = 255.255.255.0
       ipv4-network = 10.9.0.0
       ipv4-netmask = 255.255.255.0
       
       # An alternative way of specifying the network:
       #ipv4-network = 192.168.1.0/24
       
       # The IPv6 subnet that leases will be given from.
       #ipv6-network = fda9:4efe:7e3b:03ea::/64
       
       # Specify the size of the network to provide to clients. It is
       # generally recommended to provide clients with a /64 network in
       # IPv6, but any subnet may be specified. To provide clients only
       # with a single IP use the prefix 128.
       #ipv6-subnet-prefix = 128
       #ipv6-subnet-prefix = 64
       
       # Whether to tunnel all DNS queries via the VPN. This is the default
       # when a default route is set.
       #tunnel-all-dns = true
       
       # The advertized DNS server. Use multiple lines for
       # multiple servers.
       # dns = fc00::4be0
       #dns = 192.168.1.2
       dns = 114.114.114.114
       dns = 114.114.115.115
       
       # The NBNS server (if any)
       #nbns = 192.168.1.3
       
       # 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.
       # Only set to true, if there can be occupied addresses in the
       # IP range for leases.
       ping-leases = false
       
       # Use this option to enforce an MTU value to the incoming
       # connections. Unset to use the default MTU of the TUN device.
       #mtu = 1420
       
       # 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 = 40000
       #tx-data-per-sec = 40000
       
       # 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
       
       # Routes to be forwarded to the client. If you need the
       # client to forward routes to the server, you may use the 
       # config-per-user/group or even connect and disconnect scripts.
       #
       # To set the server as the default gateway for the client just
       # comment out all routes from the server, or use the special keyword
       # 'default'.
       
       #route = 10.10.10.0/255.255.255.0
       #route = 192.168.0.0/255.255.0.0
       #route = fef4:db8:1000:1001::/64
       
       # Subsets of the routes above that will not be routed by
       # the server.
       
       #no-route = 192.168.5.0/255.255.255.0
       
       # If set, the script /usr/bin/ocserv-fw will be called to restrict
       # the user to its allowed routes and prevent him from accessing
       # any other routes. In case of defaultroute, the no-routes are restricted.
       # All the routes applied by ocserv can be reverted using /usr/bin/ocserv-fw
       # --removeall. This option can be set globally or in the per-user configuration.
       #restrict-user-to-routes = true
       
       # When set to true, all client's iroutes are made visible to all
       # connecting clients except for the ones offering them. This option
       # only makes sense if config-per-user is set.
       #expose-iroutes = true
       
       # Groups that a client is allowed to select from.
       # A client may belong in multiple groups, and in certain use-cases
       # it is needed to switch between them. For these cases the client can
       # select prior to authentication. Add multiple entries for multiple groups.
       # The group may be followed by a user-friendly name in brackets.
       #select-group = group1
       #select-group = group2[My special group]
       
       # The name of the (virtual) group that if selected it would assign the user
       # to its default group.
       #default-select-group = DEFAULT
       
       # Instead of specifying manually all the allowed groups, you may instruct
       # ocserv to scan all available groups and include the full list.
       #auto-select-group = true
       
       # 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, ipv4-netmask, rx/tx-per-sec, iroute, route, no-route,
       #  explicit-ipv4, explicit-ipv6, net-priority, deny-roaming, no-udp, 
       #  user-profile, cgroup, stats-report-time, and session-timeout.
       #
       # 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). The no-udp
       # is a boolean option (e.g., no-udp = true), and will prevent a UDP session
       # for that specific user or group.
       
       #config-per-user = /etc/ocserv/config-per-user/
       #config-per-group = /etc/ocserv/config-per-group/
       
       # When config-per-xxx is specified and there is no group or user that
       # matches, then utilize the following configuration.
       #default-user-config = /etc/ocserv/defaults/user.conf
       #default-group-config = /etc/ocserv/defaults/group.conf
       
       # 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 (the argument of iroute).
       
       #route-add-cmd = "ip route add %{R} dev %{D}"
       #route-del-cmd = "ip route delete %{R} dev %{D}"
       
       # This option allows to forward a proxy. The special keywords '%{U}'
       # and '%{G}', if present will be replaced by the username and group name.
       #proxy-url = http://example.com/
       #proxy-url = http://example.com/%{U}/
       
       # This option allows you to specify a URL location where a client can
       # post using MS-KKDCP, and the message will be forwarded to the provided
       # KDC server. That is a translation URL between HTTP and Kerberos.
       # In MIT kerberos you'll need to add in realms:
       #   EXAMPLE.COM = {
       #     kdc = https://ocserv.example.com/kerberos
       #     http_anchors = FILE:/etc/ocserv-ca.pem
       #   }
       # This option is available if ocserv is compiled with GSSAPI support. 
       
       #kkdcp = SERVER-PATH KERBEROS-REALM PROTOCOL@SERVER:PORT
       #kkdcp = /kerberos EXAMPLE.COM udp@127.0.0.1:88
       #kkdcp = /kerberos-tcp EXAMPLE.COM tcp@127.0.0.1:88
       
       #
       # The following options are for (experimental) AnyConnect client 
       # compatibility. 
       
       # This option will enable the pre-draft-DTLS version of DTLS, and
       # will not require clients to present their certificate on every TLS
       # connection. It must be set to true to support legacy CISCO clients
       # and openconnect clients < 7.08. When set to true, it implies dtls-legacy = true.
       cisco-client-compat = true
       
       # This option allows to disable the DTLS-PSK negotiation (enabled by default).
       # The DTLS-PSK negotiation was introduced in ocserv 0.11.5 to deprecate
       # the pre-draft-DTLS negotiation inherited from AnyConnect. It allows the
       # DTLS channel to negotiate its ciphers and the DTLS protocol version.
       #dtls-psk = false
       
       # This option allows to disable the legacy DTLS negotiation (enabled by default,
       # but that may change in the future).
       # The legacy DTLS uses a pre-draft version of the DTLS protocol and was
       # from AnyConnect protocol. It has several limitations, that are addressed
       # by the dtls-psk protocol supported by openconnect 7.08+.
       dtls-legacy = true
       
       # Client profile xml. A sample file exists in doc/profile.xml.
       # It is required by some of the CISCO clients.
       # This file must be accessible from inside the worker's chroot. 
       user-profile = profile.xml
       
       #Advanced options
       
       # Option to allow sending arbitrary custom headers to the client after
       # authentication and prior to VPN tunnel establishment. You shouldn't
       # need to use this option normally; if you do and you think that
       # this may help others, please send your settings and reason to
       # the openconnect mailing list. The special keywords '%{U}'
       # and '%{G}', if present will be replaced by the username and group name.
       #custom-header = "X-My-Header: hi there"
       
      
      修改了 auth = "pam" -> auth = "plain[/etc/ocserv/ocpasswd]" tcp-port = 443 udp-port = 443 -> tcp-port = 4443 udp-port = 4443 max-same-clients = 2 -> max-same-clients = 0 try-mtu-discovery = false -> try-mtu-discovery = true ipv4-network = 192.168.1.0 ipv4-netmask = 255.255.255.0 -> 取消注释, 并改为 ipv4-network = 10.9.0.0 ipv4-netmask = 255.255.255.0 dns = 192.168.1.2 -> 取消注释, 并改为 dns = 114.114.114.114 dns = 114.114.115.115
    5. 生成 OCSERV 连接密码
       ocpasswd -c /etc/ocserv/ocpasswd username
      
      username 为连接用户名
    6. 配置 iptables
       yum install iptables-services -y
       systemctl mask firewalld
       systemctl enable iptables
       systemctl stop firewalld
       systemctl start iptables
       iptables --flush
       iptables -t nat -A POSTROUTING -s 10.9.0.0/24 -o eth0 -j MASQUERADE
       iptables -A FORWARD -s 10.9.0.0/24 -j ACCEPT
       iptables-save > /etc/sysconfig/iptables
      
    7. 配置 IPv4 转发
       vim /etc/sysctl.conf
       添加net.ipv4.ip_forward = 1到文件顶部
       systemctl restart network.service
      
    8. 启动并设置开机启动
       systemctl start ocserv
       systemctl enable ocserv
      至此,ocserv搭建完成。
      搭建 udp-broadcast-relay:
  2.  cd
     yum install git gcc -y
     git clone https://github.com/nomeata/udp-broadcast-relay.git
     cd udp-broadcast-relay
     make
     ln -s `pwd`/udp-broadcast-relay /usr/bin/udp-broadcast-relay
    
  3. 整合 AnyConnect udp-broadcast-relay
     vim /usr/bin/ocserv-script-udp-broadcast-relay
    
    内容为
     #!/bin/bash
    
     function getDev()
     {
         dev="eth0"
         for ((t=0; t < 16; t++))
         do
             ifconfig vpns${t} &> /dev/null && dev="${dev} vpns${t}"
         done
         echo ${dev}
     }
     
     killall udp-broadcast-relay
     udp-broadcast-relay -f 1 3801 $(getDev)
    
    3801 为游戏的 UDP 广播端口
     vim /etc/ocserv/ocserv.conf
    
    connect-script = /usr/bin/ocserv-script disconnect-script = /usr/bin/ocserv-script 取消注释并修改为 connect-script = /usr/bin/ocserv-script-udp-broadcast-relay disconnect-script = /usr/bin/ocserv-script-udp-broadcast-relay
     chmod +x /usr/bin/ocserv-script-udp-broadcast-relay
     systemctl restart ocserv
------------------------------------------

在iOS中安装自签名证书

如果使用自签名证书的话还需要多这一步,不然iOS上是不能手动信任的. 将前面的pulbic.pem转为der格式
openssl x509 -outform der -in public.pem -out public.der  
然后将public.der用邮件的方式发到iOS上,点击证书就会自动开始引到安装了.
(openssl genrsa -out private.pem 2048
openssl req -new -x509 -key private.pem -out public.pem -days 3650)
-------------------------------------------------
相关帖子:
OpenConnect vpn server0.8.9 一键安装脚本 for debian 7+

ocserv的一个问题


mac上/windows上的anyconnect vpn客户端程序下载地址
-------

http://briteming.hatenablog.com/entry/2017/11/01/123516
---------

Ocserv 配置备忘

于2015/3/21更新

在网络环境越来越严苛的今天,如何维护一个较为良好的网络环境成为了我最关心的问题。现在看来,Ocserv(即Openconnect Server)是一个良好的解决方法。原因如下:

  1. Ocserv基于一个还算“可靠”的系统,这个可靠并不指安全性这一点,因为安全性这点上与它一致或比它好的VPN服务并不少……主要是,Ocserv其实是一个基于Cisco的Anyconnect系统的VPN服务端。只这点就相对来说比较有保障了,毕竟这条路断了的话也很有可能影响正常的经济运行呢……此中深意只要稍微了解一下VPN真正的用途就明确了。

  2. Anyconnect这套协议是在TLS/DTLS上的,换句话说,在真正建立连接的时候,刚开始的几步和其余使用TLS的协议并无太大差距。换句话说,如果你把这个服务的TCP监听端口放在443、并只启用TLS的话,那么你真正交互内容的过程在外界看来和HTTPS没什么大区别,只是流量比较大而已。

  3. Anyconnect可以只基于TCP,也可以通过TCP完成连接、认证等必要步骤后使用DTLS/UDP进行真正的数据通信。其实,在可以使用UDP的环境下,还是尽量要使用UDP,因为,TCP实在是太过“沉重”了,并不适合VPN的应用,尤其是如果VPN基于TCP的话,那么TCP over TCP的情况将会经常产生,这是非常低效的……(虽然PPTP也是这么干的……但还是不吐槽了)

  4. Ocserv的运行只需要系统对TUN/TAP的支持,所以OVZ用户也存在使用Ocserv的可能。

基于以上四点,再加上OpenWRT可以直接通过OpenConnect直接与Ocserv服务连接,所以,目前我的主要维护优良上网环境的方式就是它了。下面是Debian系Linux配置Ocserv的重点步骤。

Step 0. 如果你用的是Ubuntu的话,只要更新好了就可以忽略此步骤;如果你用的是Debian Wheezy的话,那么一定要在 /etc/apt/sources.list后加上wheezy-backports的源:

deb http://ftp.us.debian.org/debian/ wheezy-backports main contrib non-free

当然,上面的源地址可以根据你的喜好更改。

Step 1. 到了这里,我们要安装编译Ocserv必要的东西了:

sudo apt-get update
sudo apt-get install libwrap0-dev libpam0g-dev libdbus-1-dev libnl-route-3-dev \
libprotobuf-c0-dev libpcl1-dev libopts25-dev autogen libgnutls28-dev \
libseccomp-dev libreadline-dev build-essential

(注:如果wheezy下出现找不到包的情况,请在apt-getinstall间加上-t wheezy-backports

Step 2. 先到 ftp://ftp.infradead.org/pub/ocserv/ 上确认目前 Ocserv 的最新版本,然后将网址复制下来,到服务器上进行下载、解压、编译、安装:

wget 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/
./configure --prefix=/usr --sysconfdir=/etc
make
sudo make install

如果上述Step 1.做好了的话,这里应该不会出现任何错误的……

Step 3. 进行Ocserv的配置。首先,在你执行make的目录中执行:

sudo mkdir /etc/ocserv
cp doc/sample.config /etc/ocserv/ocserv.conf

接下来就按照文件中的注释去修改/etc/ocserv/ocserv.conf文件吧……

如果使用用户证书认证的话,你需要把生成用户证书的跟证书放在配置文件的ca-certificate属性中,并在上面的认证配置中选择证书认证。

如果你使用的是plain认证,那么你可以通过ocpasswd来生成对应的密钥文件:

ocpasswd -c /path/to/.ocpasswd <username>

当然,Ocserv为SSLVPN,所以,你需要证书。如果是自签名证书的话其实很麻烦的……所以推荐使用StartSSL的免费证书。只要别忘了把StartSSL的Intermediate证书和CA证书放在你的证书后面就好,即你的证书(不是密钥)中的内容顺序是:证书-Intermediate-CA。然后就好好设置server-certserver-key属性。

当然,还有一个重要的地方是,为了实现全局路由,并不能直接route=0.0.0.0/0.0.0.0解决,而需要拆分成route=0.0.0.0/128.0.0.0route=128.0.0.0/128.0.0.0才可以,这样会避免一些过于奇妙的情况。

配置文件中还可以选择监听端口,虚拟地址段等等。这些都可以自己通过注释去配置。

Step 4. 创建对应的守护进程脚本,放在/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.\n\r"
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

之后需要做的事情就是chmod +x /etc/init.d/ocserv设置运行权限,以及update-rc.d ocserv defaults设置开机自动启动,还有service ocserv start启动服务了。

Step 5. 设置转发和防火墙。首先要将/etc/sysctl.conf中的net.ipv4.ip_forward=1前的注释去掉,执行sysctl -p,这样开启内核转发。

接下来防火墙设置就是:iptables -t nat -A POSTROUTING -s <你定义的网段的CIDR表示> -o eth0 -j MASQUERADE。如果使用的是OVZ的话,那么iptables的设置应该是这样的:iptables -t nat -A POSTROUTING -s <配置VPN时定义的网段CIDR> -j SNAT --to-source <你的服务器外网IP>

现在应该一切妥当了……