Openconnect服务器(ocserv)是一个SSL VPN服务器,适用于需要细致进行用户管理和控制。Openconnect服务器提供企业环境中所需的用户管理界面和后端,以及安全功能,例如隔离连接的客户端,以及现有VPN服务器都不具备的功能。
它是如何工作的?

个人理解与WireGuard对比,它的验证更为丰富,更为精确的支持为每个客户端或客户端组设置资源限制,带宽,网络优先级等。但这并不是说ocserv要比WireGuard要好,主要还是看使用场合吧,在一个多用户(甚至超过2000人)办公场合,对于管理员来说前者显然是更好的选择;而对于需要连接到有N多云服务器的环境来说,WireGuard要更好。两者都是非常安全且实用的工具,不同点只是使用场景不一而已,所以也记录一下ocserv服务的部署吧。

安装
可以通过编译或者包管理器进行安装,截止目前,Ubuntu 18.04.2 LTS默认源的版本为0.11.9,而debian源的版本相对较新。
通过包管理器可以快速的安装,只需使用命令
1
2
|
sudo apt-get update
sudo apt-get install ocserv
|
即可完成安装。
本人使用的是Ubuntu,因为想使用官方最新版本,所以只有通过编译源码的方式进行。
下载
官方提供FTP服务进行下载,当然了也可以到gitlab拉取源码,或者根据tag进行下载。
截止当前最新发布的版本为0.12.3
1
2
|
wget ftp://ftp.infradead.org/pub/ocserv/ocserv-0.12.3.tar.xz
tar Jxf ocserv-0.12.3.tar.xz
|
依赖安装
准备编译环境,需要安装一些依赖:
1
2
3
4
|
sudo apt-get install build-essential pkg-config \
libgnutls28-dev libev-dev \
libpam0g-dev liblz4-dev libseccomp-dev libreadline-dev \
liboath-dev
|
编译
配置编译
1
2
|
cd ocserv-0.12.3
./configure && make && make check
|
上面的命令包含编译后的测试,测试结果理论上不应该含错误信息,例如:
1
2
3
4
5
6
7
8
9
10
11
|
============================================================================
Testsuite summary for ocserv 0.12.3
============================================================================
# TOTAL: 47
# PASS: 14
# SKIP: 33
# XFAIL: 0
# FAIL: 0
# XPASS: 0
# ERROR: 0
============================================================================
|
下一步使用sudo make install
进行安装即可.
安装的工具包含
- ocserv: /usr/local/sbin/ocserv 主服务应用程序
- occtl: /usr/local/bin/occtl 服务器的控制工具。允许用户查询服务器的信息
- ocpasswd: /usr/local/bin/ocpasswd 一个管理简单密码文件的工具
启动文件
默认的systemd文件没有被安装,它在如下位置:
1
2
|
./doc/systemd/standalone/ocserv.service
./doc/systemd/socket-activated/ocserv.service
|
当使用standalone文件时
1
2
|
sudo cp ./doc/systemd/standalone/ocserv.service /lib/systemd/system/
sudo systemctl enable ocserv
|
而socket模式时,端口会被init占用并一直保留,直到将其socket也停止后才被释放。
当我刚开始使用包管理器安装并开启服务时,检查ocserv默认443端口返回是这样的:
sudo netstat -ntlp | grep :443
tcp6 0 0 :::443 :::* LISTEN 1/init
而当使用sudo systemctl stop ocserv
后,被提示
Warning: Stopping ocserv.service, but it can still be activated by:
ocserv.socket
使用命令行方式启用被提示端口被占用,查看443端口依旧是上面的结果。
这里正确的终止命令应该是sudo systemctl stop ocserv.socket
如果要使用这种模式请这样复制systemd文件
1
2
|
sudo cp ./doc/systemd/socket-activated/ocserv* /lib/systemd/system/
sudo systemctl enable ocserv.socket
|
或者,习惯使用init方式的,使用这个脚本即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
sudo sh -c 'umask 077; cat > /etc/init.d/ocserv' <<EOF
#! /bin/sh
### BEGIN INIT INFO
# Provides: ocserv
# Required-Start: $remote_fs $syslog dbus
# Required-Stop: $remote_fs $syslog dbus
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: OpenConnect SSL VPN server
# Description: secure, small, fast and configurable OpenConnect SSL VPN server
### END INIT INFO
set -e
NAME=ocserv
DESC="OpenConnect SSL VPN server"
DAEMON=/usr/sbin/ocserv
DAEMON_CONFIG=/etc/${NAME}/${NAME}.conf
DAEMON_PIDFILE=/var/run/${NAME}.pid
DAEMON_ARGS="--pid-file $DAEMON_PIDFILE --config $DAEMON_CONFIG"
test -x $DAEMON || exit 0
umask 022
. /lib/lsb/init-functions
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
daemon_start()
{
if [ ! -s "$DAEMON_CONFIG" ]; then
log_failure_msg "please create ${DAEMON_CONFIG}, not starting..."
log_end_msg 1
exit 0
fi
log_daemon_msg "Starting $DESC" "$NAME" || true
if start-stop-daemon --start --quiet --oknodo --pidfile $DAEMON_PIDFILE --exec $DAEMON -- $DAEMON_ARGS ; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
}
case "$1" in
start)
daemon_start
;;
stop)
log_daemon_msg "Stopping $DESC" "$NAME" || true
if start-stop-daemon --stop --quiet --oknodo --pidfile $DAEMON_PIDFILE; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;;
reload|force-reload)
log_daemon_msg "Reloading $DESC" "$NAME" || true
if start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile $DAEMON_PIDFILE --exec $DAEMON; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;;
restart)
log_daemon_msg "Restarting $DESC" "$NAME" || true
start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile $DAEMON_PIDFILE
daemon_start
;;
try-restart)
log_daemon_msg "Restarting $DESC" "$NAME" || true
RET=0
start-stop-daemon --stop --quiet --retry 30 --pidfile $DAEMON_PIDFILE || RET="$?"
case $RET in
0)
# old daemon stopped
daemon_start
;;
1)
# daemon not running
log_progress_msg "(not running)" || true
log_end_msg 0 || true
;;
*)
# failed to stop
log_progress_msg "(failed to stop)" || true
log_end_msg 1 || true
;;
esac
;;
status)
status_of_proc -p $DAEMON_PIDFILE $DAEMON $NAME && exit 0 || exit $?
;;
*)
log_action_msg "Usage: /etc/init.d/$NAME {start|stop|reload|force-reload|restart|try-restart|status}" || true
exit 1
esac
exit 0
EOF
sudo sh -c "chmod +x /etc/init.d/ocserv"
|
默认证书
即将编辑的配置文件当中,需要使用到CA证书以及服务器秘钥和证书,在刚开始配置的时候可以先使用默认的证书。
从编译目录拷贝到指定目录当中:
1
2
3
4
|
sudo mkdir -p /etc/ocserv/certs
sudo cp ./tests/certs/ca.pem /etc/ocserv/certs
sudo cp ./tests/certs/server-cert-ca.pem /etc/ocserv/certs
sudo cp ./tests/certs/server-key.pem /etc/ocserv/certs
|
配置文件
同样的,配置文件也没有被安装。你可以在./doc/sample.config
找到它,官网的文档首页也提供了一个标准的配置文件。
这里简略掉了说明直接写入配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
sudo cp ./doc/profile.xml /etc/ocserv
sudo sh -c 'umask 077; cat > /etc/ocserv/ocserv.conf' <<EOF
auth = "pam[gid-min=1000]"
# TCP and UDP port number
tcp-port = 443
udp-port = 443
run-as-user = nobody
run-as-group = daemon
#使用haproxy时取消注释
#listen-clear-file = /var/run/ocserv-conn.socket
socket-file = ocserv.sock
chroot-dir = /etc/ocserv
server-cert = /etc/ocserv/certs/server-cert-ca.pem
server-key = /etc/ocserv/certs/server-key.pem
ca-cert = /etc/ocserv/certs/ca.pem
isolate-workers = true
banner = "Welcome~"
max-clients = 16
max-same-clients = 2
#使用haproxy时取消注释
#listen-proxy-proto = true
keepalive = 32400
dpd = 90
mobile-dpd = 1800
switch-to-tcp-timeout = 25
try-mtu-discovery = true
cert-user-oid = 2.5.4.3
compression = true
no-compress-limit = 256
#禁用tls1.0和1.1
tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1"
auth-timeout = 240
min-reauth-time = 12
max-ban-score = 50
ban-reset-time = 300
cookie-timeout = 300
persistent-cookies = true
deny-roaming = false
rekey-time = 172800
rekey-method = ssl
use-utmp = true
use-occtl = true
pid-file = /var/run/ocserv.pid
device = vpns
predictable-ips = true
default-domain = 2333.lvmoo.com
ipv4-network = 192.168.7.0
ipv4-netmask = 255.255.255.0
dns = 192.168.7.2
ping-leases = false
route = 10.10.10.0/255.255.255.0
route = 192.168.0.0/255.255.0.0
no-route = 192.168.5.0/255.255.255.0
cisco-client-compat = true
dtls-legacy = true
#user-profile = profile.xml
[vhost:vpn.lvmoo.com]
auth = "plain[passwd=/etc/ocserv/ocserv.passwd]"
server-cert = /etc/ocserv/certs/server-cert-ca.pem
server-key = /etc/ocserv/certs/server-key.pem
ca-cert = /etc/ocserv/certs/ca.pem
ipv4-network = 192.168.8.0
ipv4-netmask = 255.255.255.0
cert-user-oid = 0.9.2342.19200300.100.1.1
EOF
|
至此,配置文件告一段落。
转发&防火墙设置
进行到这,使用客户端进行连接后通常来说,依旧无法正常使用的。
因为系统默认是不打开转发的,可以使用以下方式查看转发状态:
执行sysctl net.ipv4.ip_forward
或者cat /proc/sys/net/ipv4/ip_forward
又或者sudo sysctl -a | grep ip_forward
返回值为0的话就代表转发状态被关闭了。
可以临时修改设置检查联通性sudo sysctl -w net.ipv4.ip_forward=1
当然推荐修改配置永久修改状态
1
2
|
sed -i '/net.ipv4.ip_forward.*/d;$a\net.ipv4.ip_forward = 1' /etc/sysctl.conf
sysctl -p
|
而后修改防火墙NAT设置等,注意网络接口
1
2
3
4
|
sudo iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -I INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -I INPUT -p udp --dport 443 -j ACCEPT
|
这样,就算配置完成了
测试&启动
完成了以上全部环节之后,在启动前可以先做一个测试,以便排查某个步骤出现的问题:
1
|
sudo ocserv -c /etc/ocserv/ocserv.conf -f -d 1
|
返回的日志当中不应当出现error信息,否则你可能需要根据报错信心排查问题了。
一切就绪之后通过sudo systemctl start ocserv
即可启动服务了。
occtl的使用
关于occtl的使用可以查看官方的文档
使用occtl show users
列出当前的用户连接状态
使用occtl --json show users
json格式打印最为详细的连接信息。