本页内容
- 先决条件
- 步骤 1 - 搭建 CA 服务器 步骤 1.1 - 安装 Easy-RSA 步骤 1.2 - 创建公钥基础设施目录 步骤 1.3 - 创建证书颁发机构
- 步骤 2 - 在 OpenVPN 服务器上安装 OpenVPN 和 Easy-RSA
- 步骤 3 - 为 OpenVPN 服务器创建 PKI
- 步骤 4 - 创建 OpenVPN 服务器证书请求和私钥
- 步骤 5 - 签署 OpenVPN 服务器的 CSR
- 步骤 6 - 配置 OpenVPN 加密材料
- 步骤 7 - 生成客户端证书和密钥对
- 步骤 8 - 配置 OpenVPN 通过 VPN 重定向全部流量 更改端口和协议 指向非默认凭据
- 步骤 9 - 调整 OpenVPN 服务器网络配置
- 步骤 10 - 配置防火墙
- 步骤 11 - 启动 OpenVPN
- 步骤 12 - 创建客户端配置
- 步骤 13 - 安装并测试客户端连接 连接客户端
- 步骤 14 - 撤销客户端证书
- 结语
- 步骤 1.1 - 安装 Easy-RSA
- 步骤 1.2 - 创建公钥基础设施目录
- 步骤 1.3 - 创建证书颁发机构
- 通过 VPN 重定向全部流量
- 更改端口和协议
- 指向非默认凭据
- 连接客户端
虚拟专用网络(VPN)可以隐藏你的位置来访问互联网,让你在不信任的网络上安全地访问互联网,并规避地理限制和审查。OpenVPN 是一个开源的传输层安全(TLS)VPN 解决方案,可实现这一目标。
在本教程中,我们将在一台 Ubuntu 22.04 服务器上安装 OpenVPN,将其配置为可从客户端机器访问,并在两者之间建立 VPN 连接,将客户端的所有流量通过 OpenVPN 服务器进行转发。
先决条件
- 一台运行 Ubuntu 22.04 的服务器,需同时支持 IPv4 和 IPv6 连接。我们将其称为 OpenVPN 服务器。该服务器上已启用并运行 uncomplicated Firewall(UFW)。
- 一台运行 Ubuntu 22.04 的服务器,需同时支持 IPv4 和 IPv6 连接。我们将其配置为私有证书颁发机构(CA),并称之为 CA 服务器。
- 在 OpenVPN 服务器和 CA 服务器上均具有 sudo 权限的非 root 用户。
- 用于连接 OpenVPN 服务器的客户端机器。你可以使用本地设备作为客户端机器。OpenVPN 提供适用于 Windows、Linux、macOS、Android 和 iOS 的客户端,你可以使用其中任意一种进行连接。本教程中我们将使用一台 Ubuntu 22.04 客户端电脑。
- OpenVPN 服务器和 CA 服务器上的所有软件均已更新。$ sudo apt update && sudo apt upgrade
一台运行 Ubuntu 22.04 的服务器,需同时支持 IPv4 和 IPv6 连接。我们将其称为 OpenVPN 服务器。该服务器上已启用并运行 uncomplicated Firewall(UFW)。
一台运行 Ubuntu 22.04 的服务器,需同时支持 IPv4 和 IPv6 连接。我们将其配置为私有证书颁发机构(CA),并称之为 CA 服务器。
在 OpenVPN 服务器和 CA 服务器上均具有 sudo 权限的非 root 用户。
用于连接 OpenVPN 服务器的客户端机器。你可以使用本地设备作为客户端机器。OpenVPN 提供适用于 Windows、Linux、macOS、Android 和 iOS 的客户端,你可以使用其中任意一种进行连接。本教程中我们将使用一台 Ubuntu 22.04 客户端电脑。
OpenVPN 服务器和 CA 服务器上的所有软件均已更新。
$ sudo apt update && sudo apt upgrade
步骤 1 - 搭建 CA 服务器
证书颁发机构(CA)是负责颁发数字证书以验证互联网上身份的实体。在本教程中,我们将使用一台独立的服务器作为私有 CA 服务器,用于验证 OpenVPN 服务器和客户端的证书。你的 CA 服务器除了导入、签署和验证证书之外,不应运行任何其他服务。
步骤 1.1 - 安装 Easy-RSA
第一步是安装 easy-rsa 脚本集。easy-rsa 是一个证书颁发机构管理工具,用于生成私钥和公共根证书。
$ sudo apt install easy-rsa
步骤 1.2 - 创建公钥基础设施目录
下一步是在 CA 服务器上创建一个公钥基础设施(PKI)的骨架。
$ mkdir ~/easy-rsa
创建指向已安装的 easy-rsa 软件包文件的符号链接。
$ ln -s /usr/share/easy-rsa/* ~/easy-rsa/
限制对 PKI 目录的访问权限。
$ chmod 700 /home/<username>/easy-rsa
初始化 PKI。
$ cd ~/easy-rsa
$ ./easyrsa init-pki
你将看到如下输出。
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /home/<username>/easy-rsa/pki
步骤 1.3 - 创建证书颁发机构
在创建 CA 的私钥和证书之前,你需要为其配置组织信息。在 easy-rsa 目录中创建一个 vars 文件来存储这些信息,并打开它进行编辑。
$ cd ~/easy-rsa
$ nano vars
将以下代码粘贴到其中。
set_var EASYRSA_REQ_COUNTRY "US"
set_var EASYRSA_REQ_PROVINCE "NewYork"
set_var EASYRSA_REQ_CITY "New York City"
set_var EASYRSA_REQ_ORG "Example"
set_var EASYRSA_REQ_EMAIL "
[email protected]
"
set_var EASYRSA_REQ_OU "Community"
set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"
按 Ctrl + X,并在提示时输入 Y 保存文件。
运行以下命令为你的证书颁发机构创建根公钥和私钥对。
$ ./easyrsa build-ca
系统会提示你为密钥对输入一个密码短语。请选择一个强密码短语并记下以备后用。系统还会要求你为 CA 输入通用名称(CN)。你可以输入任意字符串,但为简便起见,按 ENTER 键接受默认名称即可。
Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
Enter New CA Key Passphrase:
Re-Enter New CA Key Passphrase:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:
CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/home/<username>/easy-rsa/pki/ca.crt
如果你不希望在每次与 CA 交互时都被要求输入密码,可以使用以下命令代替。
$ ./easyrsa build-ca nopass
这将创建两个文件:
- ~/easy-rsa/pki/ca.crt 是 CA 的公钥证书文件。每个用户以及 OpenVPN 服务器都需要该文件的一份副本。
- ~/easy-rsa/pki/ca.key 是 CA 用于对 OpenVPN 服务器和客户端的证书进行签名的私钥。如果攻击者获取了你的 CA,进而获取了你的 ca.key 文件,你将需要销毁你的 CA。因此,你的 ca.key 文件只应存放在 CA 机器上,并且理想情况下,CA 机器在不签署证书请求时应保持离线,以此作为额外的安全措施。
步骤 2 - 在 OpenVPN 服务器上安装 OpenVPN 和 Easy-RSA
登录到你的 OpenVPN 服务器并安装 OpenVPN 和 Easy-RSA 软件包。
$ sudo apt install openvpn easy-rsa
创建目录 ~/easy-rsa 。
$ mkdir ~/easy-rsa
像在 CA 服务器上一样,从我们刚刚安装的 easy-rsa 脚本创建符号链接。
$ ln -s /usr/share/easy-rsa/* ~/easy-rsa/
限制对该目录的访问权限。
$ chmod 700 ~/easy-rsa
步骤 3 - 为 OpenVPN 服务器创建 PKI
在 ~/easy-rsa 目录中创建一个 vars 文件,用于存储创建 PKI 所需的信息,并打开它进行编辑。
$ cd ~/easy-rsa
$ nano vars
将以下行粘贴到其中。
set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"
由于我们未将此服务器用作 CA,因此我们只需要这两个值。这将配置你的 OpenVPN 和 CA 服务器使用 ECC(椭圆曲线加密),这意味着当客户端和服务器尝试建立共享对称密钥时,它们使用椭圆曲线算法进行交换。由于数字更小且计算更快,它比使用经典 RSA 算法配合普通 Diffie-Hellman 显著更快。
下一步是使用 init-pki 选项创建 PKI 目录。尽管你作为先决条件的一部分已在 CA 服务器上运行过此命令,但此处仍须运行它,因为你的 OpenVPN 服务器和 CA 服务器拥有各自独立的 PKI 目录。
$ ./easyrsa init-pki
OpenVPN 服务器上的 PKI 用作存储证书请求和公共证书的集中位置。
步骤 4 - 创建 OpenVPN 服务器证书请求和私钥
切换到 OpenVPN 服务器上的 ~/easy-rsa 目录。
$ cd ~/easy-rsa
下一步是在你的 OpenVPN 服务器上生成私钥和证书签名请求(CSR)。运行 easy-rsa 命令,并使用 gen-req 选项,后接服务器的通用名称(CN)。在本教程中,我们将使用 server 作为 OpenVPN 服务器的 CN。我们还将使用 nopass 选项以避免任何权限问题。
$ ./easyrsa gen-req server nopass
你将看到如下输出。
Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
..........+.....+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....................+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+..+......+.......+...+..+.+.....+....+..+...+............+.+...+.....+....+...........+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+...+......+.....+....+...........+...+..........+..+.+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*............+.+..+....+..............+.....................+....+......+..............+.+.....+....+............+..+............+....+..+...+.......+.....+....+...+..+.........+.+.........+..+...+.+..............+.+.........+...........+.+.....+.........+...+......+.+......+.....+..........+...+..............+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [server]:
Keypair and certificate request completed. Your files are:
req: /home/<username>/easy-rsa/pki/reqs/server.req
key: /home/<username>/easy-rsa/pki/private/server.key
这将为服务器创建私钥和一个名为 server.req 的证书请求文件。将服务器密钥复制到 /etc/openvpn/server 目录。
$ sudo cp /home/<username>/easy-rsa/pki/private/server.key /etc/openvpn/server/
证书签名请求(CSR)现已准备好由 CA 进行签署。
步骤 5 - 签署 OpenVPN 服务器的 CSR
下一步是将 CSR 文件复制到 CA 服务器进行签署。如果你的服务器启用了密码认证,你可以直接使用以下命令复制该文件。
$ scp /home/username/easy-rsa/pki/reqs/server.req username@your_ca_server_ip:/tmp
如果你不想使用密码认证,则需要为每台服务器生成 SSH 密钥对,然后将 OpenVPN 服务器的 SSH 公钥添加到 CA 机器的 authorized_keys 文件中,反之亦然。
如果你不想经历上述全部过程,可以直接复制文件。在 OpenVPN 服务器上打开文件,复制其内容,然后在 CA 服务器上创建文件并粘贴内容。
重新登录到 CA 服务器,切换到 ~/easy-rsa 目录并导入 CSR 文件。
$ cd ~/easy-rsa
$ ./easyrsa import-req /tmp/server.req server
你将看到如下输出。
Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
The request has been successfully imported with a short name of: server
You may now use this name to perform signing operations on this request.
使用以下命令签署请求。由于我们签署的是 OpenVPN 服务器的 CSR,因此将使用其通用名称(CN)。
$ ./easyrsa sign-req server server
系统会提示你确认请求是否来自可信来源。输入 yes 然后按 ENTER 键确认。
Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.
Request subject, to be signed as a server certificate for 825 days:
subject=
commonName = server
Type the word 'yes' to continue, or any other input to abort.
Confirm request details: yes
接下来,系统会提示你输入之前设置的 CA 私钥密码短语。
Using configuration from /home/<username>/easy-rsa/pki/easy-rsa-13476.9IC4QC/tmp.lPVwQo
Enter pass phrase for /home/<username>/easy-rsa/pki/private/ca.key:
40975B6A677F0000:error:0700006C:configuration file routines:NCONF_get_string:no value:../crypto/conf/conf_lib.c:315:group=<NULL> name=unique_subject
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'server'
Certificate is to be certified until May 8 12:41:46 2025 GMT (825 days)
Write out database with 1 new entries
Data Base Updated
Certificate created at: /home/<username>/easy-rsa/pki/issued/server.crt
生成的证书包含 OpenVPN 服务器的公共加密密钥以及 CA 服务器的签名。将证书复制回 OpenVPN 服务器。
$ scp pki/issued/server.crt username@your_vpn_server_ip:/tmp
$ scp pki/ca.crt username@your_vpn_server_ip:/tmp
在你的 OpenVPN 服务器上,将这些文件复制到 /etc/openvpn/server 目录。
$ sudo cp /tmp/{server.crt,ca.crt} /etc/openvpn/server
步骤 6 - 配置 OpenVPN 加密材料
我们将添加一个额外的共享密钥,服务器和所有客户端都会与 OpenVPN 的 tls-crypt 指令一起使用。这可确保 OpenVPN 服务器能够处理未经验证的流量、端口扫描和拒绝服务攻击。它还使识别 OpenVPN 网络流量变得更加困难。
切换到 ~/easy-rsa 目录。
$ cd ~/easy-rsa
生成 tls-crypt 预共享密钥。这将创建一个名为 ta.key 的文件
$ openvpn --genkey secret ta.key
将 ta.key 复制到 /etc/openvpn/server 目录。
$ sudo cp ta.key /etc/openvpn/server
步骤 7 - 生成客户端证书和密钥对
创建一个目录来存储客户端证书和密钥文件。
$ mkdir -p ~/client-configs/keys
限制该目录的权限以保护它。
$ chmod -R 700 ~/client-configs
接下来,切换到 ~/easy-rsa 目录。
$ cd ~/easy-rsa
使用 client1 作为客户端的通用名称生成客户端密钥。你可以为客户端使用任意 CN。
$ ./easyrsa gen-req client1 nopass
按 ENTER 键确认通用名称。你将看到如下输出。
Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
.......+.+.....+.+........+.+...+...+........+....+..+....+.........+....................+......+.......+...+.....+.+.........+...............+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*............+......+.........+......+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+........+...+...................+...........+....+...........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
..........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...........+......+.......+..+..........+.....+.......+.....+....+.....+....+...+.....+...+....+...........+....+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [client1]:
Keypair and certificate request completed. Your files are:
req: /home/username/easy-rsa/pki/reqs/client1.req
key: /home/username/easy-rsa/pki/private/client1.key
接下来,将 client1.key 文件复制到 ~/client-configs/keys 目录。
$ cp pki/private/client1.key ~/client-configs/keys/
将 client1.req 文件传输到 CA 服务器。
$ scp pki/reqs/client1.req username@your_ca_server_ip:/tmp
重新登录到 CA 服务器并导入服务器请求。
$ cd ~/easy-rsa
$ ./easyrsa import-req /tmp/client1.req client1
你将看到如下输出。
Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
The request has been successfully imported with a short name of: client1
You may now use this name to perform signing operations on this request.
使用以下命令签署请求。我们使用 client 作为请求类型。
$ ./easyrsa sign-req client client1
当系统提示时,输入 yes 确认签署请求,并确认它来自可信来源。
Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.
Request subject, to be signed as a client certificate for 825 days:
subject=
commonName = client1
Type the word 'yes' to continue, or any other input to abort.
Confirm request details: yes
系统会提示你输入 CA 密码短语。
Using configuration from /home/<username>/easy-rsa/pki/easy-rsa-13573.uI2Vi8/tmp.q1RnLo
Enter pass phrase for /home/<username>/easy-rsa/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'client1'
Certificate is to be certified until May 8 12:50:23 2025 GMT (825 days)
Write out database with 1 new entries
Data Base Updated
Certificate created at: /home/username/easy-rsa/pki/issued/client1.crt
将生成的证书传输回 OpenVPN 服务器。
$ scp pki/issued/client1.crt username@your_server_ip:/tmp
在 OpenVPN 服务器上,将客户端证书复制到 ~/client-configs/keys 目录。
$ cp /tmp/client1.crt ~/client-configs/keys/
将 ca.crt 和 ta.key 文件复制到 ~/client-configs/keys 目录,并为当前登录的服务器设置适当的权限。
$ cp ~/easy-rsa/ta.key ~/client-configs/keys/
$ sudo cp /etc/openvpn/server/ca.crt ~/client-configs/keys/
$ sudo chown username.username ~/client-configs/keys/*
步骤 8 - 配置 OpenVPN
复制示例 server.conf 文件作为配置 OpenVPN 的起点。
$ sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf /etc/openvpn/server/
打开该文件进行编辑。
$ sudo nano /etc/openvpn/server/server.conf
通过查找 tls-auth 指令找到文件的 HMAC 部分。在该行开头添加分号(;)将其注释掉。如下所示在其下方添加一行新内容。
;tls-auth ta.key 0 # This file is secret
tls-crypt ta.key
接下来,通过查找 cipher 行来更改加密算法值。默认值设置为 AES-256-CBC。将默认值注释掉,并添加另一行使用 AES-256-GCM 加密,它提供了更好的加密级别和性能,如下所示。
;cipher AES-256-CBC
cipher AES-256-GCM
在其正下方,添加 auth 指令以选择 HMAC 消息摘要算法。
auth SHA256
由于我们使用的椭圆曲线加密,需要关闭 Diffie-Hellman 加密。将 dh dh2048.pem 行注释掉,并在其下方添加 dh none。
;dh dh2048.pem
dh none
OpenVPN 在启动后应无特权运行。要启用此功能,找到并取消注释 user nobody 和 group nobody 行,并按如下所示进行修改。
user nobody
group nogroup
Ubuntu 拥有 nogroup 组,而不是 CentOS 发行版中提供的 nobody 组。
通过 VPN 重定向全部流量
上述设置会在客户端和服务器之间创建 VPN 连接,但不会强制任何连接使用隧道。为此,首先找到 push "redirect-gateway def1 bypass-dhcp" 这一行。这一行告诉客户端将其所有流量通过 OpenVPN 服务器进行重定向。取消注释该行以启用此功能。
push "redirect-gateway def1 bypass-dhcp"
找到该行下方的 dhcp-option 部分。从这两行的开头移除分号。这会告诉客户端使用 OpenDNS 解析器。
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
更改端口和协议
OpenVPN 默认使用端口 1194 和 UDP 协议来接受客户端连接。你可以根据需要更改端口。如果你未在 OpenVPN 服务器上托管 Web 内容,可以使用端口 443。
找到 port 1194 这一行并更改其值。
# Optional!
port 443
找到 proto udp 这一行,并在其前面添加分号将其注释掉。同时,如下所示移除分号以取消注释 proto tcp 这一行。
proto tcp
;proto udp
由于我们使用的是 TCP 协议,需要将 explicit-exit-notify 指令的值从 1 更改为 0,因为该指令仅用于 UDP。
explicit-exit-notify 0
指向非默认凭据
如果你在之前的 ./easy-rsa gen-req server 命令中选择了不同的名称,则需要修改 cert 和 key 行,使其指向相应的 .crt 和 .key 文件。由于我们使用的是默认的服务器名称,默认值是正确的。
cert server.crt
key server.key
完成后,按 Ctrl + X,并在提示时输入 Y 保存文件。
步骤 9 - 调整 OpenVPN 服务器网络配置
下一步是配置服务器的网络设置,以使 OpenVPN 能够正确路由流量。我们需要配置的第一项是端口转发。
打开 /etc/sysctl.conf 文件进行编辑。
$ sudo nano /etc/sysctl.conf
在文件底部添加以下行。
net.ipv4.ip_forward = 1
按 Ctrl + X,并在提示时输入 Y 保存文件。
要读取文件并为当前会话加载新值,请使用以下命令。
$ sudo sysctl -p
net.ipv4.ip_forward = 1
此配置将通过你服务器的 IP 地址路由来自客户端的所有 Web 流量,客户端的公共 IP 地址将被有效地隐藏。
步骤 10 - 配置防火墙
要允许 OpenVPN 通过防火墙,你需要启用 IP 伪装(masquerading),这是 iptables 的一个概念,提供即时动态网络地址转换(NAT)以正确路由客户端连接。
在打开防火墙配置文件添加伪装规则之前,首先使用以下命令查找你机器的公共网络接口。
$ ip route list default
你将收到类似的输出。
default via 64.225.64.1 dev eth0 proto static
这告诉我们接口名称为 eth0。打开 /etc/ufw/before.rules 文件进行编辑。
$ sudo nano /etc/ufw/before.rules
这些规则会在常规 UFW 规则加载之前被读取并生效。如下所示在文件开头添加以下行。
#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
# ufw-before-input
# ufw-before-output
# ufw-before-forward
#
# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
# Allow traffic from OpenVPN client to eth0 (change to the interface you discovered!)
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
COMMIT
# END OPENVPN RULES
# Don't delete these required lines, otherwise there will be errors
*filter
. . .
按 Ctrl + X,并在提示时输入 Y 保存文件。
接下来,我们需要配置 UFW 默认允许转发的数据包。打开 /etc/default/ufw 文件进行编辑。
$ sudo nano /etc/default/ufw
找到 DEFAULT_FORWARD_POLICY 指令,并将其值从 DROP 更改为 ACCEPT。
DEFAULT_FORWARD_POLICY="ACCEPT"
按 Ctrl + X,并在提示时输入 Y 保存文件。
最后,打开你之前为 OpenVPN 服务器配置的端口 443。
$ sudo ufw allow 443/tcp
禁用并重新启用防火墙以应用新配置。
$ sudo ufw disable
$ sudo ufw enable
步骤 11 - 启动 OpenVPN
启用 OpenVPN 服务以在开机时启动。
$ sudo systemctl -f enable
[email protected]
启动 OpenVPN 服务。
$ sudo systemctl start
[email protected]
检查服务的状态。
$ sudo systemctl status
[email protected]
你将收到类似的输出。
?
[email protected]
- OpenVPN service for server
Loaded: loaded (/lib/systemd/system/
[email protected]
; enabled; vendor preset: enabled)
Active: active (running) since Fri 2023-02-03 13:40:28 UTC; 32s ago
Docs: man:openvpn(8)
https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
https://community.openvpn.net/openvpn/wiki/HOWTO
Main PID: 15492 (openvpn)
Status: "Initialization Sequence Completed"
Tasks: 1 (limit: 1116)
Memory: 1.8M
CPU: 29ms
CGroup: /system.slice/system-openvpn\x2dserver.slice/
[email protected]
??15492 /usr/sbin/openvpn --status /run/openvpn-server/status-server.log --status-version 2 --suppress-timestamps --config server.conf
Feb 03 13:40:28 vpnserver openvpn[15492]: Listening for incoming TCP connection on [AF_INET][undef]:443
Feb 03 13:40:28 vpnserver openvpn[15492]: TCPv4_SERVER link local (bound): [AF_INET][undef]:443
Feb 03 13:40:28 vpnserver openvpn[15492]: TCPv4_SERVER link remote: [AF_UNSPEC]
Feb 03 13:40:28 vpnserver openvpn[15492]: GID set to nogroup
Feb 03 13:40:28 vpnserver openvpn[15492]: UID set to nobody
Feb 03 13:40:28 vpnserver openvpn[15492]: MULTI: multi_init called, r=256 v=256
Feb 03 13:40:28 vpnserver openvpn[15492]: IFCONFIG POOL IPv4: base=10.8.0.4 size=62
Feb 03 13:40:28 vpnserver openvpn[15492]: IFCONFIG POOL LIST
Feb 03 13:40:28 vpnserver openvpn[15492]: MULTI: TCP INIT maxclients=1024 maxevents=1028
Feb 03 13:40:28 vpnserver openvpn[15492]: Initialization Sequence Completed
步骤 12 - 创建客户端配置
在测试客户端之前,我们需要为我们将要使用的客户端创建配置文件。创建一个用于存储客户端配置文件的目录。
$ mkdir -p ~/client-configs/files
将示例客户端配置文件复制到该目录。
$ cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client-configs/base.conf
打开配置文件进行编辑。
$ nano ~/client-configs/base.conf
找到 remote 指令,并将其设置为指向你的 OpenVPN 服务器的公共 IP 地址。同时,将端口更改为与你之前选择的端口相匹配。
. . .
# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote your_server_ip 443
. . .
设置你之前选择的协议。
proto tcp
通过移除前面的分号来取消注释 user 和 group 指令。同时,将 group 指令的值更改为 nogroup。
# Downgrade privileges after initialization (non-Windows only)
user nobody
group nogroup
找到 ca、cert 和 key 指令,并在它们前面添加分号将其注释掉。这是因为我们将在客户端配置文件中添加证书和密钥。
# SSL/TLS parms.
# See the server config file for more
# description. It's best to use
# a separate .crt/.key file pair
# for each client. A single ca
# file can be used for all clients.
;ca ca.crt
;cert client.crt
;key client.key
将 tls-auth 指令注释掉,因为我们将把 ta.key 直接添加到客户端配置文件中。
# If a tls-auth key is used on the server
# then every client must also have the key.
;tls-auth ta.key 1
与你之前在 `/etc/openvpn/server/server.conf 文件中设置的 cipher 和 auth 设置保持一致。
cipher AES-256-GCM
auth SHA256
添加 key-direction 指令并将其设置为 1,以使 VPN 正常工作。
key-direction 1
接下来,添加几行注释掉的内容,以处理 VPN 客户端用于 DNS 解析的不同方法。为不使用 systemd-resolved 但依赖 resolvconf 实用程序管理 DNS 的客户端添加以下一组行。
; script-security 2
; up /etc/openvpn/update-resolv-conf
; down /etc/openvpn/update-resolv-conf
为使用 systemd-resolved 进行 DNS 解析的客户端添加以下一组行。
; script-security 2
; up /etc/openvpn/update-systemd-resolved
; down /etc/openvpn/update-systemd-resolved
; down-pre
; dhcp-option DOMAIN-ROUTE .
按 Ctrl + X,并在提示时输入 Y 保存文件。
创建一个脚本,将基础配置与相关的证书、密钥和加密文件编译在一起,然后将生成的配置文件复制到 ~/client-configs/files 目录。
在 ~/client-configs 目录中创建并打开文件 make_config.sh。
$ nano ~/client-configs/make_config.sh
将以下代码粘贴到其中。
#!/bin/bash
# First argument: Client identifier
KEY_DIR=~/client-configs/keys
OUTPUT_DIR=~/client-configs/files
BASE_CONFIG=~/client-configs/base.conf
cat ${BASE_CONFIG} \
<(echo -e '<ca>') \
${KEY_DIR}/ca.crt \
<(echo -e '</ca>\n<cert>') \
${KEY_DIR}/${1}.crt \
<(echo -e '</cert>\n<key>') \
${KEY_DIR}/${1}.key \
<(echo -e '</key>\n<tls-crypt>') \
${KEY_DIR}/ta.key \
<(echo -e '</tls-crypt>') \
> ${OUTPUT_DIR}/${1}.ovpn
按 Ctrl + X,并在提示时输入 Y 保存文件。
使该文件可执行并限制其权限。
$ chmod 700 ~/client-configs/make_config.sh
此脚本会复制 base.conf 文件,收集所有证书和密钥文件,提取其内容,将其附加到基础配置文件中,然后导出所有内容以创建一个新的客户端配置文件。每当你添加一个新客户端时,都需要为其生成新的密钥和证书,然后运行此脚本以创建客户端配置文件。
我们已经在步骤 7 中创建了客户端证书和密钥文件。现在让我们为它创建配置文件。
切换到 ~/client-configs 目录。
$ cd ~/client-configs
运行脚本以生成客户端配置文件。
$ ./make_config.sh client1
这将创建一个名为 client1.ovpn 的文件。如果你想要不同的文件名,请更改参数。检查目录内容。
$ ls ~/client-configs/files
client1.ovpn
这是你需要传输到客户端的配置文件,之后将用于连接到 OpenVPN 服务器。你可以使用任何 SFTP 协议/程序将文件传输到客户端。
步骤 13 - 安装并测试客户端连接
在本教程中,我们使用的是一台 Ubuntu 22.04 客户端机器。通过以下命令安装 OpenVPN。
$ sudo apt install openvpn
通过运行以下命令检查你的系统是否使用 systemd-resolved 来管理 DNS 查询。
$ cat /etc/resolv.conf
你将收到类似的输出。
Output
# This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8).
# Do not edit.
. . .
nameserver 127.0.0.53
options edns0 trust-ad
search .
如果系统使用的是 systemd-resolved,那么上面的 IP 地址将是 127.0.0.53。此外,文件顶部的注释也会确认这一点。如果 IP 地址不是 127.0.0.53,则系统未使用 systemd-resolved,你需要按照后面提到的步骤操作。
针对使用 systemd-resolved 的客户端
安装 openvpn-systemd-resolved 软件包,它提供的脚本可强制 systemd-resolved 使用 VPN 服务器进行 DNS 解析。
$ sudo apt install openvpn-systemd-resolved
打开客户端配置文件进行编辑。
$ nano client1.ovpn
通过移除前面的分号来取消注释文件中的以下行。
script-security 2
up /etc/openvpn/update-systemd-resolved
down /etc/openvpn/update-systemd-resolved
down-pre
dhcp-option DOMAIN-ROUTE .
按 Ctrl + X,并在提示时输入 Y 保存文件。
针对使用 update-resolv-conf 的客户端
首先,确认你的发行版正在使用 update-resolv-conf。
$ ls /etc/openvpn
client server update-resolv-conf
如果你的系统包含 update-resolv-conf 文件,则打开客户端配置文件进行编辑。
$ nano client1.ovpn
通过移除前面的分号来取消注释文件中的以下行。
script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf
如果你使用的是基于 CentOS 的发行版,请将 group 指令从 nogroup 更改为 nobody。
group nobody
按 Ctrl + X,并在提示时输入 Y 保存文件。
连接客户端
运行以下命令将客户端连接到 VPN 服务器。
$ sudo openvpn --config client1.ovpn
你应该会收到类似的输出。
2023-02-06 15:18:37 OpenVPN 2.5.5 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Jul 14 2022
2023-02-06 15:18:37 library versions: OpenSSL 3.0.2 15 Mar 2022, LZO 2.10
2023-02-06 15:18:37 NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
2023-02-06 15:18:37 Outgoing Control Channel Encryption: Cipher 'AES-256-CTR' initialized with 256 bit key
2023-02-06 15:18:37 Outgoing Control Channel Encryption: Using 256 bit message hash 'SHA256' for HMAC authentication
2023-02-06 15:18:37 Incoming Control Channel Encryption: Cipher 'AES-256-CTR' initialized with 256 bit key
2023-02-06 15:18:37 Incoming Control Channel Encryption: Using 256 bit message hash 'SHA256' for HMAC authentication
2023-02-06 15:18:37 TCP/UDP: Preserving recently used remote address: [AF_INET]64.225.66.226:443
2023-02-06 15:18:37 Socket Buffers: R=[131072->131072] S=[16384->16384]
2023-02-06 15:18:37 Attempting to establish TCP connection with [AF_INET]64.225.66.226:443 [nonblock]
2023-02-06 15:18:38 TCP connection established with [AF_INET]64.225.66.226:443
2023-02-06 15:18:38 TCP_CLIENT link local: (not bound)
2023-02-06 15:18:38 TCP_CLIENT link remote: [AF_INET]64.225.66.226:443
2023-02-06 15:18:38 NOTE: UID/GID downgrade will be delayed because of --client, --pull, or --up-delay
2023-02-06 15:18:38 TLS: Initial packet from [AF_INET]64.225.66.226:443, sid=b6459c4e 0e23d362
2023-02-06 15:18:38 VERIFY OK: depth=1, CN=Easy-RSA CA
2023-02-06 15:18:38 VERIFY KU OK
2023-02-06 15:18:38 Validating certificate extended key usage
2023-02-06 15:18:38 ++ Certificate has EKU (str) TLS Web Server Authentication, expects TLS Web Server Authentication
2023-02-06 15:18:38 VERIFY EKU OK
2023-02-06 15:18:38 VERIFY OK: depth=0, CN=server
2023-02-06 15:18:38 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 2048 bit RSA, signature: RSA-SHA256
2023-02-06 15:18:38 [server] Peer Connection Initiated with [AF_INET]64.225.66.226:443
2023-02-06 15:18:39 SENT CONTROL [server]: 'PUSH_REQUEST' (status=1)
2023-02-06 15:18:39 PUSH: Received control message: 'PUSH_REPLY,redirect-gateway def1 bypass-dhcp,dhcp-option DNS 208.67.222.222,dhcp-option DNS 208.67.220.220,route 10.8.0.1,topology net30,ping 10,ping-restart 120,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM'
2023-02-06 15:18:39 OPTIONS IMPORT: timers and/or timeouts modified
2023-02-06 15:18:39 OPTIONS IMPORT: --ifconfig/up options modified
2023-02-06 15:18:39 OPTIONS IMPORT: route options modified
2023-02-06 15:18:39 OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
2023-02-06 15:18:39 OPTIONS IMPORT: peer-id set
2023-02-06 15:18:39 OPTIONS IMPORT: adjusting link_mtu to 1626
2023-02-06 15:18:39 OPTIONS IMPORT: data channel crypto options modified
2023-02-06 15:18:39 Outgoing Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
2023-02-06 15:18:39 Incoming Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
2023-02-06 15:18:39 net_route_v4_best_gw query: dst 0.0.0.0
2023-02-06 15:18:39 net_route_v4_best_gw result: via 10.0.2.2 dev enp0s3
2023-02-06 15:18:39 ROUTE_GATEWAY 10.0.2.2/255.255.255.0 IFACE=enp0s3 HWADDR=08:00:27:84:e2:0b
2023-02-06 15:18:39 TUN/TAP device tun0 opened
2023-02-06 15:18:39 net_iface_mtu_set: mtu 1500 for tun0
2023-02-06 15:18:39 net_iface_up: set tun0 up
2023-02-06 15:18:39 net_addr_ptp_v4_add: 10.8.0.6 peer 10.8.0.5 dev tun0
2023-02-06 15:18:39 /etc/openvpn/update-systemd-resolved tun0 1500 1626 10.8.0.6 10.8.0.5 init
<14>Feb 6 15:18:39 update-systemd-resolved: Link 'tun0' coming up
<14>Feb 6 15:18:39 update-systemd-resolved: Adding DNS Routed Domain .
<14>Feb 6 15:18:39 update-systemd-resolved: Adding IPv4 DNS Server 208.67.222.222
<14>Feb 6 15:18:39 update-systemd-resolved: Adding IPv4 DNS Server 208.67.220.220
<14>Feb 6 15:18:39 update-systemd-resolved: SetLinkDNS(5 2 2 4 208 67 222 222 2 4 208 67 220 220)
<14>Feb 6 15:18:39 update-systemd-resolved: SetLinkDomains(5 1 . true)
2023-02-06 15:18:39 net_route_v4_add: 64.225.66.226/32 via 10.0.2.2 dev [NULL] table 0 metric -1
2023-02-06 15:18:39 net_route_v4_add: 0.0.0.0/1 via 10.8.0.5 dev [NULL] table 0 metric -1
2023-02-06 15:18:39 net_route_v4_add: 128.0.0.0/1 via 10.8.0.5 dev [NULL] table 0 metric -1
2023-02-06 15:18:39 net_route_v4_add: 10.8.0.1/32 via 10.8.0.5 dev [NULL] table 0 metric -1
2023-02-06 15:18:39 GID set to nogroup
2023-02-06 15:18:39 UID set to nobody
2023-02-06 15:18:39 WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
2023-02-06 15:18:39 Initialization Sequence Completed
打开另一个终端来检查 DNS 设置。
$ systemd-resolve --status tun0
你将看到如下输出,其中可以看到我们之前配置的 DNS 服务器。这确保 VPN 工作正常。
Link 4 (tun0)
Current Scopes: DNS
Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 208.67.222.222
DNS Servers: 208.67.222.222 208.67.220.220
DNS Domain: ~.
你可以通过在浏览器中访问相关网站来检查你的 IP 地址以及 OpenVPN 服务器的位置,从而进一步验证连接。

你还可以通过执行标准的 DNS 泄漏测试来进一步验证。

你可以看到我们之前配置的 OpenDNS 主机名,且服务器的位置与 OpenVPN 服务器的位置相匹配。
上述命令会在前台运行 OpenVPN,这意味着终端将被阻塞。要关闭连接,你需要按 Ctrl + C。不过,你也可以让 OpenVPN 在后台运行。使用以下命令来实现。
sudo openvpn --config client1.ovpn --daemon
要关闭连接,请找到该进程的进程 ID。
$ ps aux | grep openvpn
你将收到类似的输出。
nobody 4357 0.3 0.0 13468 8432 ? Ss 15:35 0:00 openvpn --config client1.ovpn --daemon
username 4406 0.0 0.0 17732 2432 pts/0 S+ 15:35 0:00 grep --color=auto openvpn
如你所见,与 OpenVPN 进程对应的进程 ID 是 4357。使用以下命令终止该进程以关闭 VPN 连接。
$ sudo kill -9 4357
OpenVPN 为 Windows、macOS、Android 和 iOS 平台提供 GUI 客户端,你可以导入客户端配置文件进行连接。
步骤 14 - 撤销客户端证书
如果你想撤销客户端的证书以阻止其访问,可以通过登录到 CA 服务器来实现。
切换到 ~/easy-rsa 目录。
$ cd ~/easy-rsa
使用 revoke 选项运行脚本,后接客户端名称。
$ ./easyrsa revoke client1
系统会提示你是否要撤销该证书。
Please confirm you wish to revoke the certificate with the following subject:
subject=
commonName = client1
Type the word 'yes' to continue, or any other input to abort.
Continue with revocation: yes
. . .
Revoking Certificate 8348B3F146A765581946040D5C4D590A
. . .
这会在 CA 服务器上撤销证书。但是,OpenVPN 服务器无法检查撤销状态。为此,我们需要生成证书撤销列表(CRL)并将其传输到 OpenVPN 服务器。
生成 CRL。
$ ./easyrsa gen-crl
系统会提示你输入 CA 密码短语。上述命令会生成一个 crl.pem 文件。
将此文件复制到 OpenVPN 服务器。
$ scp ~/easy-rsa/pki/crl.pem username@your_server_ip:/tmp
重新登录到 OpenVPN 服务器,并将 CRL 文件复制到 /etc/openvpn/server 目录。
$ sudo cp /tmp/crl.pem /etc/openvpn/server/
打开 OpenVPN 服务器配置文件进行编辑。
$ sudo nano /etc/openvpn/server/server.conf
在文件底部添加以下行。这会指示 OpenVPN 服务器检查已被限制的客户端的撤销列表。
crl-verify crl.pem
按 Ctrl + X,并在提示时输入 Y 保存文件。
重新启动 OpenVPN 服务器以应用更改。
sudo systemctl restart
[email protected]
客户端再也无法连接到 OpenVPN 服务器。
结语
至此,我们在 Ubuntu 22.04 服务器上安装和配置 OpenVPN 服务器的教程就结束了。我们还将 OpenVPN Linux 客户端连接到了服务器。如果你有任何问题,请在下方评论区留言。