OpenVPN 搭建与使用

0. 网络结构

外网设备 client1 通过 OpenVPN 连接到内网设备 client2,使外网设备能通过内网 ip 直接访问内网资源。
假设 OpenVPN 服务器分配地址段为192.168.7.0/24,需访问的内网地址段为10.180.0.0/16

1. 服务端搭建

1.1 安装 OpenVPN 和 easy-rsa

1
sudo apt install -y openvpn easy-rsa

为避免更新导致丢失配置或密钥,复制 easy-rsa 文件到 openvpn 目录下

1
sudo cp -r /usr/share/easy-rsa /etc/openvpn

1.2 签发证书

使用 easy-rsa 签发证书。

1.2.1 修改 vars 配置文件

进入 easy-rsa 所在目录,重命名 vars 示例

1
2
cd /etc/openvpn/easy-rsa
mv vars.example vars

按需设置组织信息

1
vim vars

1.2.2 初始化 PKI

1
./easyrsa init-pki

1.2.3 生成 CA 证书

1
./easyrsa build-ca nopass

按需输入 Common Name

1.2.4 生成 Diffie-Hellman 密钥

1
./easyrsa gen-dh

此项耗时较长

1.2.5 签发服务端证书

按需输入 Common Name,这里以 server1 为例

1
2
./easyrsa gen-req server1 nopass
./easyrsa sign-req server server1

1.3 配置 OpenVPN 服务端

假设服务端配置文件位于/etc/openvpn/server

1.3.1 移动服务端证书

1
2
3
4
cp pki/ca.crt /etc/openvpn/server/pki
cp pki/dh.pem /etc/openvpn/server/pki
cp pki/issued/server1.crt /etc/openvpn/server/pki
cp pki/private/server1.key /etc/openvpn/server/pki

1.3.2 创建服务端配置文件

配置文件说明参考
Ubuntu Manpage: openvpn

1
vim /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
21
22
23
24
25
26
27
28
29
30
31
32
33
34
local 0.0.0.0
# 协议<tcp/udp>
proto tcp
# 端口
port 8047
# 虚拟网络设备<tap/tun>
dev tun
# 分配IP段,服务端将使用第1个IP
server 192.168.7.0 255.255.255.0
push "route 192.168.7.0 255.255.255.0"
# 添加路由规则
push "route 10.180.0.0 255.255.0.0"
route 10.180.0.0 255.255.0.0
# 证书位置
ca /etc/openvpn/server/pki/ca.crt
dh /etc/openvpn/server/pki/dh.pem
cert /etc/openvpn/server/pki/server1.crt
key /etc/openvpn/server/pki/server1.key
topology subnet
# client配置目录,可以为指定设备下发特点配置
client-config-dir /etc/openvpn/server/ccd
# 允许证书复用
duplicate-cn
keepalive 20 120
persist-key
persist-tun
# 允许客户端之间通信
client-to-client
script-security 2
# 开启数据压缩
comp-lzo
#log
status /etc/openvpn/server/connect.log 10
log /etc/openvpn/server/openvpn.log

1.3.3 创建服务并启动

创建服务

1
vim /etc/systemd/system/openvpn-server.service
1
2
3
4
5
6
7
8
[Unit]
Description=OpenVPN Server
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/server/server.conf

启动服务

1
2
3
systemctl daemon-reload && systemctl restart openvpn-server
systemctl status openvpn-server
systemctl enable openvpn-server

1.4 修改防火墙设置

根据实际情况自行修改防火墙设置。
参考设置:

1
2
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

1.5 配置转发

1.5.1 内网对外节点配置

为了使外网设备通过 client2 访问内网资源,需要在 client2 上配置转发。
通过在ccd文件夹内新建与 Common Name 相同的文件,即可为该设备下发特定配置。
ccd内新建名为client2的文件:

1
vim /etc/openvpn/server/ccd/client2
1
iroute 10.180.0.0 255.255.0.0

将对10.180.0.0/16的访问从服务段路由到特定的客户端client2

1.5.2 内网其它设备配置

对于需要在外访问的内网设备,添加ip route规则,使经由 OpenVPN 的外部访问通过 内网对外节点 client2进行转发。

1
ip route add 192.168.7.0/24 via <client2 内网ip>

1.6 (可选)配置用户名密码登陆

比较抽象,要自己写验证程序。

1.6.1 创建用户列表

格式为用户名:密码

1
vim /etc/openvpn/server/userlist
1
2
client1:password1
client2:password2

1.6.2 创建验证脚本

一个简单的验证脚本,用于与用户列表进行比对。

1
vim /etc/openvpn/server/auth.sh
1
2
3
4
5
6
7
8
9
#!/bin/sh
username=$1
password=$2
expected_password=$(grep "^${username}:" /etc/openvpn/server/userlist | cut -d ':' -f 2)
if [ "${password}" = "${expected_password}" ]; then
exit 0 # succeeded
else
exit 1 # failed
fi
1
chmod 777 /etc/openvpn/server/auth.sh

1.6.3 修改配置文件

  • 在服务端配置/etc/openvpn/server/server.conf中添加一行
1
auth-user-pass-verify /etc/openvpn/server/auth.sh via-env

重启服务

1
systemctl restart openvpn
  • 在客户端配置中添加一行
1
auth-user-pass

2. 客户端使用

2.1 签发客户端证书

按需输入 Common Name,其将被作为客户端的设备名,这里以client1为例

2.1.1 生成客户端证书

1
./easyrsa gen-req client1 nopass

2.1.2 签发客户端证书

1
./easyrsa sign-req client client1

2.1.3 移动客户端证书备用

1
2
3
cp pki/ca.crt /etc/openvpn/client
mv pki/issued/client1.crt /etc/openvpn/client
mv pki/private/client1.key /etc/openvpn/client

2.2 创建客户端配置文件

1
vim /etc/openvpn/client/client1.ovpn
1
2
3
4
5
6
7
8
9
10
11
12
13
client
dev tun
proto tcp
remote <服务器ip> <服务器端口>
ca ca.crt
cert client1.crt
key client1.key
nobind
resolv-retry infinite
persist-key
persist-tun
verb 3
comp-lzo

2.3 Windows 客户端使用

2.3.1 下载并安装 OpenVPN

下载地址

2.3.2 导入配置文件和证书

打开配置文件目录,默认为%USERPROFILE%\OpenVPN\config
在其中新建一个配置文件夹,将配置文件和证书复制到该目录下
包括client1.ovpnca.crtclient1.crtclient1.key

2.3.3 连接

启动 OpenVPN,右键托盘图标,选择连接

2.4 Linux 客户端使用

2.4.1 安装 OpenVPN

1
sudo apt install -y openvpn

2.4.2 导入配置文件和证书

将配置文件和证书复制到/etc/openvpn/client目录下
包括client2.ovpnca.crtclient2.crtclient2.key

2.4.3 创建并启动服务

创建服务

1
vim /etc/systemd/system/openvpn.service
1
2
3
4
5
6
7
8
[Unit]
Description=OpenVPN Client
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/client/client2.ovpn

启动服务

1
2
3
systemctl daemon-reload && systemctl restart openvpn
systemctl status openvpn
systemctl enable openvpn

2.5 配置文件和密钥四合一

配置文件加上密钥,需要准备一共四份文件,非常繁琐。
因此可以将配置文件和密钥合并为一个文件,方便传输。
只需将三个密钥的内容复制到配置文件中即可。

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
client
dev tun
proto tcp
remote <服务器ip> <服务器端口>
nobind
resolv-retry infinite
persist-key
persist-tun
verb 3
comp-lzo

<ca>
-----BEGIN CERTIFICATE-----
......
-----END CERTIFICATE-----
</ca>

<cert>
-----BEGIN CERTIFICATE-----
......
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
......
-----END PRIVATE KEY-----
</key>

2.6 自动生成配置文件脚本

手动四合一过程繁琐,故采用脚本自动化签名并生成配置文件。

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
#!/bin/bash

# 检查客户端名称是否提供
if [ -z "$1" ]; then
echo "错误:请输入客户端名称。"
echo "用法: $0 <客户端名称> [服务器IP] [服务器端口]"
exit 1
fi

CLIENT_NAME=$1
SERVER_IP=${2:-"<默认服务器ip>"}
SERVER_PORT=${3:-"<默认服务器端口>"}

# 生成客户端证书
./easyrsa gen-req "$CLIENT_NAME" nopass

# 自动签发证书(自动确认两次提示)
yes yes | ./easyrsa sign-req client "$CLIENT_NAME"

# 创建目标目录并移动证书文件
CERT_DIR="/etc/openvpn/client"
sudo mkdir -p "$CERT_DIR"
sudo cp pki/ca.crt "$CERT_DIR/"
sudo mv "pki/issued/$CLIENT_NAME.crt" "$CERT_DIR/"
sudo mv "pki/private/$CLIENT_NAME.key" "$CERT_DIR/"

# 创建客户端配置文件并嵌入证书
OVPN_FILE="$CERT_DIR/$CLIENT_NAME.ovpn"
sudo tee "$OVPN_FILE" > /dev/null <<EOF
client
dev tun
proto tcp
remote $SERVER_IP $SERVER_PORT
nobind
resolv-retry infinite
persist-key
persist-tun
verb 3
comp-lzo
EOF

# 嵌入CA证书
echo -e "\n<ca>" | sudo tee -a "$OVPN_FILE" > /dev/null
sudo cat "$CERT_DIR/ca.crt" | sudo tee -a "$OVPN_FILE" > /dev/null
echo "</ca>" | sudo tee -a "$OVPN_FILE" > /dev/null

# 嵌入客户端证书
echo -e "\n<cert>" | sudo tee -a "$OVPN_FILE" > /dev/null
sudo sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' "$CERT_DIR/$CLIENT_NAME.crt" | sudo tee -a "$OVPN_FILE" > /dev/null
echo "</cert>" | sudo tee -a "$OVPN_FILE" > /dev/null

# 嵌入客户端密钥
echo -e "\n<key>" | sudo tee -a "$OVPN_FILE" > /dev/null
sudo cat "$CERT_DIR/$CLIENT_NAME.key" | sudo tee -a "$OVPN_FILE" > /dev/null
echo "</key>" | sudo tee -a "$OVPN_FILE" > /dev/null

rm "$CERT_DIR/$CLIENT_NAME.key" "$CERT_DIR/$CLIENT_NAME.crt" "$CERT_DIR/ca.crt"

echo -e "客户端配置完成:$OVPN_FILE \n==============="
cat "$OVPN_FILE"

OpenVPN 搭建与使用
https://heeteve-blog.pages.dev/2024/08/OpenVPN搭建与使用/
作者
Heeteve
发布于
2024年8月4日
许可协议