OpenVPN 服务端与客户端的搭建与配置
OpenVPN 是一种开源的虚拟私人网络(VPN)协议,旨在为企业和个人提供安全的网络连接。它使用 OpenSSL 库和 SSLv3/TLSv1 协议来加密传输的数据,确保通信的安全性和隐私性。这篇文章将记录如何搭建与配置 OpenVPN 服务端与客户端。
请注意,本文仅用于教育和技术交流目的,旨在提供搭建和配置 OpenVPN 服务器的技术指导。我们坚决反对并谴责任何利用本文提供的信息进行非法活动的行为。读者应确保其使用 OpenVPN 的方式符合当地法律法规,并仅将其用于合法、合规的用途。对于因使用本文内容而产生的任何法律责任,作者及发布平台概不负责
服务端搭建
服务端演示环境:
Ubuntu 24.04.1 LTS x86_64
OpenVPN 2.6.12 x86_64-pc-linux-gnu
(由于使用 Windows 系统来搭建 OpenVPN 服务端的场景较少,所以这里将不会演示使用 Windows 的搭建步骤)
步骤
-
安装所需软件包
更新系统并安装OpenVPN以及EasyRSA
sudo apt update && sudo apt upgrade -y sudo apt install openvpn easy-rsa
-
配置EasyRSA
-
创建EasyRSA的工作目录
mkdir /opt/easy-rsa
-
复制EasyRSA到目录
cp -a /usr/share/easy-rsa/* /opt/easy-rsa/ cd /opt/easy-rsa/
完整操作日志
# 创建 EasyRSA 目录 root@huajibenji:/# mkdir /opt/easy-rsa root@huajibenji:/# cd /opt/easy-rsa/ # 复制 EasyRSA 到刚才创建的目录内 root@huajibenji:/opt/easy-rsa# cp -a /usr/share/easy-rsa/* /opt/easy-rsa root@huajibenji:/opt/easy-rsa# ls easyrsa openssl-easyrsa.cnf vars.example x509-types
-
-
生成服务器证书以及密钥
-
初始化 PKI (公钥基础设施)
./easyrsa init-pki
-
生成 CA (证书颁发机构)
./easyrsa build-ca
- 系统会提示设置一个 CA 密码(用于保护 CA,输入密码的过程中将不会显示任何信息,输入完成后请按回车)
设置完密码后,服务器会让你设置一个通用名称,此名称可以是你的用户、主机名或者服务器名
完整操作日志
# 请先使用 ./easyrsa init-pki 初始化后,再执行此步操作 # 生成 CA Key (生成证书的时候需要) root@huajibenji:/opt/easy-rsa# ./easyrsa build-ca No Easy-RSA 'vars' configuration file exists! # 这个报错理论上可以不用管,似乎不会影响后续的证书生成、签发 Using SSL: * openssl OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024) Enter New CA Key Passphrase: # (设置CA Key密码) Confirm New CA Key Passphrase: # (确认CA Key密码) ......(此处省略) ----- 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]:huajibenji Notice ------ # 这里告诉了你密钥和证书都保存在哪的 CA creation complete. Your new CA certificate is at: * /opt/easy-rsa/pki/ca.crt
- 系统会提示设置一个 CA 密码(用于保护 CA,输入密码的过程中将不会显示任何信息,输入完成后请按回车)
-
生成服务器的密钥和证书签名请求(CSR)
./easyrsa gen-req server nopass
- 生成的密钥文件为
server.key
,CSR 文件为server.req
完整操作日志
# 生成服务器的密钥和证书签名请求(CSR) root@huajibenji:/opt/easy-rsa# ./easyrsa gen-req server nopass No Easy-RSA 'vars' configuration file exists! Using SSL: * openssl OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024) ......(此处省略) ----- 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]:huajibenji Notice ------ Private-Key and Public-Certificate-Request files created. # 这里告诉了你密钥和证书都保存在哪的 Your files are: * req: /opt/easy-rsa/pki/reqs/server.req * key: /opt/easy-rsa/pki/private/server.key
- 生成的密钥文件为
-
使用 CA 签署服务器证书
./easyrsa sign-req server server
- 输入 “yes” 确认签署操作,这会生成签署后的服务器证书
server.crt
完整操作日志
# 使用 CA 签署服务器证书 root@huajibenji:/opt/easy-rsa# ./easyrsa sign-req server server No Easy-RSA 'vars' configuration file exists! Using SSL: * openssl OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024) 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= # 这里的通用名称就是刚才3.3步设置的通用名称(commonName) commonName = huajibenji Type the word 'yes' to continue, or any other input to abort. Confirm request details: yes # 这里需要输入‘yes’来确认继续操作 Using configuration from /opt/easy-rsa/pki/openssl-easyrsa.cnf Enter pass phrase for /opt/easy-rsa/pki/private/ca.key: # 这里输入上面给 CA Key 设置的密码。同样,输入的时候不会有任何提示。输入完成后按下回车以继续 Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows # 设置通用名称(例如你的用户、主机名或者服务器名。这里不一定要按照我的来) commonName :ASN.1 12:'huajibenji' Certificate is to be certified until Apr 25 13:30:33 2027 GMT (825 days) Write out database with 1 new entries Database updated Notice ------ # 这里告诉了你密钥和证书都保存在哪的 Certificate created at: * /opt/easy-rsa/pki/issued/server.crt
- 输入 “yes” 确认签署操作,这会生成签署后的服务器证书
-
-
生成客户端证书
-
为客户端生成密钥以及 CSR
./easyrsa gen-req server_client1 nopass
- 其中
server_client1
是客户端的名称,你可以替换为你需要的名称
在为客户端生成密钥的时候,会让你设置一个通用名称(Common Name)。设置完通用名称后请牢记此名称,后面要用(比如CCD
设置。关于CCD
,请参照此篇笔记的客户端示例配置文件的client-config-dir
选项解释)
这里的通用名称将会使用server_1
来举例
完整操作日志
# 为客户端生成密钥和 CSR root@huajibenji:/opt/easy-rsa# ./easyrsa gen-req server_client1 nopass No Easy-RSA 'vars' configuration file exists! Using SSL: * openssl OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024) ......(此处省略) ----- 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_client1]:server_1 # 通用名称设置为server_1 Notice ------ Private-Key and Public-Certificate-Request files created. # 这里告诉了你密钥和证书都保存在哪的 Your files are: * req: /opt/easy-rsa/pki/reqs/server_client1.req * key: /opt/easy-rsa/pki/private/server_client1.key
(以下是可选步骤,如果你不需要生成多个密钥的话请忽略)
理论上,这里可以生成多个客户端的密钥,更改其中的客户端名称,即可生成其他客户端的密钥。如我要生成另外一个客户端
server_client2
的密钥,那么接下来需要这样操作./easyrsa gen-req server_client2 nopass
如果需要生成更多的密钥,那么接下来的操作和上述步骤差不多,只需更改客户端名称即可(不要重复)
- 其中
-
使用 CA 签署客户端证书
./easyrsa sign-req client server_client1
- 其中
server_client1
是客户端的名称,请替换为之前(步骤4.1)设置的客户端名称 - 签署时,服务器会要求你提供 CA Key 的密码,同样输入密码的过程中将不会显示任何信息,输入完成后请按回车
完整操作日志
# 使用 CA 签署客户端证书 root@huajibenji:/opt/easy-rsa# ./easyrsa sign-req client server_client1 No Easy-RSA 'vars' configuration file exists! Using SSL: * openssl OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024) 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 = server_1 Type the word 'yes' to continue, or any other input to abort. Confirm request details: yes # 这里需要输入‘yes’来确认继续操作 Using configuration from /opt/easy-rsa/pki/openssl-easyrsa.cnf Enter pass phrase for /opt/easy-rsa/pki/private/ca.key: # 输入生成 CA Key 时设置的密码 Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows # 设置通用名称(例如你的用户、主机名或者服务器名。这里不一定要按照我的来) commonName :ASN.1 12:'server_1' # 签发证书时设置的通用名称(步骤4.1设置的通用名称) Certificate is to be certified until Apr 25 14:06:09 2027 GMT (825 days) Write out database with 1 new entries Database updated Notice ------ # 这里告诉了你密钥和证书都保存在哪的 Certificate created at: * /opt/easy-rsa/pki/issued/server_client1.crt
(以下是可选步骤,如果你不需要签署多个客户端的证书的话请忽略)
同样,如果需要签署多个客户端的证书,那么接下来的操作与上述步骤差不多,只需更改之前设置的客户端名称(密钥命名)即可
./easyrsa sign-req client server_client2
- 其中
-
-
生成 Diffie-Hellman (DH) 参数
DH 参数用于安全密钥的交换
./easyrsa gen-dh
- 生成的文件为
dh.pem
,生成时可能会消耗一定时间
完整操作日志
# 生成Diffie-Hellman参数(这里将会消耗一定时间) root@huajibenji:/opt/easy-rsa# ./easyrsa gen-dh No Easy-RSA 'vars' configuration file exists! Using SSL: * openssl OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024) Generating DH parameters, 2048 bit long safe prime ......(此处省略) DH parameters appear to be ok. Notice ------ # 这里告诉了你DH参数是放在哪的 DH parameters of size 2048 created at: * /opt/easy-rsa/pki/dh.pem
到这里,证书生成的部分已经完成了,你可以在网页的侧栏点击“总结(对应步骤3-5)”到下文去查看上述步骤的总结
- 生成的文件为
-
配置 OpenVPN 服务端
接下来需要配置 OpenVPN 服务端
-
将生成的文件复制到 OpenVPN 的工作目录
sudo cp pki/ca.crt pki/issued/server.crt pki/private/server.key pki/dh.pem /etc/openvpn/server
在一般情况下
/etc/openvpn/server
是默认创建好了的,如果没有,请创建此目录,创建完成后再将生成的文件复制到此目录sudo mkdir -p /etc/openvpn/server
此时,所有的证书都已经存放在
/etc/openvpn/server
内了。在后续配置 OpenVPN 的配置文件时可能需要用到此目录(因为证书什么的都在这个目录里) -
配置 OpenVPN 的配置文件
首先需要将示例配置文件复制到 OpenVPN 的工作目录。在一般情况下,示例配置文件的目录在
/usr/share/doc/openvpn/examples/sample-config-files
cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf /etc/openvpn/
接下来配置 OpenVPN 服务端的配置文件
vim /etc/openvpn/server.conf
同样的,进入
vim
编辑器页面后,按下i
来启用插入模式(左下角显示-- INSERT --
表示启用成功,如果你的系统使用了中文语言包,那么将会显示为-- 插入 --
)。完成对配置文件的编辑后,按下:
进入vim
编辑器的命令行模式,随后输入wq
来对配置文件进行一个保存,并退出编辑器。此时你会回到终端命令行页面为了方便理解其中每一个配置项的意思,这里提供一份根据示例配置文件来对照翻译的服务端配置文件(请注意,其中配置大部分的内容是由AI翻译,这里给出配置文件的翻译仅仅只是为了方便理解其中选项的含义,并不代表本笔记作者对其中已翻译内容的认可。另外请不要直接复制这篇翻译的内容直接放到您的配置文件中,以免出现意外情况。)
另外,如果你不会写配置文件,那么你可以参考下文的示例配置文件
################################################# # Sample OpenVPN 2.6 config file for # # multi-client server. # # # # This file is for the server side # # of a many-clients <-> one-server # # OpenVPN configuration. # # # # OpenVPN also supports # # single-machine <-> single-machine # # configurations (See the Examples page # # on the web site for more info). # # # # This config should work on Windows # # or Linux/BSD systems. Remember on # # Windows to quote pathnames and use # # double backslashes, e.g.: # # "C:\\Program Files\\OpenVPN\\config\\foo.key" # # # # Comments are preceded with '#' or ';' # ################################################# # OpenVPN应该监听哪个本地IP地址? # (可选) ;local a.b.c.d # 指定OpenVPN Server运行的端口 # OpenVPN应该监听哪个TCP/UDP端口? # 如果您想在同一台机器上运行多个OpenVPN实例, # 每个实例使用不同的端口号。您需要在防火墙上 # 打开这个端口。 port 1194 # 使用TCP还是UDP? ;proto tcp proto udp # “dev tun”将创建一个路由IP隧道, # “dev tap”将创建一个以太网隧道。 # 如果你进行以太网桥接,并且已经预先创建了一个tap0虚拟接口 # 并将其与你的以太网接口桥接,请使用“dev tap0”。 # 如果你想要控制VPN上的访问策略,你必须为TUN/TAP接口创建防火墙 # 规则。 # 在非Windows系统上,你可以给出一个明确的单元号,例如tun0。 # 在Windows上,为此使用“dev-node”。 # 在大多数系统上,除非你部分或完全禁用/打开TUN/TAP接口的防火墙,否则VPN将无法正常工作。 # # 在这里,dev tun是最常用的模式,适合大部分的应用场景 ;dev tap dev tun # Windows需要网络连接面板中的TAP-Win32适配器名称 # 如果你有多个适配器的话。 # 你可能需要有选择地禁用 # Windows防火墙的TAP适配器。 # 非Windows系统通常不需要此操作。 ;dev-node MyTap # SSL/TLS根证书(ca)、证书 # (cert)和私钥(key)。每个客户端 # 和服务器都必须有自己的证书和 # 密钥文件。服务器和所有客户端将 # 使用相同的ca文件。 # # 有关生成RSA证书的更多信息,请参阅“easy-rsa”项目 # 和私钥,可访问 # https://github.com/OpenVPN/easy-rsa # 记住为服务器和每个客户端证书使用 # 唯一的通用名称。 # # 可以使用任何X509密钥管理系统。 # OpenVPN也可以使用PKCS #12格式的密钥文件 # (请参阅手册页中的“pkcs12”指令)。 # # 如果您不想维护CA # 并且只有少量客户端 # 您也可以使用自签名证书 # 并使用peer-fingerprint选项。 # 有关配置示例,请参阅openvpn-examples手册页。 # 这里假设所有的证书、密钥文件都是放在/etc/openvpn/server里的 # 请根据实际情况更改目录,如果路径配置错误,可能会导致OpenVPN服 # 务器无法正常启动 ca /etc/openvpn/server/ca.crt cert /etc/openvpn/server/server.crt key /etc/openvpn/server/server.key # 此文件应保密 # Diffie Hellman参数。 # 使用以下命令生成你自己的参数: # openssl dhparam -out dh2048.pem 2048 # 这里假设所有的证书、密钥文件都放在/etc/openvpn/server里的 # 请根据实际情况更改目录,如果路径配置错误,可能会导致OpenVPN服 # 务器无法正常启动 dh /etc/openvpn/server/dh.pem # 允许连接到非常旧的 OpenVPN 版本 # 不支持 AEAD(OpenVPN 2.3.x 或更早版本) # 这会将 AES-256-CBC 添加为回退密码 # 并保留现代密码。 ;data-ciphers AES-256-GCM:AES-128-GCM:?CHACHA20-POLY1305:AES-256-CBC # 网络拓扑 # 应该是子网(通过IP进行寻址) # 除非需要支持Windows客户端v2.0.9及更低版本 # (那时应使用net30,即每个客户端一个/30) # 默认设置为net30(不推荐) topology subnet # 配置服务器模式并提供一个VPN子网 # 供OpenVPN分配客户端地址。 # 服务器将为自己保留10.8.0.1, # 其余的地址将分配给客户端。 # 每个客户端都能够通过10.8.0.1访问服务器。如果你正在 # 进行以太网桥接,请注释掉这一行。更多信息请参阅手册页。 server 10.8.0.0 255.255.255.0 # 在此文件中维护客户端 <-> 虚拟IP地址 # 关联记录。如果OpenVPN宕机或 # 重启,重新连接的客户端可以被分配 # 之前从池中分配的相同虚拟IP地址。 ifconfig-pool-persist /var/log/openvpn/ipp.txt # 配置以太网桥接的服务器模式。 # 您必须首先使用操作系统的桥接功能 # 将TAP接口与以太网 # NIC接口桥接。然后您必须手动设置 # 桥接接口的IP/子网掩码,在这里我们假设是10.8.0.4/255.255.255.0。最后,我们必须在这个子网中留出一个IP范围 # (起始=10.8.0.50 结束=10.8.0.100)分配 # 给连接的客户端。除非您进行以太网桥接,否则请保留此行注释。 ;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100 # 配置以太网桥接的服务器模式 # 使用DHCP代理,客户端与OpenVPN服务器端的DHCP服务器通信 # 以接收IP地址分配和DNS服务器地址。您必须首先使用 # 操作系统的桥接功能将TAP接口与以太网NIC接口桥接。 # 注意:此模式仅适用于客户端(例如Windows),其中客户端侧的TAP适配器 # 绑定到DHCP客户端。 ;server-bridge # 向客户端推送路由以允许其 # 到达服务器后面的其他私有子网。请记住,这些 # 私有子网也需要知道将OpenVPN客户端 # 地址池(10.8.0.0/255.255.255.0) # 路由回OpenVPN服务器。 ;push "route 192.168.10.0 255.255.255.0" ;push "route 192.168.20.0 255.255.255.0" # 为特定客户端分配特定IP地址, # 或如果连接的客户端在其后面有一个应该具有VPN访问权限的私有子网, # 使用子目录"ccd"来存放客户端特定的配置文件(更多信息请参见手册页)。 # 示例:假设具有证书通用名称"Thelonious"的客户端 # 在其连接的机器后面还有一个小型子网, # 例如192.168.40.128/255.255.255.248。 # 首先,取消注释以下这些行: ;client-config-dir ccd ;route 192.168.40.128 255.255.255.248 # 然后创建一个文件 ccd/Thelonious,内容为: # iroute 192.168.40.128 255.255.255.248 # 这将允许 Thelonious 的私有子网 # 访问 VPN。此示例仅在您进行路由而不是桥接时有效, # 即您使用的是 "dev tun" 和 "server" 指令。 # 示例:假设您想给 Thelonious 分配一个固定的 VPN IP 地址 10.9.0.1。 # 首先取消以下行的注释: ;client-config-dir ccd ;route 10.9.0.0 255.255.255.252 # 然后添加这一行到 ccd/Thelonious: # ifconfig-push 10.9.0.1 10.9.0.2 # 假设你想要为不同的客户端组启用不同的 # 防火墙访问策略。有两种方法: # (1) 运行多个 OpenVPN 守护进程,每个组一个, # 并适当为每个组/守护进程的 TUN/TAP 接口设置防火墙。 # (2) (高级)创建一个脚本,以动态地根据来自不同客户端的访问 # 修改防火墙。有关 learn-address 脚本的更多信息,请参阅手册页。 ;learn-address ./script # 如果启用,此指令将配置 # 所有客户端将其默认的 # 网络网关通过VPN重定向,导致 # 所有IP流量,如网页浏览和 # DNS查询都将通过VPN进行 # (OpenVPN服务器可能需要对 # TUN/TAP接口进行NAT或桥接到互联网 # 以便此功能正常工作)。 ;push "redirect-gateway def1 bypass-dhcp" # 某些特定于 Windows 的网络设置 # 可以推送到客户端,例如 DNS # 或 WINS 服务器地址。注意事项: # http://openvpn.net/faq.html#dhcpcaveats # 下面的地址是指由 opendns.com 提供的公共 # DNS 服务器。 ;push "dhcp-option DNS 208.67.222.222" ;push "dhcp-option DNS 208.67.220.220" # 取消此指令的注释以允许不同的 # 客户端能够“看到”彼此。 # 默认情况下,客户端只会看到服务器。 # 要强制客户端只看到服务器,你还需要适当防火墙服务器的 # TUN/TAP接口。 ;client-to-client # 取消此指令的注释,如果多个客户端 # 可能使用相同的证书/密钥 # 文件或通用名称连接。这仅推荐 # 用于测试目的。对于生产使用, # 每个客户端应有自己的证书/密钥对。 # # 如果您尚未为每个客户端生成单独的 # 证书/密钥对, # 每个都有其唯一的“通用名称”, # 取消此行的注释。 ;duplicate-cn # keepalive指令导致类似ping的消息 # 在链接两端来回发送,以便每一端都知道 # 对端何时断开。 # 每10秒ping一次,在120秒的时间段内如果没有收到 # ping,则认为远程对等方已断开。 keepalive 10 120 # 为了获得超出SSL/TLS提供的安全性的额外保障,创建一个"HMAC防火墙" # 以帮助阻止拒绝服务攻击和UDP端口洪泛。 # # 使用以下命令生成: # openvpn --genkey tls-auth ta.key # # 服务器和每个客户端必须拥有 # 该密钥的副本。 # 第二个参数在服务器上应为'0',在客户端上应为'1'。 ;tls-auth ta.key 0 # 这个文件应当保密 # 我们希望允许的最大并发连接客户端数量。 ;max-clients 100 # 在初始化后降低OpenVPN # 守护进程的权限是个好主意。 # # 你可以在非Windows系统上取消注释这一行 # 在创建一个专用用户之后。 ;user openvpn ;group openvpn # 持久化选项将尽量避免 # 在重启时访问可能由于 # 权限降低而无法再访问的某些资源。 persist-key persist-tun # 输出一个简短的状态文件,显示 # 当前连接,每分钟截断并重写。 status /var/log/openvpn/openvpn-status.log # 默认情况下,日志消息将发送到系统日志(或 # 在 Windows 上,如果作为服务运行,则会发送到 # "\Program Files\OpenVPN\log" 目录)。 # 使用 log 或 log-append 可覆盖此默认设置。 # "log" 在 OpenVPN 启动时会截断日志文件, # 而 "log-append" 则会追加到日志文件。使用其中 # 一个(但不要同时使用两个)。 ;log /var/log/openvpn/openvpn.log ;log-append /var/log/openvpn/openvpn.log # 设置适当的日志级别 # 文件详细程度。 # # 0 表示静默,除致命错误外不输出任何信息 # 4 对于一般使用是合理的 # 5 和 6 可以帮助调试连接问题 # 9 是非常详细的 verb 5 # 静默重复的消息。最多 # 20 条相同消息类别的连续消息 # 将输出到日志。 ;mute 20 # 通知客户端服务器重启时 # 它可以自动重新连接。
-
-
启动 OpenVPN 服务器
systemctl start openvpn@server
-
这里
openvpn@server
的server
指的是server.conf
(它对应于/etc/openvpn/
目录下的server.conf
配置文件。当然通过使用不同的实例名称,你可以使用不同的配置文件运行多个 OpenVPN 服务器)假如你的 OpenVPN 服务端的配置文件命名
server_1.conf
,那么启动 OpenVPN 服务器时就需要在终端执行systemctl start openvpn@server_1
如果你想要让 OpenVPN 在启动服务器时自动启动,那么就需要在终端执行
systemctl enable openvpn@server
最后检查一下 OpenVPN 服务器的状态
systemctl status openvpn@server
不出意外,你应该会在终端中看到
● openvpn@server.service - OpenVPN connection to server Loaded: loaded (/usr/lib/systemd/system/openvpn@.service; enabled-runtime; preset: enabled) Active: active (running) since Tue 2025-01-21 02:31:37 CST; 14h ago Docs: man:openvpn(8) https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage https://community.openvpn.net/openvpn/wiki/HOWTO Main PID: 25089 (openvpn) Status: "Initialization Sequence Completed" Tasks: 1 (limit: 10) Memory: 1.4M (peak: 1.7M) CPU: 920ms ......(省略)
关键:
Active: active (running) since Tue yyyy-mm-dd hh:mm:ss CST; xxxh ago
如果不是,那么请看下文的常见问题,或者必应搜索解决方案
在终端执行
ip a
会列出所有服务器上面的网卡等等
另外如果你注意到了的话,你会发现服务器多了一个网卡。例如
tun0
,这里网卡名对应配置文件里的dev tun
250: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500 link/none inet 10.8.0.1 peer 10.8.0.2/32 scope global tun0 valid_lft forever preferred_lft forever inet6 fe80::e02d:9ddb:61a6:26f9/64 scope link stable-privacy valid_lft forever preferred_lft forever
-
-
开启防火墙
当然,为了让其他的客户端能够正确连接到 OpenVPN 服务端,这里肯定是需要开放防火墙的
如果你在配置文件中设置的协议是
UDP
(配置文件对应项proto udp
),那么就需要在终端执行# 这里假设配置文件中设置的端口号为 1194 ufw allow 1194/udp
同样,如果你设置的协议是
TCP
(配置文件对应项proto tcp
),那么就需要在终端执行ufw allow 1194/tcp
执行完成后,如果终端返回
Rules updated
则表示设置完成如果你用的是一些云服务器(比如阿里云、腾讯云或AWS等等,则需要在云服务器控制台安全组开放防火墙端口。
同样如果你在 OpenVPN 设置的是
TCP
,那么安全组的协议那部分就应该填TCP
。如果设置的是UDP
,那么同样以此类推
总结(对应步骤3-5)
因为证书以及密钥签署的部分比较复杂且对于萌新来说可能比较难懂,这里将会对上文(证书、密钥签署)部分进行一个总结(该总结使用了AI,仅供参考)
-
生成 CA 证书和密钥
步骤:在步骤 3.2 执行
./easyrsa build-ca
生成的文件:
- CA 证书:
/opt/easy-rsa/pki/ca.crt
- CA 密钥:
/opt/easy-rsa/pki/private/ca.key
说明:CA 是用于签署其他证书的根证书,在此过程中需要设置 CA 密钥密码和通用名称(如
huajibenji
)。 - CA 证书:
-
生成服务器证书签名请求(CSR)和密钥
步骤:在步骤 3.3 执行
./easyrsa gen-req server nopass
生成的文件:
- 服务器密钥:
/opt/easy-rsa/pki/private/server.key
- 服务器 CSR 文件:
/opt/easy-rsa/pki/reqs/server.req
说明:此步骤仅生成了服务器证书的密钥和签名请求文件,尚未生成最终的服务器证书。
- 服务器密钥:
-
使用 CA 签署服务器证书
步骤:在步骤 3.4 执行
./easyrsa sign-req server server
生成的文件:
- 签署后的服务器证书:
/opt/easy-rsa/pki/issued/server.crt
说明:CA 密钥
ca.key
用于签署服务器 CSR 文件,生成了服务器证书server.crt
。签署过程中需要输入 CA 密钥的密码。 - 签署后的服务器证书:
-
生成客户端证书签名请求(CSR)和密钥
步骤:在步骤 4.1 执行
./easyrsa gen-req server_client1 nopass
生成的文件:
- 客户端密钥:
/opt/easy-rsa/pki/private/server_client1.key
- 客户端 CSR 文件:
/opt/easy-rsa/pki/reqs/server_client1.req
说明:此步骤生成了客户端
server_client1
的密钥和 CSR 文件。 - 客户端密钥:
-
使用 CA 签署客户端证书
步骤:在步骤 4.2 执行
./easyrsa sign-req client server_client1
生成的文件:
- 签署后的客户端证书:
/opt/easy-rsa/pki/issued/server_client1.crt
说明:CA 密钥
ca.key
用于签署客户端 CSR 文件,生成了客户端证书server_client1.crt
。签署过程中需要输入 CA 密钥的密码。 - 签署后的客户端证书:
-
生成 Diffie-Hellman 参数
步骤:在步骤 5 执行
./easyrsa gen-dh
生成的文件:
- Diffie-Hellman 参数文件:
/opt/easy-rsa/pki/dh.pem
说明:生成 DH 参数,用于确保密钥交换的安全性。
- Diffie-Hellman 参数文件:
对照表格:
步骤编号 | 生成项 | 文件名称 | 文件路径 | 通用名称 |
---|---|---|---|---|
3.2 | CA 证书 | ca.crt |
/opt/easy-rsa/pki/ca.crt |
huajibenji |
3.3 | 服务器密钥 | server.key |
/opt/easy-rsa/pki/private/server.key |
huajibenji |
3.3 | 服务器证书签名请求 (CSR) | server.req |
/opt/easy-rsa/pki/reqs/server.req |
huajibenji |
3.4 | 服务器证书 | server.crt |
/opt/easy-rsa/pki/issued/server.crt |
huajibenji |
4.1 | 客户端密钥 | server_client1.key |
/opt/easy-rsa/pki/private/server_client1.key |
server_1 |
4.1 | 客户端证书签名请求 (CSR) | server_client1.req |
/opt/easy-rsa/pki/reqs/server_client1.req |
server_1 |
4.2 | 客户端证书 | server_client1.crt |
/opt/easy-rsa/pki/issued/server_client1.crt |
server_1 |
5 | Diffie-Hellman 参数 | dh.pem |
/opt/easy-rsa/pki/dh.pem |
不适用 |
签署关系
- CA 证书(
ca.crt
)和密钥(ca.key
):用于签署服务器和客户端证书。 - 服务器证书签名请求(
server.req
)由 CA 签署后生成服务器证书(server.crt
)。 - 客户端证书签名请求(
server_client1.req
)由 CA 签署后生成客户端证书(server_client1.crt
)。
常见问题
-
failed to find GID for group openvpn
(权限问题)如果你在配置文件中设置了用户组:
user openvpn group openvpn
随后呢又在 OpenVPN 的日志里找到了这一行:
failed to find GID for group openvpn
这是导致 OpenVPN 无法启动的主要原因。服务器配置文件中指定了 OpenVPN 应运行的用户组(如
group openvpn
),但系统中不存在名为openvpn
的用户组,或其 GID(组 ID)无法被找到。怎么解决?
检查是否存在
openvpn
组:getent group openvpn
如果没有输出,说明组不存在,需要创建
sudo groupadd openvpn sudo useradd -g openvpn -s /usr/sbin/nologin openvpn
完成后重启 OpenVPN
有人可能不知道 OpenVPN 的日志是放在哪的......这里做一下提示:
/var/log/openvpn.log
。如果你在配置文件中手动指定了日志文件保存位置,那么请按照你设置的路径去寻找日志文件 -
Options error(选项错误)
在使用
systemctl start openvpn@server
时,终端报错:root@iZ2vc5dobammin8x5yzvdgZ:/etc/openvpn# systemctl start openvpn@server Job for openvpn@server.service failed because the control process exited with error code. See "systemctl status openvpn@server.service" and "journalctl -xeu openvpn@server.service" for details.
随后使用
journalctl -xeu openvpn@server.service
Jan 20 23:56:14 iZ2vc5dobammin8x5yzvdgZ ovpn-server[13264]: Warning: Error redirecting stdout/stderr to --log file: /etc/openvpn/log/openvpn.log: No such file or directory Jan 20 23:56:14 iZ2vc5dobammin8x5yzvdgZ ovpn-server[13264]: WARNING: --topology net30 support for server configs with IPv4 pools will be removed in a future release. Please mig> Jan 20 23:56:14 iZ2vc5dobammin8x5yzvdgZ ovpn-server[13264]: DEPRECATED OPTION: --cipher set to 'AES-256-CBC' but missing in --data-ciphers (AES-256-GCM:AES-128-GCM:CHACHA20-POL> Jan 20 23:56:14 iZ2vc5dobammin8x5yzvdgZ ovpn-server[13264]: Note: '--allow-compression' is not set to 'no', disabling data channel offload. Jan 20 23:56:14 iZ2vc5dobammin8x5yzvdgZ ovpn-server[13264]: Consider using the '--compress migrate' option. Jan 20 23:56:14 iZ2vc5dobammin8x5yzvdgZ ovpn-server[13264]: Options error: --status fails with '/etc/openvpn/log/openvpn-status.log': No such file or directory (errno=2) Jan 20 23:56:14 iZ2vc5dobammin8x5yzvdgZ ovpn-server[13264]: Options error: --client-config-dir fails with '/etc/openvpn/ccd': No such file or directory (errno=2) Jan 20 23:56:14 iZ2vc5dobammin8x5yzvdgZ ovpn-server[13264]: Options error: Please correct these errors. Jan 20 23:56:14 iZ2vc5dobammin8x5yzvdgZ ovpn-server[13264]: Use --help for more information. Jan 20 23:56:14 iZ2vc5dobammin8x5yzvdgZ systemd[1]: openvpn@server.service: Main process exited, code=exited, status=1/FAILURE
OpenVPN 提示
Options error: Please correct these errors.
如果你看到了这些错误,则表示你的配置文件配置有误。请重新检查你的配置文件。此类错误一般都会在日志中提示错误所在的地方,按照日志的提示去解决即可。
示例配置文件
如果你不太会写配置文件,那么这里我将会提供一个配置文件。配置文件内容仅供参考,请不要直接全部照搬。否则因此造成的损失作者概不承担
# 定义OpenVPN监听的端口号
port 1194
# 使用的协议,这里设置为UDP(相比TCP,延迟更低,更适合VPN)
proto udp
# 指定VPN设备类型为TUN(用于路由模式)
# 另一种类型是TAP(用于桥接模式)
dev tun
# 指定CA证书路径
# 指定服务器端的证书路径
# 指定服务器端的私钥路径
# 指定服务器端的私钥路径
# 指定Diffie-Hellman参数文件路径
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/server.crt
key /etc/openvpn/server/server.key
dh /etc/openvpn/server/dh.pem
# 定义VPN分配的IP地址池及其子网掩码
server 10.8.0.0 255.255.255.0
# 推送路由信息到客户端,通知客户端通过VPN访问指定的子网
push "route 10.8.0.0 255.255.255.0"
# 允许客户端之间直接通信,而无需通过服务器转发
client-to-client
# 设置VPN拓扑结构为“子网模式”,支持更精确的子网划分
topology subnet
# 定义客户端的配置文件目录,支持为特定客户端设置静态IP等
client-config-dir /etc/openvpn/ccd
# 定期发送心跳包以保持连接的活跃状态
# 格式为“间隔秒数 最大等待时间”
keepalive 10 120
# 定义可用的数据加密算法,按优先级排序
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
# 使用压缩(stub-v2为推荐模式,兼顾性能与安全)
compress stub-v2
# 设置最大连接的客户端数量,防止超载
max-clients 2048
# 指定运行OpenVPN的用户身份,降低权限,增加安全性
# 指定运行OpenVPN的用户组身份,进一步限制权限
user openvpn
group openvpn
# 启用额外的TLS验证文件路径
tls-auth /etc/openvpn/server/ta.key
# 指定状态日志文件路径,记录VPN连接状态
status /etc/openvpn/log/openvpn-status.log
# 指定普通日志的路径,日志会被追加到文件末尾
log-append /etc/openvpn/log/openvpn.log
# 保持VPN隧道设备持久化,避免频繁重新初始化
# 保持密钥持久化,避免频繁重新加载密钥
persist-tun
persist-key
# 设置日志详细程度,范围为0-11,数字越高信息越详细
verb 5
# 设定同一类型的重复日志信息最多显示20次,减少冗余日志
mute 20
这里也做一些简要的解释
选项解释
-
client-to-client
该选项是默认不启用的。当启用了
client-to-client
选项后,OpenVPN服务器会将来自一个客户端的数据包转发给其他客户端,这使得所有连接到该OpenVPN服务器的客户端可以在虚拟网络内直接相互通信,就像它们在一个局域网中一样 -
client-config-dir
简称CCD
。是一个非常有用的选项,它允许为每个客户端指定自定义配置。通过使用client-config-dir
,你可以为每个连接到服务器的客户端提供特定的IP地址、路由、权限等配置,而无需修改主服务器配置文件假如你现在要为一个 OpenVPN 客户端指定一个固定的 IP 地址,那么就需要在
CCD
(对应以上配置文件client-config-dir /etc/openvpn/ccd
)这个目录里创建一个文件,命名为当时为客户端生成密钥和 CSR(请参照步骤4.1)时设置的通用名称,这里就以server_1
来举例:cd /etc/openvpn/ccd touch server_1
接下来编辑配置文件,并往此文件内写入内容
vim server_1
# 假如你要给通用名称为server_1的客户端设置固定 IP ifconfig-push 10.8.0.10 255.255.255.0
同样的,进入
vim
编辑器页面后,按下i
来启用插入模式(左下角显示-- INSERT --
表示启用成功,如果你的系统使用了中文语言包,那么将会显示为-- 插入 --
)。完成对配置文件的编辑后,按下:
进入vim
编辑器的命令行模式,随后输入wq
来对配置文件进行一个保存,并退出编辑器。此时你会回到终端命令行页面完成后,让
server_1
这个客户端来连接到 OpenVPN 服务器,此时你会发现,客户端被分配的 IP 已经被分配为了10.8.0.10
(对应的CCD
内的配置文件项ifconfig-push 10.8.0.10 255.255.255.0
)
客户端配置
步骤 (Linux)
客户端演示环境
Ubuntu 24.04.1 LTS x86_64
OpenVPN 2.6.12 x86_64-pc-linux-gnu
-
安装所需软件包
更新系统并安装OpenVPN
sudo apt update && sudo apt upgrade -y sudo apt install openvpn
-
准备所需文件
在上文生成以及签署证书时,就已经签署了客户端的证书
客户端所需证书有以下几个:
CA 根证书(
ca.crt
)- 用于验证服务器的可信性。
- 文件位置:
pki/ca.crt
客户端证书(
server_client1.crt
)- 用于标识客户端的身份。
- 文件位置:
pki/issued/<client_name>.crt
(如pki/issued/server_client1.crt
)
客户端私钥(
server_client1.key
)- 用于客户端的加密通信。
- 文件位置:
pki/private/<client_name>.key
(如pki/private/server_client1.key
)
TLS 密钥(可选,
ta.key
)-
如果服务器使用了
tls-auth
或tls-crypt
,需要此文件进行额外的握手验证。 -
文件位置:通常是由以下命令生成的:
openvpn --genkey --secret ta.key
将这些文件都复制到 OpenVPN 的客户端目录里(如果客户端在另外一台服务器上,那么可能需要将这些密钥以及证书下载下来,然后放在 OpenVPN 客户端的证书目录里)
这里提供的示例是服务端和客户端在同一台服务器的情况。实际使用中一般不会这么用(因为这是示例)
-
创建客户端目录
mkdir -p /etc/openvpn/client
-
复制配置文件模板
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/
-
复制所需的密钥以及证书
sudo cp /opt/easy-rsa/pki/ca.crt /etc/openvpn/client/ sudo cp /opt/easy-rsa/pki/issued/server_client1.crt /etc/openvpn/client/ sudo cp /opt/easy-rsa/pki/private/server_client1.key /etc/openvpn/client/
如果在 OpenVPN 服务端配置了
tls-auth
或tls-crypt
,那么也需要将TLS 密钥文件(如ta.key
)复制到目标目录。如果没有,请忽略此步骤sudo cp /opt/easy-rsa/ta.key /etc/openvpn/client/
-
配置客户端配置文件
创建配置文件
touch client.conf
接下来编辑配置文件
vim client.conf
同样的,进入
vim
编辑器页面后,按下i
来启用插入模式(左下角显示-- INSERT --
表示启用成功,如果你的系统使用了中文语言包,那么将会显示为-- 插入 --
)。完成对配置文件的编辑后,按下:
进入vim
编辑器的命令行模式,随后输入wq
来对配置文件进行一个保存,并退出编辑器。此时你会回到终端命令行页面为了方便理解其中每一个配置项的意思,这里提供一份根据示例配置文件来对照翻译的客户端配置文件(请注意,其中配置大部分的内容是由AI翻译,这里给出配置文件的翻译仅仅只是为了方便理解其中选项的含义,并不代表本笔记作者对其中已翻译内容的认可。另外请不要直接复制这篇翻译的内容直接放到您的配置文件中,以免出现意外情况。)
另外,如果你不会写配置文件,那么请你参考下文的示例配置文件
############################################## # Sample client-side OpenVPN 2.6 config file # # for connecting to multi-client server. # # # # This configuration can be used by multiple # # clients, however each client should have # # its own cert and key files. # # # # On Windows, you might want to rename this # # file so it has a .ovpn extension # ############################################## # 指定我们是客户端,并且我们将从服务器 # 拉取某些配置文件指令。 client # 使用与服务器端相同的设置。 # 在大多数系统上,除非您部分或完全禁用 # TUN/TAP接口的防火墙,否则VPN将无法正常工作。 ;dev tap dev tun # Windows需要来自网络连接面板的TAP-Win32适配器名称 # 如果你有多个适配器。在XP SP2上, # 你可能需要禁用TAP适配器的防火墙。 ;dev-node MyTap # 我们是连接到TCP还是 # UDP服务器?使用与 # 服务器相同的设置。 ;proto tcp proto udp # 服务器的主机名/IP和端口。 # 你可以有多个远程条目 # 以在服务器之间进行负载均衡。 remote my-server-1 1194 ;remote my-server-2 1194 # 从远程列表中选择一个随机主机以进行负载均衡。否则 # 按指定的顺序尝试主机。 ;remote-random # 持续不断尝试解析OpenVPN服务器的主机名。对于并非永久 # 连接到互联网的设备(例如笔记本电脑)非常有用。 resolv-retry infinite # 大多数客户端不需要绑定到 # 特定的本地端口号码。 nobind # 初始化后降低权限(仅限非Windows) ;user openvpn ;group openvpn # 尝试在重启后保留一些状态。 persist-key persist-tun # 如果您是通过HTTP代理连接到实际的OpenVPN服务器, # 请在此处填写代理服务器/IP和端口号。如果您需要代理 # 服务器认证,请参阅手册页面。 ;http-proxy-retry # 在连接失败时重试 ;http-proxy [proxy server] [proxy port #] # 无线网络经常产生大量重复的数据包。设置此标志以 # 静默重复数据包警告。 ;mute-replay-warnings # SSL/TLS 参数。 # 请参阅服务器配置文件以获取更多 # 描述。最好为每个客户端使用 # 单独的 .crt/.key 文件对。 # 所有客户端可以使用单个 ca 文件。 # 这里假设所有的证书、密钥文件都是放在/etc/openvpn/client里的 # 请根据实际情况更改目录 ca /etc/openvpn/client/ca.crt cert /etc/openvpn/client/client.crt key /etc/openvpn/client/client.key # 通过检查证书是否设置了正确的密钥用法来验证服务器证书。 # 这是一个重要的预防措施,以防止这里讨论的潜在攻击: # http://openvpn.net/howto.html#mitm # # 要使用此功能,您需要生成服务器证书,并将 keyUsage 设置为 # 数字签名, 密钥加密 # 并将 extendedKeyUsage 设置为 # 服务器身份验证 # EasyRSA 可以为您完成此操作。 remote-cert-tls server # 允许连接到非常旧的 OpenVPN 版本 # 不支持 AEAD(OpenVPN 2.3.x 或更早版本) # 这会添加 AES-256-CBC 作为回退加密算法 # 并保留现代加密算法。 ;data-ciphers AES-256-GCM:AES-128-GCM:?CHACHA20-POLY1305:AES-256-CBC # 如果服务器上使用了tls-auth密钥 # 那么每个客户端也必须拥有该密钥。 # 这里假设所有的密钥和证书都放置在/etc/openvpn/client里的 # 请根据实际情况来 ;tls-auth ta.key 1 # 设置日志文件的详细程度。 verb 3 # 禁用重复消息 ;mute 20
请注意:其中某些项需要根据 OpenVPN 服务器的配置文件来编写
-
启动客户端
配置文件编写完成后使用以下命令来启动 OpenVPN 客户端,来连接服务器
systemctl start openvpn@client
如果你的 OpenVPN 服务器设置的网段为
10.8.0.0
,那么不出意外的话,你就可以使用10.8.0.1
这个地址来连接服务器了测试客户端与服务器的连接:
ping 10.8.0.1
PING 10.8.0.1 (10.8.0.1) 56(84) bytes of data. 64 bytes from 10.8.0.1: icmp_seq=1 ttl=64 time=1.72 ms 64 bytes from 10.8.0.1: icmp_seq=2 ttl=64 time=1.44 ms ^C --- 10.8.0.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 1.437/1.579/1.721/0.142 ms
完成!!
示例配置文件
如果你不太会写配置文件,那么这里我将会提供一个配置文件。配置文件内容仅供参考,请不要直接全部照搬。否则因此造成的损失作者概不承担
# 指定我们是客户端
client
# 使用与服务器端相同的设置。
;dev tap
dev tun
# 指定UDP协议
proto udp
# 服务器的主机名/IP和端口。
# 你可以有多个远程条目以在服务器之间进行负载均衡。
remote your-server-ip 1194
;remote your-server-2 1194
# 大多数客户端不需要绑定到
# 特定的本地端口号码。
nobind
# 尝试在重启后保留一些状态。
persist-key
persist-tun
# SSL/TLS 参数
# 请参阅服务器配置文件以获取更多
# 描述。最好为每个客户端使用
# 单独的 .crt/.key 文件对
# 所有客户端可以使用单个 ca 文件
ca ./client/ca.crt
cert ./client/server_client1.crt
key ./client/server_client1.key
# 通过检查证书是否设置了正确的密钥用法来验证服务器证书
# 这是一个重要的预防措施,以防止这里讨论的潜在攻击:
# http://openvpn.net/howto.html#mitm
#
# 要使用此功能,您需要生成服务器证书,并将 keyUsage 设置为
# 数字签名, 密钥加密
# 并将 extendedKeyUsage 设置为
# 服务器身份验证
# EasyRSA 可以为您完成此操作
remote-cert-tls server
# 允许连接到非常旧的 OpenVPN 版本
# 不支持 AEAD(OpenVPN 2.3.x 或更早版本)
# 这会添加 AES-256-CBC 作为回退加密算法
# 并保留现代加密算法
data-ciphers AES-256-GCM:AES-128-GCM:?CHACHA20-POLY1305:AES-256-CBC
# 如果服务器上使用了tls-auth密钥
# 那么每个客户端也必须拥有该密钥
tls-auth ./client/ta.key
# 日志文件详细程度
verb 3