介绍

虚拟专用网络(VPN)允许您遍历不受信任的网络,就像在专用网络上一样。当您连接到不受信任的网络(例如酒店或咖啡店的 WiFi)时,它使您可以从智能手机或笔记本电脑,安全地访问 Internet。

OpenVPN 是功能齐全的,开源的传输层安全性(TLS)VPN 解决方案,可适应多种配置。

使用 Docker 快速部署服务端

配置

首先创建一个目录,用来存放 openvpn 相关文件。之后在目录内执行下面这两条命令

生成服务端配置文件
1
docker run -v $(pwd)/conf:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_genconfig -u udp://<这里填写服务端公网ip>
创建CA,配置证书
1
docker run -v $(pwd)/conf:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn ovpn_initpki
注意

创建 CA 时设置的密码在后续创建客户端证书时需要用到

说明

默认生成的配置文件适用于本地局域网环境,即客户机无法访问外网,需要借助服务机连接外网(未实践,可能有误)

由于默认生成的配置文件会导致本机网络无法使用,这里我们需要对其进行修改:将 $(pwd)/conf/openvpn.conf 中的内容替换

openvpn.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server 10.8.0.0 255.255.255.0
port 1194
proto udp
dev tun0
verb 3
key /etc/openvpn/pki/private/<这里保留原来的文件名>.key
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/<这里保留原来的文件名>.crt
dh /etc/openvpn/pki/dh.pem
tls-auth /etc/openvpn/pki/ta.key
key-direction 0
keepalive 10 120
persist-key
persist-tun
status /tmp/openvpn-status.log
client-to-client
user nobody
group nogroup
comp-lzo no
push "route 10.8.0.0 255.255.255.0"

其中,10.8.0.0 为 vpn 连接后的网段,可以根据自己需要修改子网和掩码。serverpush 配置项需要保持一致

若需要让每个客户端每次连接的 ip 不变,可以往该配置文件中添加

1
ifconfig-pool-persist ipp.txt

启动

提供两种方式启动,根据自己喜好选择。

1
docker run --restart always --cap-add NET_ADMIN --name openvpn -p 1194:1194/udp --privileged -v $(pwd)/conf:/etc/openvpn kylemanna/openvpn
1
2
3
4
5
6
7
8
9
10
11
12
13
version: '3'
services:
openvpn:
image: kylemanna/openvpn
restart: always
cap_add:
- NET_ADMIN
container_name: openvpn
ports:
- 1194:1194/udp
privileged: true
volumes:
- ./conf:/etc/openvpn

生成客户端配置

创建客户端证书,$client_name 替换为需要的名字,需要输入 CA 密码。

1
docker run -v $(pwd)/conf:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn easyrsa build-client-full $client_name nopass

接下来创建一个目录将下列文件复制过去

  • conf/pki/ca.crt
  • conf/pki/ta.key
  • conf/pki/issued/$client_name.crt: 即 client.crt
  • conf/pki/private/$client_name.key: 即 client.key

接下来按照 配置客户端连接 进行配置。

下面介绍手动部署方法

前提

  • 使用具有 sudo 非 root 用户进行搭建,下文称为 OpenVPN 服务器
注意

出于安全考虑,不推荐你直接使用 root 用户进行搭建。

你要想用也拦不住你
  • 使用单独的一台服务器作为专用的证书颁发机构(CA),下文称为 CA服务器
注意

虽然从技术上讲可以将你的 OpenVPN 服务器或本地计算机作为 CA,但不建议这样做,因为它可能会使你的 VPN 出现一些安全漏洞。根据 OpenVPN 官方文档,你应该将 CA 放置在专用于导入和签名证书请求的独立计算机上。

都说了,你要想用咱也拦不住你

安装 OpenVPN 和 Easy-RSA

首先需要安装 OpenVPN 和 Easy-RSA。

Easy-RSA 是一种公钥基础结构(PKI)管理工具,你将在 OpenVPN Server 上使用该工具生成证书请求,然后在 CA Server 上进行验证和签名。

CentOS 8 / Rocky 8

CentOS 8 和 Rocky 8 默认不提供 OpenVPN 和 Easy-RSA,因此你需要启用 EPEL 存储库。

1
2
sudo dnf install epel-release
sudo dnf install openvpn easy-rsa

Ubuntu

Ubuntu 的默认仓库就已经有 OpenVPN 的包了

1
2
sudo apt-get update
sudo apt-get install openvpn easy-rsa

配置 easy-rsa

安装完成后,你需要以非 root 用户身份在 OpenVPN 服务器上创建一个新目录:

1
mkdir ~/easy-rsa

该目录位置可以自定义,此处假设目录位置为~

现在,你需要从 easy-rsa 创建一个符号连接,以便将软件包安装到你刚刚创建的 easy-rsa 目录中。

1
ln -s /usr/share/easy-rsa/3/* ~/easy-rsa/

最后,确保目录所有者是你当前使用的用户,并限制对该目录的访问:

1
2
sudo chown openvpn ~/easy-rsa
chmod 700 ~/easy-rsa

假设你使用的是openvpn用户

为 OpenVPN 创建 PKI

要在 OpenVPN 服务器上构建 PKI 目录,你需要使用一些默认值填充 vars 文件。

进入 easy-rsa 目录,然后创建和编辑 vars 文件。

1
vi vars

打开文件后,粘贴下面两行:

~/easy-rsa/vars
1
2
set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"

这些配置能够确保将你的私钥和证书请求配置为使用现代化的椭圆曲线密码术(ECC)为客户端和 OpenVPN 服务器生成密钥和安全签名。

填充 vars 文件后,即可继续创建 PKI 目录。

~/easy-rsa
1
./easyrsa init-pki

配置 CA 服务器

先按照上面的步骤安装 easy-rsa ,然后配置 easy-rsa 和 创建 PKI

说明

如果你 CA 服务器和 OpenVPN 服务器一致,则直接执行下面的命令即可。

接下来执行该命令创建 CA 证书:

1
2
cd ~/easy-rsa
./easyrsa build-ca

首先会提示设置密码,用于 ca 对之后生成的 server 和 client 证书签名时使用,然后会提示设置 Country Name, State or Province Name, Locality Name, Organization Name, Organizational Unit Name, Common Name, Email Address, 可以键入回车使用默认的,也可以手动更改

创建 Diffie-Hellman

在 OpenVPN 服务端执行该命令创建 Diffie-Hellman, 完成后将其复制到 /etc/openvpn/server 目录。

1
2
3
cd ~/easy-rsa
./easyrsa gen-dh
sudo cp pki/dh.pem /etc/openvpn/server

时间可能会有点长,请耐心等待。

创建一个OpenVPN服务器证书请求和私钥

现在,通过使用 gen-req 选项调用 easyrsa,后跟机器的通用名称(CN)。CN可以是你喜欢的任何内容,但最好是具有一定的描述性。在这里,OpenVPN Server 的 CN 将设置为 server。后面还需要包括 nopass 选项。否则,将对请求的文件进行密码保护,这可能会在以后导致权限问题。

注意

如果你在这里选择 server 以外的名称,则必须调整以下一些内容。例如,将生成的文件复制到 /etc/openvpn/server 目录时,你必须替换正确的名称。你还必须修改 /etc/openvpn/server/server.conf 文件,以指向正确的 .crt 和 .key 文件

~/easy-rsa
1
./easyrsa gen-req server nopass
1
2
3
4
5
Common Name (eg: your user, host, or server name) [server]:  # 这里直接回车

Keypair and certificate request completed. Your files are:
req: /home/sammy/easy-rsa/pki/reqs/server.req
key: /home/sammy/easy-rsa/pki/private/server.key

这会为 OpenVPN 服务器创建一个 server.key 私钥和一个名为 server.req 的证书请求文件。将该密钥复制到 /etc/openvpn/server 目录:

1
sudo cp ~/easy-rsa/pki/private/server.key /etc/openvpn/server/

完成这些步骤后,你已经成功为您的 OpenVPN 服务器创建了私钥,并且生成了证书签名请求(req)。CSR 现在可以由你的 CA 签名了。

签署 OpenVPN 服务器的证书请求

在 OpenVPN 服务器上,使用 scp 或其他传输方法将 server.req 证书请求复制到 CA 服务器以进行签名。

1
scp ~/easy-rsa/pki/reqs/server.req ca_user@your_ca_server_ip:/tmp
说明

若你的 CA 服务器为 OpenVPN 服务器,则你无需复制证书请求,无需导入证书请求。直接运行下面的 sign-req 命令即可

现在,以拥有 easy-rsa 目录的非 root 用户登录到 CA 服务器,使用 easyrsa 脚本导入证书请求:

1
2
cd ~/easy-rsa
./easyrsa import-req /tmp/server.req server
1
2
3
. . .
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.

接下来运行带有 sign-req 选项的 easyrsa 脚本,然后时请求类型和公用名来对请求进行签名。请求类型可以是 client 或 server。由于我们在处理 OpenVPN 服务器的证书请求,因此请确保使用服务器请求类型(server):

1
./easyrsa sign-req server server

然后系统将提示你确认请求是否来自受信任的来源。输入 yes,然后按 Enter 确认:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 3650 days:

subject=
commonName = server


Type the word 'yes' to continue, or any other input to abort.
Confirm request details: yes
. . .
Certificate created at: /home/ca/easy-rsa/pki/issued/server.crt
注意

如果你加密了 CA 私钥,则还会提示你输入密码

完成配置后,请将 server.crt 和 ca.crt 文件从 CA 服务器复制到 OpenVPN 服务器:

1
2
scp pki/issued/server.crt openvpn@your_vpn_server_ip:/tmp
scp pki/ca.crt openvpn@your_vpn_server_ip:/tmp

现在回到 OpenVPN 服务器,将文件从 /tmp 复制到 /etc/openvpn/server:

1
sudo cp /tmp/{server.crt,ca.crt} /etc/openvpn/server

配置OpenVPN加密材料

为了增加安全性,我们需要添加一个额外的共享密钥,服务器和所有客户端将使用该密钥,并将其与 OpenVPN 的 tls-crypt 指令一起使用。此选项用于混淆服务器和客户端最初相互连接时使用的 TLS 证书。 OpenVPN 服务器还使用它对传入的数据包进行快速检查: 如果数据包是使用预共享密钥签名的,则服务器会对其进行处理;如果未签名,则服务器知道它来自不受信任的来源,可以丢弃它而不必执行其他解密工作。

此选项将帮助确保您的 OpenVPN 服务器能够应对未经身份验证的流量,端口扫描和拒绝服务攻击,这些攻击可能占用服务器资源。这也使识别 OpenVPN 网络流量变得更加困难。

请在 OpenVPN 服务器上的 ~/easy-rsa 目录中运行以下命令:

1
2
cd ~/easy-rsa
openvpn --genkey --secret ta.key

然后将其复制到 /etc/openvpn/server 目录

1
sudo cp ta.key /etc/openvpn/server

到这里,服务端所需的文件都齐全了,现在可以为需要使用这个 VPN 的用户创建客户端证书和密钥文件了。

生成客户端证书和密钥对

接下来将指导你生成一个客户端证书和密钥对。如果你有多个客户端,则可以为每个客户端重复这个过程。

注意

每个客户端的名称都必须为唯一的

1
2
cd ~/easy-rsa
./easyrsa gen-req client1 nopass

接下来可以再创建一个目录,用于收集客户端所需文件,同样的,建议将该目录权限改为 700

1
2
3
mkdir ~/client
sudo chown openvpn ~/client
chmod 700 ~/client

将刚刚生成的 client1.key 复制到该目录

1
cp ~/easy-rsa/pki/private/client1.key ~/client

然后将 client1.req 文件传输到你的 CA Server:

1
scp pki/reqs/client1.req ca@your_ca_server_ip:/tmp

登录到 CA Server,然后进入 easy-rsa 目录,导入证书请求并签名。

1
2
3
cd ~/easy-rsa
./easyrsa import-req /tmp/client1.req client1
./easarsa sign-req client client1

这里你必须指定请求类型为客户端类型(client)

1
2
Type the word 'yes' to continue, or any other input to abort.
Confirm request details: yes

若你对 CA 密钥进行了加密,你还需输入 CA 密钥的密码。

接下来将生成的客户端证书文件传回服务器:

1
scp pki/issued/client1.crt openvpn@your_server_ip:/tmp

然后将其移动到 client 目录

1
mv /tmp/client1.crt ~/client

最后 OpenVPN 客户端还需要 ca.crtta.key 文件。

1
sudo cp /etc/openvpn/server/{ca.crt,ta.key} ~/client

配置 OpenVPN 服务器

首先,复制样本server.conf文件做为您自己的配置文件的起点,并编辑它:

1
2
sudo cp /usr/share/doc/openvpn/sample/sample-config-files/server.conf /etc/openvpn/server/
sudo vi /etc/openvpn/server/server.conf

在文件底部添加下列内容,# 后面的是注释,请勿将其写入配置

/etc/openvpn/server/server.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
local 0.0.0.0
port 1194 # 使用端口
proto udp # 使用协议
dev tun # 网卡名称
ca ca.crt
cert server.crt
key server.key
dh dh.pem
server 10.8.0.0 255.255.255.0 # VPN网段及掩码
ifconfig-pool-persist ipp.txt
push "route 10.8.0.0 255.255.255.0" # 流量转发,如需转发其它流量往下添加即可
client-to-client
keepalive 10 120
tls-auth ta.key 0
cipher AES-256-CBC
comp-lzo
persist-key
persist-tun
status openvpn-status.log
verb 3

然后启动 OpenVPN Server 并开启自启

1
2
sudo systemctl start openvpn-server@server
sudo systemctl enable openvpn-server@server

若你使用了防火墙,记得打开对应端口

配置客户端连接

Linux

先安装 openvpn,如CentOS 8 / Rocky 8:

1
2
sudo dnf install epel-release
sudo dnf install openvpn

然后将 OpenVPN 服务端 client 目录中的 ca.crtta.keyclient.keyclient.crt 文件复制到客户端的 /etc/openvpn/client 目录。

openvpn-server
1
scp ~/client/{ca.crt,ta.key,client.key,client.crt} client@your_client_ip:/tmp
openvpn-client
1
sudo mv /tmp/{ca.crt,ta.key,client.key,client.crt} /etc/openvpn/client/

接下来复制样本 client.conf 文件做为你自己的配置文件起点,并编辑它:

1
2
sudo cp /usr/share/doc/openvpn/sample/sample-config-files/client.conf /etc/openvpn/client/
sudo vi /etc/openvpn/client/client.conf

在文件底部添加下列内容,# 后面的是注释,请勿将其写入配置

/etc/openvpn/client/client.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
client
dev tun # 网卡名
proto udp # OpenVPN服务器使用的协议
remote x.x.x.x 1194 # OpenVPN 服务器及端口
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
ca ca.crt
cert client1.crt
key client1.key
tls-auth ta.key 1
cipher AES-256-CBC
comp-lzo
verb 3

最后启动 OpenVPN Client 并设置开机自启

1
2
sudo systemctl start openvpn-client@client
sudo systemctl enable openvpn-client@client

Windows

首先前往 OpenVPN 官网下载 Windows 客户端应用

然后将 OpenVPN 服务端 client 目录中的 ca.crtta.keyclient.keyclient.crt 文件复制到 C:\Users\自己的用户名\OpenVPN\config 目录中

接下来在该目录创建一个 config.ovpn 文件,并编辑它 (# 后面的是注释,请勿将其写入配置)

config.ovpn
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
client
dev tun # 网卡名
proto udp # OpenVPN服务器使用的协议
remote x.x.x.x 1194 # OpenVPN 服务器及端口
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
ca ca.crt
cert client1.crt
key client1.key
tls-auth ta.key 1
cipher AES-256-CBC
comp-lzo
verb 3

最后启动 OpenVPN Client 应用,右键任务栏托盘中的 OpenVPN 图标,点击 连接