在 CentOS 7 上部署 OpenVPN 服务


一、OpenVPN 简介

OpenVPN 是一个跨平台且开源的加密隧道(VPN)构建工具,现已被广泛应用于中小企业远程访问 VPN 的部署。

相比其他的远程访问 VPN 协议,OpenVPN 最大的优点在于它仅使用单一的 IP/IPv6 端口(TCP 或 UDP)来建立隧道连接。这使得 OpenVPN 能够很好地适应当前 NAT 已经烂大街的网络环境,同时也支持前置代理。

此外,OpenVPN 不仅能直接在加密隧道中传输 IP 包(TUN 模式),还允许直接在加密隧道中传输以太网帧(TAP 模式)。

不过,OpenVPN 在部署的时候需要维护一个 PKI(公钥基础设施)系统。也就是说,客户端需要通过数字证书来进行身份验证。这是 OpenVPN 部署的难点。

说明
• 新版的 OpenVPN 其实也支持客户端使用用户名密码来进行身份验证,但在现网中依然较少使用。我觉得主要是因为目前 OpenVPN 客户端大多都是通过直接导入现成的配置文件来进行配置的,而客户端的证书和密钥又可以直接嵌入到配置文件中,如果使用用户名密码来进行身份验证的话反而会增加客户端配置的复杂度。还有就是部分 OpenVPN 客户端不支持使用用户名密码来进行身份验证。

本文将介绍如何在 CentOS 7 系统上部署 OpenVPN 服务,最后也简要介绍下如何使用 Windows 系统连接 OpenVPN。


二、网络拓扑图及说明

如图,某小型企业使用 CentOS 7 系统的软路由作为网关。企业内网的网段为 10.100.100.0/24,路由器外网接口的 IP 地址为 100.0.0.1

现在需要在该网关上部署 OpenVPN 来让远程办公人员安全地访问企业内网(但不要通过企业的网关上网)。

考虑到有些平台(如 iOS)不支持 TAP 模式的 OpenVPN,所以这里使用 TUN 模式来部署。加密隧道使用的网段为 10.255.255.0/24

为了保证连接稳定性,客户端与服务器将使用 TCP 来建立连接。客户端连接服务器使用的端口为默认的 1194


三、OpenVPN 服务器的配置

3.1 安装所需软件

执行以下命令:

yum -y install epel-release && \
yum -y install openvpn

3.2 开启 IP 转发

说明
• 如果已经开启 IP 转发则可以忽略本步骤。

执行以下命令:

echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf && \
sysctl -p

3.3 创建服务器配置文件

执行以下命令:

cat << EOF > /etc/openvpn/server/1.conf

请按实际情况以及注释提示修改以下内容,完成后去除 # 号和后面的注释,然后粘贴到命令行窗口中按回车即可。

port <端口号> # 指定提供服务的端口号
proto tcp # 使用 TCP 模式
dev tun # 使用 TUN 模式
ca /etc/openvpn/server/1-pki/ca_cert.pem # 根证书的位置
cert /etc/openvpn/server/1-pki/server_cert.pem # 服务器证书的位置
key /etc/openvpn/server/1-pki/server_key.pem # 服务器密钥的位置
dh /etc/openvpn/server/1-pki/dh.pem # DH 文件的位置
crl-verify /etc/openvpn/server/1-pki/ca_crl.pem # 证书吊销列表的位置
client-to-client # 允许客户端互通
duplicate-cn # 允许同一用户建立多个 VPN 连接
ifconfig-pool-persist ipp.txt # 记住分配给每个用户的地址
server <加密隧道使用的网段> <加密隧道使用的子网掩码> # 设置加密隧道使用的网段及子网掩码
keepalive 1 10 # 每隔 1 秒向客户端发送一个心跳包,若连续 10 次不回应则断开连接
comp-lzo # 使用 LZO 压缩数据
status /tmp/vpn.status 10
EOF

例如这里是:

port 1194
proto tcp
dev tun
ca /etc/openvpn/server/1-pki/ca_cert.pem
cert /etc/openvpn/server/1-pki/server_cert.pem
key /etc/openvpn/server/1-pki/server_key.pem
dh /etc/openvpn/server/1-pki/dh.pem
crl-verify /etc/openvpn/server/1-pki/crl.pem
client-to-client
duplicate-cn
ifconfig-pool-persist ipp.txt
server 10.255.255.0 255.255.255.0
keepalive 1 10
comp-lzo
status /tmp/vpn.status 10
EOF

3.4 PKI 系统的配置

⚠️ 注意
• 请确保服务器的时间是正确的。

3.4.1 创建证书存储目录

执行以下命令:

mkdir -p /etc/openvpn/server/1-pki && \
cd /etc/openvpn/server/1-pki

3.4.2 创建证书序号文件以及签发列表

执行以下命令:

echo 01 > serial && \
touch index.txt 

3.4.3 创建 OpenSSL 配置文件

执行以下命令:

cat << EOF > openssl.cnf

以下内容直接粘贴到命令行窗口中按回车即可。

[ ca ]
default_ca = openvpn                

[ openvpn ]
dir = .
database = \$dir/index.txt
new_certs_dir = \$dir
certificate = \$dir/ca_cert.pem
serial = \$dir/serial
private_key = \$dir/ca_key.pem 
RANDFILE = \$dir/.rand

default_bits = 4096
default_days = 36500                    
default_crl_days = 36500                    
default_md = sha512                    
unique_subject = no                     

policy = policy_anything            

[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = supplied
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
EOF

3.4.4 创建 CA 证书

执行以下命令:

openssl req -x509 -nodes -days 36500 -newkey rsa:4096 -keyout ca_key.pem -out ca_cert.pem -new -sha512 -subj "/O=OpenVPN/CN=CA/"

3.4.5 签发服务器证书

执行以下命令:

openssl req -nodes -new -days 36500 -newkey rsa:4096 -keyout server_key.pem -out server_csr.pem -subj "/O=OpenVPN/CN=Server/" && \
openssl ca -in server_csr.pem -out server_cert.pem -config openssl.cnf && rm -rf server_csr.pem

然后按 y 回车两次即可确认签发。

3.4.6 签发用户证书

格式

以后如果想签发用户证书的话直接按照这个格式执行命令就可以了。

cd /etc/openvpn/server/1-pki/ && \
openssl req -nodes -new -days 36500 -newkey rsa:4096 -keyout user_<用户名>_key.pem -out user_<用户名>_csr.pem -subj "/O=OpenVPN/CN=<用户名>/" && \
openssl ca -in user_<用户名>_csr.pem -out user_<用户名>_cert.pem -config openssl.cnf && \
rm -rf user_<用户名>_csr.pem

例如

用户名为 user1

执行以下命令:

cd /etc/openvpn/server/1-pki/ && \
openssl req -nodes -new -days 36500 -newkey rsa:4096 -keyout user_user1_key.pem -out user_user1_csr.pem -subj "/O=OpenVPN/CN=user1/" && \
openssl ca -in user_user1_csr.pem -out user_user1_cert.pem -config openssl.cnf && \
rm -rf user_user1_csr.pem

y 回车两次即可确认签发。

3.4.7 证书字段的定义

上面三个步骤中 -subj 后面的参数即为证书的字段,可按以下说明自定义。

字段名 说明
O 组织名。所有证书必须保持一致
CN 公用名称。不能出现重复。用户证书中此字段作为用户名

3.4.8 创建证书吊销列表

执行以下命令:

openssl ca -gencrl -keyfile ca_key.pem -cert ca_cert.pem -out crl.pem -config openssl.cnf

3.4.9 吊销证书(可选)

如果有用户泄漏了证书的私钥,或者不再使用 VPN 服务,可以通过以下命令来吊销证书以防止非法接入(直接删除服务器上的证书是没有任何作用的)。如果该 VPN 只有一人使用或者只使用一张证书的话,也可以将整个 PKI 系统删掉然后重建。

格式

以后如果想吊销证书的话直接按照这个格式执行命令就可以了。

cd /etc/openvpn/server/1-pki/ && \
openssl ca -revoke user_<用户名>_cert.pem -config openssl.cnf && \
openssl ca -gencrl -keyfile ca_key.pem -cert ca_cert.pem -out crl.pem -config openssl.cnf

例如

创建一个用户名为 fake_user1 的证书。

执行以下命令:

cd /etc/openvpn/server/1-pki/ && \
openssl req -nodes -new -days 36500 -newkey rsa:4096 -keyout user_fake_user1_key.pem -out user_fake_user1_csr.pem -subj "/O=OpenVPN/CN=fake_user1/" && \
openssl ca -in user_fake_user1_csr.pem -out user_fake_user1_cert.pem -config openssl.cnf && \
rm -rf user_fake_user1_csr.pem

接着吊销该证书。

执行以下命令:

openssl ca -revoke user_fake_user1_cert.pem -config openssl.cnf && \
openssl ca -gencrl -keyfile ca_key.pem -cert ca_cert.pem -out crl.pem -config openssl.cnf

注意
• 由于 OpenVPN 服务器在每次客户端连接的时候都会读取证书吊销列表,所以无需重启 OpenVPN 服务即可生效。

3.5 生成 DH 文件

执行以下命令:

openssl dhparam -out /etc/openvpn/server/1-pki/dh.pem 4096

速度可能会有些慢,请耐心等待!

3.6 启动服务

执行以下命令:

systemctl start [email protected]

如需开机启动,请执行:

systemctl enable [email protected]

3.7 防火墙放行端口

以 iptables 为例,端口为默认的 1194(TCP)。

执行以下命令:

iptables -A INPUT -p tcp --dport 1194 -j ACCEPT

然后根据需要自行保存防火墙的配置。


四、创建 OpenVPN 客户端配置文件

请按实际情况以及注释提示修改以下内容,完成后去除 # 号和后面的注释,然后保存为后缀名为 .ovpn 的文件。

⚠️ 注意
• 该文件包含客户端的私钥,请妥善保管。如果不慎泄漏请及时到服务器上吊销相应的证书。

client
proto tcp # 使用 TCP 模式
remote <服务器 IP/域名> <端口号> # 指定服务器的 IP 地址/域名和端口号
dev tun # 使用 TUN 模式
ca [inline] # 使用内嵌的根证书
cert [inline] # 使用内嵌的客户端证书
key [inline] # 使用内嵌的客户端密钥
comp-lzo # 使用 LZO 压缩数据
keepalive 1 10 # 每隔 1 秒向服务器发送一个心跳包,若连续 10 次不回应则断开连接
route-nopull # 不要使用服务器提供的路由信息
route <要通过 VPN 访问的网段> <要通过 VPN 访问的网段的子网掩码> vpn_gateway # 指定要走 VPN 的网段(一个网段一行)

# 配置根证书
<ca>
# 此处填入服务器中 /etc/openvpn/server/1-pki/ca_cert.pem 文件的内容
</ca>

# 配置客户端证书
<cert>
# 此处填入服务器中 /etc/openvpn/server/1-pki/user_<用户名>_cert.pem 文件的内容
</cert>

# 配置客户端密钥
<key>
# 此处填入服务器中 /etc/openvpn/server/1-pki/user_<用户名>_key.pem 文件的内容
</key>

如果按照上面的例子并且用户名为 user1 的话,那么配置文件的内容应该是:

client
proto tcp
remote 100.0.0.1
dev tun
ca [inline]
cert [inline]
key [inline]
comp-lzo
keepalive 1 10
route-nopull
route 10.100.100.0 255.255.255.0 vpn_gateway

<ca>
-----BEGIN CERTIFICATE-----
...(省略)
-----END CERTIFICATE-----
</ca>

<cert>
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number: 2 (0x2)
    Signature Algorithm: sha512WithRSAEncryption
        Issuer: O=OpenVPN, CN=CA
        Validity
            Not Before: Jan 12 02:17:56 2019 GMT
            Not After : Dec 19 02:17:56 2118 GMT
        Subject: O=OpenVPN, CN=user1
...(省略)
-----BEGIN CERTIFICATE-----
...(省略)
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
...(省略)
-----END PRIVATE KEY-----
</key>

五、OpenVPN 客户端的配置(Windows)

说明
• 以 Windows 7 为例说明。

5.1 安装 OpenVPN 客户端

使用浏览器打开以下链接:

Community Downloads | OpenVPN

然后点击「WINDOWS INSTALLER」这一栏中的链接(如下图)下载软件包。下载完成之后打开然后一直下一步安装即可。

说明
• 在安装过程中如果弹出「您想安装这个设备软件吗?」这个对话框的话,请点击「安装」。
• 在安装过程中如果提示未安装 .NET Framework 4.0 的话,按提示安装即可。

5.2 导入配置文件

将后缀名为 .ovpn 的配置文件放到 %HOMEPATH%/OpenVPN/config/ 中。

5.3 连接 OpenVPN

⚠️ 注意
• 请确保客户端的时间是正确的。

双击打开桌面上的「OpenVPN GUI」。如下图:

然后右键点击任务栏右下角新出现的图标,选择「Connect」即可连接。如下图:

如果连接成功,会有下图的提示:

5.4 测试

连接成功后,我们 ping 一下企业内网的主机:

可以看到,企业内网的主机已经能够 ping 通。验证通过。

我们再来看一下路由表:

可以看到,只有企业内网的流量走 VPN,默认路由并没有因为 VPN 的连接而发生改变。验证通过。

发表评论

电子邮件地址不会被公开。