2015年2月20日星期五

在CentOS 6.5上编译ocserv并配置Cisco AnyConnect VPN,以便在iphone上使用OpenConnect SSL VPN翻墙

在CentOS 6.5上编译ocserv并配置Cisco AnyConnect VPN,以便在iphone上使用OpenConnect SSL VPN翻墙

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-devel gmp
wget http://ftp.gnu.org/gnu/nettle/nettle-2.7.1.tar.gz
tar zxf nettle-2.7.1.tar.gz && cd nettle-2.7.1
./configure --prefix=/usr && make
make install &&
chmod -v 755 /usr/lib/libhogweed.so.2.5 /usr/lib/libnettle.so.4.7 &&
install -v -m755 -d /usr/share/doc/nettle-2.7.1 &&
install -v -m644 nettle.html /usr/share/doc/nettle-2.7.1

2、编译unbound
安装expat-devel
yum install expat-devel
wget http://unbound.nlnetlabs.nl/downloads/unbound-1.4.22.tar.gz
tar zxf unbound-1.4.22.tar.gz && cd unbound-1.4.22
./configure && make && make install
mkdir -p /etc/unbound && unbound-anchor -a "/etc/unbound/root.key"

3、编译gnutls
wget ftp://ftp.gnutls.org/gcrypt/gnutls/v3.2/gnutls-3.2.12.1.tar.xz
xz -c -d gnutls-3.2.12.1.tar.xz | tar x
cd gnutls-3.2.12
./configure --prefix=/usr && make && make install

4、编译ocserv
wget ftp://ftp.infradead.org/pub/ocserv/ocserv-0.3.2.tar.xz
xz -c -d ocserv-0.3.2.tar.xz | tar x
cd ocserv-0.3.2
./configure && make && make install
如果nettle和gnutls安装在/usr/local目录,需要运行以下命令设置系统变量,再运行./configure。同时要把这些命令加进系统启动里。
export LD_LIBRARY_PATH=/usr/local/lib/:/usr/local/lib64/ NETTLE_CFLAGS="-I/usr/local/include/" NETTLE_LIBS="-L/usr/local/lib64/ -lnettle" HOGWEED_CFLAGS="-I/usr/local/include" HOGWEED_LIBS="-L/usr/local/lib64/ -lhogweed"
export LD_LIBRARY_PATH=/usr/local/lib/:/usr/local/lib64/ LIBGNUTLS_CFLAGS="-I/usr/local/include/" LIBGNUTLS_LIBS="-L/usr/local/lib/ -lgnutls" LIBNL3_CFLAGS="-I/usr/local/include" LIBNL3_LIBS="-L/usr/local/lib/ -lnl-3 -lnl-route-3"

5、配置ocserv
创建ca证书和服务器证书(参考http://www.infradead.org/ocserv/manual.html#heading5
certtool --generate-privkey --outfile ca-key.pem
cat << _EOF_ >ca.tmpl
cn = "stunnel.info VPN"
organization = "stunnel.info"
serial = 1
expiration_days = 365
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 = "stunnel.info VPN"
o = "stunnel"
serial = 2
expiration_days = 365
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

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

复制配置文件样本,还在源码目录中
cp doc/sample.config /usr/local/etc/ocserv/ocserv.conf
编辑配置文件
vim /usr/local/etc/ocserv/ocserv.conf

修改如下:
auth = "plain[/usr/local/etc/ocserv/ocpasswd]"
#ocserv支持多种认证方式,这是自带的密码认证,使用ocpasswd创建密码文件
#ocserv还支持证书认证,可以通过Pluggable Authentication Modules (PAM)使用radius等认证方式
server-cert = /usr/local/etc/ocserv/server-cert.pem
server-key = /usr/local/etc/ocserv/server-key.pem
#证书路径
max-same-clients = 10
#同一个用户最多同时登陆数
run-as-group = nobody
ipv4-network = 192.168.10.0
#分配给VPN客户端的IP段
dns = 8.8.8.8
dns = 8.8.4.4
#route = 192.168.1.0/255.255.255.0
#route = 192.168.5.0/255.255.255.0
#注释掉这两行。route参数留空表示所有流量均走VPN。
#ocserv可以给客户端下发路由表。比如可以把公司内网IP段、所有国外IP走VPN出去。
#default-domain = example.com
#注释掉这行。

创建认证用的用户文件
ocpasswd -c /usr/local/etc/ocserv/.passwd <username>

修改系统配置,允许转发
sed -i 's/net.ipv4.ip_forward = 0/net.ipv4.ip_forward = 1/g' /etc/sysctl.conf
sysctl -p
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o venet0 -j MASQUERADE
iptables -A FORWARD -s 192.168.10.0/24 -j ACCEPT
#IP段和venet0接口要根据自己的情况修改

最后运行服务
/usr/local/sbin/ocserv -c /usr/local/etc/ocserv/ocserv.conf
在iOS上安装Cisco AnyConnect即可连接服务器
Android上也有Cisco AnyConnect(需要root),不过Android可选择的太多,推荐Shadowsocks
Windows、MAC OS也有Cisco的官方客户端

参考:
http://www.infradead.org/ocserv/manual.html
http://ttz.im/blog/2014/02/1131
http://www.cisco.com/web/CN/solutions/trends/byod_smart_solution/pdf/at_a_glance_c45_578609.pdf
--------------------------------------------------
 架设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 xvf 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。)
sudo apt-get install build-essential pkg-config libgnutls28-dev libreadline-dev libseccomp-dev libpam0g-dev libwrap0-dev libnl-nf-3-dev
编译并安装。
./configure
(在我测试的环境里,最终报告只有systemd和dbus的结果为no,如果你发现其他项目显示no,不必担心,你的环境可能安装了可选的包导致出现不同结果。目前只有libgnutls28-dev是必须的模块。)
make
sudo make install

配置OCserv

我们希望做到的,是无需用户名与密码的客户端证书验证登陆。但在此之前,让我们先测通更简单的密码登录模式。首先让我们把CA证书与服务器证书生成好,具体步骤官方文档也有——
mkdir certificates
cd certificates
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,否则AnyConnect客户端将无法正确导入证书。
cn = "Your hostname or 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
确保以下配置正确
# 登陆方式,目前先用密码登录
auth = "plain[/etc/ocserv/ocpasswd]"
# 允许同时连接的客户端数量
max-clients = 4
# 限制同一客户端的并行登陆数量
max-same-clients = 2
# 服务监听的IP(服务器IP,可不设置)
listen-host = 1.2.3.4
# 服务监听的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 username
这样OCserv就基本配置好了。但如果你和我一样强化过服务器安全,还得为服务器上开些端口才行。以Linode的安全配置为例,我们需要加入和修改以下内容。
sudo nano /etc/iptables.firewall.rules
打开OCserv对应的TCP/UDP端口
-A INPUT -p tcp -m state --state NEW --dport 9000 -j ACCEPT
-A INPUT -p udp -m state --state NEW --dport 9001 -j ACCEPT
注释这行,允许转发
# -A FORWARD -j DROP
启用NAT
*nat
-A POSTROUTING -j MASQUERADE
COMMIT

完成之后导入新配置并检查配置正确。
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 /etc/sysctl.conf

测试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
重启OCserv服务,确认VPN无需密码就可以正常登陆。

小结

这篇笔记是在完成配置之后靠回忆写下的,仅仅做到“可用”,没做更多优化与安全配置。如有什么疏漏(很可能有,毕竟环境不可能完全一致),欢迎在留言栏相互协助。祝各位的iPhone生活美满~
参考阅读:
 -----------------------------------------------------------------------
在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 上安装,那么需要参考这文章安装 Nettle 和 Gnutls

安装 Ocserv

下载 Ocserv 0.3.2
wget ftp://ftp.infradead.org/pub/ocserv/ocserv-0.3.2.tar.xz
tar xvf ocserv-0.3.2.tar.xz
cd ocserv-0.3.2
安装编译依赖
sudo 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 
编译
./configure --prefix=/usr --sysconfdir=/etc && make && sudo 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
vim  server.tmpl

# 输入以下内容

cn = "www.example.com"
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地址,然后转换成我们需要的格式。
--------------------------------
 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 xvf 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

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

Let’s configure it as simple as possible like:
./configure --prefix=/opt/ocserv
...
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=/opt/ocserv --enable-local-libopts --enable-libopts-install

Install

Create config folder and copy sample config:
  
make install
mkdir /opt/ocserv/etc/
cp doc/sample.* /opt/ocserv/etc/

Create configurations

Certificate related: Generate Certificate with GnuTLS and Sign with OpenSSL:
  
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/
-----------------------------------------------------
 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 xvf 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 xvf ocserv-0.8.0.tar.xz
cd ocserv-0.8.0
LIBGNUTLS_CFLAGS="-I/opt/include/" LIBGNUTLS_LIBS="-L/opt/lib/ -lgnutls" LIBNL3_CFLAGS="-I/opt/include" LIBNL3_LIBS="-L/opt/lib/ -lnl-3 -lnl-route-3" ./configure --prefix=/opt/
make && make install

You may need to

export LD_LIBRARY_PATH=/opt/lib/:/opt/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

相关帖子:
翻墙工具OpenConnect server 0.8.9 一键安装脚本 for debian 7+ 

没有评论:

发表评论