本页内容

  • 准备工作
  • 第 1 步 - 配置防火墙
  • 第 2 步 - 安装 Git
  • 第 3 步 - 安装 OpenConnect
  • 第 4 步 - 生成 SSL 证书
  • 第 5 步 - 配置 OpenConnect
  • 第 6 步 - 启动 OpenConnect 服务器
  • 第 7 步 - 创建 VPN 账户
  • 第 8 步 - 启用 IP 转发
  • 第 9 步 - 配置 IP 伪装
  • 第 10 步 - 使用 OpenConnect 客户端连接
  • 结论

OpenConnect VPN(又称 ocserv)是一个开源免费的 VPN 解决方案,具备企业级性能和特性。它基于在企业界广泛使用的 Cisco AnyConnect VPN 协议。在本教程中,你将学习如何在 Ubuntu 22.04 机器上安装 OpenConnect VPN 服务器。你还将学习如何使用 OpenConnect 客户端连接到服务器。

准备工作

  • 一台运行 Ubuntu 22.04 的服务器。
  • 一个具有 sudo 权限的非 root 用户。
  • 一个完全限定域名(FQDN),例如 vpn.example.com。
  • 确保所有软件包均为最新。$ sudo apt update $ sudo apt upgrade
  • 系统需要安装的几个软件包。$ sudo apt install wget curl nano software-properties-common dirmngr apt-transport-https gnupg2 ca-certificates lsb-release ubuntu-keyring unzip -y 其中部分软件包可能已在你的系统上安装。

一台运行 Ubuntu 22.04 的服务器。

一个具有 sudo 权限的非 root 用户。

一个完全限定域名(FQDN),例如 vpn.example.com。

确保所有软件包均为最新。

$ sudo apt update
$ sudo apt upgrade

系统需要安装的几个软件包。

$ sudo apt install wget curl nano software-properties-common dirmngr apt-transport-https gnupg2 ca-certificates lsb-release ubuntu-keyring unzip -y

其中部分软件包可能已在你的系统上安装。

第 1 步 - 配置防火墙

第一步是配置防火墙。Ubuntu 默认自带 ufw(Uncomplicated Firewall,简易防火墙)。

检查防火墙是否正在运行。

$ sudo ufw status

你应该会看到如下输出。

Status: inactive

放行 SSH 端口,以免启用防火墙时断开当前连接。

$ sudo ufw allow OpenSSH

同时放行 HTTP 和 HTTPS 端口。

$ sudo ufw allow http
$ sudo ufw allow https

启用防火墙

$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

再次检查防火墙状态。

$ sudo ufw status

你应该会看到类似的输出。

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443                        ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)

第 2 步 - 安装 Git

第 3 步 - 安装 OpenConnect

Ubuntu 22.04 自带较旧版本的 OpenConnect(1.1.3)。如果你对此满意,可以使用以下命令安装它。

$ sudo apt install ocserv

不过,在本教程中我们将安装最新版本的 OpenConnect(1.1.6)。为此,我们需要从源码编译安装。

安装编译源码所需的依赖项。

$ sudo apt install -y libgnutls28-dev libev-dev libpam0g-dev liblz4-dev libseccomp-dev \
	libreadline-dev libnl-route-3-dev libkrb5-dev libradcli-dev \
	libcurl4-gnutls-dev libcjose-dev libjansson-dev libprotobuf-c-dev \
	libtalloc-dev libhttp-parser-dev protobuf-c-compiler gperf \
	nuttcp lcov libuid-wrapper libpam-wrapper libnss-wrapper \
	libsocket-wrapper gss-ntlmssp haproxy iputils-ping freeradius \
	gawk gnutls-bin iproute2 yajl-tools tcpdump autoconf automake

克隆 ocserv 的 Git 仓库。

$ git clone https://gitlab.com/openconnect/ocserv.git

切换到克隆下来的目录。

$ cd ocserv

生成配置脚本。

$ autoreconf -fvi

编译源码。忽略任何弃用警告。

$ ./configure && make

安装 ocserv。

$ sudo make install

文件将被安装到 /usr/local/bin 和 /usr/local/sbin 目录。复制 systemd 服务文件。

$ sudo cp doc/systemd/standalone/ocserv.service /etc/systemd/system/ocserv.service

打开服务文件进行编辑。

$ sudo nano /etc/systemd/system/ocserv.service

将下面这一行中 ocserv 二进制文件的路径

$ ExecStart=/usr/sbin/ocserv --foreground --pid-file /run/ocserv.pid --config /etc/ocserv/ocserv.conf

改为以下内容。

$ ExecStart=/usr/local/sbin/ocserv --foreground --pid-file /run/ocserv.pid --config /etc/ocserv/ocserv.conf

按下 Ctrl + X 保存文件,并在提示时输入 Y。

重新加载 systemd 守护进程。

$ sudo systemctl daemon-reload

第 4 步 - 生成 SSL 证书

我们需要安装 Certbot 来生成 SSL 证书。你可以使用 Ubuntu 官方仓库安装 Certbot,也可以通过 Snapd 工具获取最新版本。本教程将使用 Snapd 版本。

Ubuntu 22.04 默认已安装 Snapd。运行以下命令确保你的 Snapd 版本为最新。

$ sudo snap install core && sudo snap refresh core

安装 Certbot。

$ sudo snap install --classic certbot

使用以下命令,通过创建指向 /usr/bin 目录的符号链接,确保 Certbot 命令可以运行。

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

生成 SSL 证书有两种情况。如果你的系统上没有运行 Web 服务器,可以使用 standalone 方式生成证书。运行以下命令,使用 Certbot 的 standalone 插件创建证书。

$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m 
[email protected]
 -d vpn.example.com

上述命令会将证书下载到服务器上的 /etc/letsencrypt/live/vpn.example.com 目录。

接下来,如果你的系统上运行着 Web 服务器,你可以使用 webroot 插件,或者你正在使用的 Nginx 或 Apache 插件。对于 Nginx 或 Apache 服务器,只需运行下面的命令即可。

$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m 
[email protected]
 -d vpn.example.com

或

$ sudo certbot certonly --apache --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m 
[email protected]
 -d vpn.example.com

如果你使用其他服务器,则需要使用 webroot 插件。为此,请创建 Web 根目录。

$ sudo mkdir -p /var/www/ocserv

将服务器用户设置为 Web 根目录的所有者。在本例中,我们使用 www-data 作为服务器用户。

$ sudo chown www-data:www-data /var/www/ocserv -R

接下来,将你的服务器配置为在 /var/www/ocserv 目录为域名 vpn.example.com 提供服务。重启服务器。然后使用以下命令生成证书。

$ sudo certbot certonly --webroot --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m 
[email protected]
 -d vpn.example.com

检查 Certbot 续期调度服务。

$ sudo systemctl list-timers

你会发现 snap.certbot.renew.service 是计划运行的服务之一。

NEXT                        LEFT          LAST                        PASSED        UNIT                       ACTIVATES
Wed 2023-04-19 10:31:47 UTC 2h 55min left Wed 2023-04-19 03:31:58 UTC 4h 3min ago   ua-timer.timer             ua-timer.service
Wed 2023-04-19 12:02:42 UTC 4h 26min left Wed 2023-04-19 03:19:20 UTC 4h 16min ago  motd-news.timer            motd-news.service
Wed 2023-04-19 18:19:56 UTC 10h left      Wed 2023-04-19 07:19:52 UTC 16min ago     apt-daily.timer            apt-daily.service
Wed 2023-04-19 22:51:00 UTC 15h left      n/a                         n/a           snap.certbot.renew.timer   snap.certbot.renew.service

对流程进行一次模拟运行,检查 SSL 续期是否正常工作。

$ sudo certbot renew --dry-run

如果没有看到错误,说明一切就绪。你的证书将自动续期。

第 5 步 - 配置 OpenConnect

如果你是通过 APT 安装的 ocserv,那么配置文件应当已经位于 /etc/ocserv/ocserv.conf。但如果你是从源码编译安装的,则需要复制配置文件。

创建存放配置文件的目录。

$ sudo mkdir /etc/ocserv

复制配置文件。

$ sudo cp /home/username/ocserv/doc/sample.config /etc/ocserv/ocserv.conf

打开该文件进行编辑。

$ sudo nano /etc/ocserv/ocserv.conf

将 auth 参数的值改为以下内容。这将允许用户使用独立的 VPN 账户。

auth = "plain[passwd=/etc/ocserv/ocpasswd]"

默认情况下,OpenConnect 同时使用 443 的 TCP 和 UDP 端口。我们将仅使用 TCP 端口进行连接,因此通过注释将其禁用 UDP 端口。

tcp-port = 443
#udp-port = 443

如果你有 Web 服务器运行在 443 端口上,则通过修改该值来更改 TCP 端口的值。

tcp-port = 8443

接下来,找到 server-crt 和 server-key 变量,并按如下方式修改它们的值。

server-cert = /etc/letsencrypt/live/vpn.example.com/fullchain.pem
server-key = /etc/letsencrypt/live/vpn.example.com/privkey.pem

设置允许的最大客户端数量。默认值为 16。设为 0 表示不限制。

max-clients = 16

设置单个用户可同时使用的设备数量。默认值为 2。设为 0 表示不限制。

max-same-clients = 2

默认情况下,OpenConnect 每 9 小时(32400 秒)发送一次 keepalive 数据包。这个值过高。将其设置为 60 秒,以降低 VPN 连接掉线的概率。

keepalive = 60

将 try-mtu-discovery 的值改为 true 以启用 MTU 发现。它可以优化 VPN 性能。

try-mtu-discovery = true

通过取消注释以下变量,设置客户端在断开连接前允许保持空闲的时间。如果你希望客户端无限期保持连接,则保持原样即可。

idle-timeout=1200
mobile-idle-timeout=1800

设置 OpenConnect VPN 的默认域名。

default-domain = vpn.example.com

修改默认的 IPv4 配置以避免 IP 地址冲突。我们将使用 10.10.10.0 作为取值。

ipv4-network = 10.10.10.0

取消注释以下行,以通过 VPN 隧道转发所有 DNS 查询。

tunnel-all-dns = true

将 DNS 解析器改为 Google DNS。同时添加第二条记录。

dns = 8.8.8.8
dns = 8.8.4.4

通过在前面添加井号(#)注释掉所有 route 参数。

#route = 10.10.10.0/255.255.255.0
#route = 192.168.0.0/255.255.0.0
#route = fef4:db8:1000:1001::/64
#route = default

# Subsets of the routes above that will not be routed by
# the server.

#no-route = 192.168.5.0/255.255.255.0

按下 Ctrl + X 保存文件,并在提示时输入 Y。

第 6 步 - 启动 OpenConnect 服务器

启动 OpenConnect VPN 服务器。

$ sudo systemctl start ocserv

检查服务状态。

$ sudo systemctl status ocserv

你会看到类似的输出。

? ocserv.service - OpenConnect SSL VPN server
     Loaded: loaded (/etc/systemd/system/ocserv.service; disabled; vendor preset: enabled)
     Active: active (running) since Thu 2023-04-20 08:52:18 UTC; 2s ago
       Docs: man:ocserv(8)
   Main PID: 19965 (ocserv-main)
      Tasks: 2 (limit: 1026)
     Memory: 1.4M
        CPU: 9ms
     CGroup: /system.slice/ocserv.service
             ??19965 ocserv-main  
             ??19966 ocserv-sm 

Apr 20 08:52:18 openconnect ocserv[19965]: note: skipping 'pid-file' config option
Apr 20 08:52:18 openconnect ocserv[19965]: note: vhost:default: setting 'plain' as primary authentication method
Apr 20 08:52:18 openconnect ocserv[19965]: error connecting to sec-mod socket '/var/run/ocserv-socket.a4413bc9': No such file or directory
Apr 20 08:52:18 openconnect ocserv[19965]: note: setting 'file' as supplemental config option
Apr 20 08:52:18 openconnect ocserv[19965]: listening (TCP) on 0.0.0.0:443...
Apr 20 08:52:18 openconnect ocserv[19965]: listening (TCP) on [::]:443...
Apr 20 08:52:18 openconnect ocserv[19966]: ocserv[19966]: sec-mod: reading supplemental config from files
Apr 20 08:52:18 openconnect ocserv[19966]: sec-mod: reading supplemental config from files
Apr 20 08:52:18 openconnect ocserv[19966]: ocserv[19966]: sec-mod: sec-mod initialized (socket: /var/run/ocserv-socket.a4413bc9.0)
Apr 20 08:52:18 openconnect ocserv[19966]: sec-mod: sec-mod initialized (socket: /var/run/ocserv-socket.a4413bc9.0)

如果你看到有关连接 sec-mod socket 的错误,请忽略它。这是正常现象。如果找不到该文件,它会进行初始化。

第 7 步 - 创建 VPN 账户

你可以使用 ocpasswd 工具创建 VPN 账户。运行以下命令创建一个新的 VPN 账户。

$ sudo ocpasswd -c /etc/ocserv/ocpasswd username
Enter password:
Re-enter password:

密码将被保存到 /etc/ocserv/ocpasswd 文件。要重置该用户的密码,请再次运行上述命令。使用不同的用户运行上述命令即可创建另一个账户。

第 8 步 - 启用 IP 转发

为了让 VPN 服务器在客户端与互联网之间路由数据包,你需要通过运行以下命令启用 IP 转发。

$ echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/60-custom.conf

运行以下命令以启用 TCP BBR 算法来提升 TCP 速度。

$ echo "net.core.default_qdisc=fq" | sudo tee -a /etc/sysctl.d/60-custom.conf
$ echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.d/60-custom.conf

使用以下命令使更改永久生效。

$ sudo sysctl -p /etc/sysctl.d/60-custom.conf

第 9 步 - 配置 IP 伪装

下一步是在防火墙中设置 IP 伪装,使 VPN 服务器可以作为客户端的虚拟路由器。找出服务器主网络接口的名称。

$ ip addr

你会看到类似的输出。

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
    link/ether 56:00:04:67:7e:79 brd ff:ff:ff:ff:ff:ff
    inet 95.179.138.135/23 metric 100 brd 95.179.139.255 scope global dynamic enp1s0
       valid_lft 66999sec preferred_lft 66999sec
    inet6 2a05:f480:1400:2381:5400:4ff:fe67:7e79/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 2591657sec preferred_lft 604457sec
    inet6 fe80::5400:4ff:fe67:7e79/64 scope link
       valid_lft forever preferred_lft forever

在本例中,enp1s0 是接口的名称。打开 UFW 配置文件进行编辑,在其中添加 iptables 命令。

$ sudo nano /etc/ufw/before.rules

在文件末尾添加以下行。请将代码中的 enp1s0 替换为你的网络接口。

# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.10.10.0/24 -o enp1s0 -j MASQUERADE

# End each table with the 'COMMIT' line or these rules won't be processed
COMMIT

在文件中找到以下几行。

# ok icmp code for FORWARD
-A ufw-before-forward -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type echo-request -j ACCEPT

在其后粘贴以下几行。

# allow forwarding for trusted network
-A ufw-before-forward -s 10.10.10.0/24 -j ACCEPT
-A ufw-before-forward -d 10.10.10.0/24 -j ACCEPT

在 Ubuntu 22.04 系统上安装搭建 OpenConnect VPN 服务器详细教程

按下 Ctrl + X 保存文件,并在提示时输入 Y。

重启防火墙。

$ sudo systemctl restart ufw

你可以使用以下命令检查伪装规则。

$ sudo iptables -t nat -L POSTROUTING

你会看到以下输出。

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  10.10.10.0/24        anywhere

第 10 步 - 使用 OpenConnect 客户端连接

我们将在 Ubuntu 22.04 机器上安装 OpenConnect 客户端。运行以下命令安装客户端。

$ sudo apt install openconnect

接下来,使用以下命令连接到 VPN 服务器。-b 参数会使客户端在连接建立后于后台运行。

$ sudo openconnect -b vpn.example.com:443

系统会要求你输入 VPN 用户名和密码。请输入在第 7 步创建的凭据。

POST https://vpn.example.com/
Connected to 95.179.138.135:443
SSL negotiation with vpn.example.com
Connected to HTTPS on vpn.example.com with ciphersuite (TLS1.3)-(ECDHE-SECP256R1)-(ECDSA-SECP256R1-SHA256)-(AES-256-GCM)
XML POST enabled
Please enter your username.
Username:navjot
POST https://vpn.example.com/auth
Please enter your password.
Password:
POST https://vpn.example.com/auth

连接成功时,你会看到如下输出。由于我们禁用了 UDP,DTLS 也被禁用。

Got CONNECT response: HTTP/1.1 200 CONNECTED
CSTP connected. DPD 90, Keepalive 60
No DTLS address
Set up UDP failed; using SSL instead
Configured as 192.168.1.13, with SSL connected and DTLS disabled
Continuing in background; pid 1650

运行以下命令以停止连接。

$ sudo pkill openconnect

我们为 OpenConnect 创建一些 systemd 脚本。第一个脚本用于在系统启动时让客户端自动连接。

创建并打开服务文件进行编辑。

$ sudo nano /etc/systemd/system/openconnect.service

在其中粘贴以下代码。

[Unit]
  Description=OpenConnect VPN Client
  After=network-online.target systemd-resolved.service
  Wants=network-online.target

[Service]
  Type=simple
  ExecStart=/bin/bash -c '/bin/echo -n password | /usr/sbin/openconnect vpn.example.com -u username --passwd-on-stdin'
  KillSignal=SIGINT
  Restart=always
  RestartSec=2

[Install]
  WantedBy=multi-user.target

按下 Ctrl + X 保存文件,并在提示时输入 Y。

启用该服务。

$ sudo systemctl enable openconnect.service

启动该服务。

$ sudo systemctl start openconnect.service

要在电脑从挂起状态恢复时自动重新连接 VPN,你需要创建另一个 systemd 脚本。

创建并打开重启脚本进行编辑。

$ sudo nano /etc/systemd/system/openconnect-restart.service

在其中粘贴以下代码。

[Unit]
Description=Restart OpenConnect client when resuming from suspend
After=suspend.target

[Service]
Type=simple
ExecStart=/bin/systemctl --no-block restart openconnect.service

[Install]
WantedBy=suspend.target

按下 Ctrl + X 保存文件,并在提示时输入 Y。

启用该服务。

$ sudo systemctl enable openconnect-restart.service

我们还可以创建一个服务,在 VPN 连接断开时自动重连。创建并打开 VPN 检测服务进行编辑。

$ sudo nano /etc/systemd/system/openconnect-check.service

在其中粘贴以下代码。

[Unit]
Description=OpenConnect VPN Connectivity Checker
After=openconnect.service

[Service]
Type=simple
ExecStart=/bin/bash -c 'for ((; ; )) do (ping -c9 10.10.10.1 || systemctl restart openconnect) done'

[Install]
WantedBy=multi-user.target

按下 Ctrl + X 保存文件,并在提示时输入 Y。

启用并启动该服务。

$ sudo systemctl enable enable openconnect-check.service --now

这将持续运行 ping 命令来检测 VPN 连接。如果连接断开,它会自动重启 OpenConnect。

如果需要,你可以下载 OpenConnect GUI 客户端。不过它们已经很久没有更新了。如果你想要更新版 GUI 客户端,可以访问 OpenConnect GUI 的 GitLab 仓库自行编译。

结论

至此,我们已经完成了关于在 Ubuntu 22.04 服务器上安装 OpenConnect VPN 服务器并使用命令行客户端连接它的教程。如果你有任何疑问,请在下方评论区留言。