Easy-RSA
设置 OpenVPN 的第一步是创建一个 公钥基础设施 (PKI)。 概括来说,这包括:
- 一个公共主 证书颁发机构 (CA) 证书和一个私钥。
- 每个服务器单独的公共证书和私钥对。
- 每个客户端单独的公共证书和私钥对。
可以将基于密钥的身份验证理解为类似于 SSH 密钥 的工作方式,并增加了一个签名机构(CA)。 OpenVPN 依赖于双向身份验证策略,因此客户端必须验证服务器的证书,同时,服务器必须验证客户端的证书。 这是通过第三方(CA)对客户端和服务器证书的签名来实现的。 一旦建立,在身份验证完成之前,将执行进一步的检查。 有关更多详细信息,请参阅 secure-computing 的指南。
- 下面概述的过程要求用户安全地在机器之间传输私钥文件。 为了本指南的目的,展示了使用 scp,但读者也可以采用其他方法。 由于 Arch 默认拒绝 root 用户通过 ssh 登录,因此使用 scp 需要将要导出的文件的所有权转移给本指南中称为 archie 的非 root 用户。
- 避免在没有良好熵源的设备上生成密钥。 请参阅 [1]。 有时,可以使用密码学安全的伪随机数生成器。
证书颁发机构 (CA)
出于安全目的,建议 CA 机器与运行 OpenVPN 的机器分开。
在 CA 机器上,安装 easy-rsa,初始化一个新的 PKI 并生成将用于签名证书的 CA 密钥对
# cd /root # export EASYRSA=/etc/easy-rsa # easyrsa init-pki # easyrsa build-ca
从 OpenVPN 2.4 开始,还可以将椭圆曲线用于 TLS 连接(例如 tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384)。 椭圆曲线密码学提供更高的安全性,并消除了对 Diffie-Hellman 参数文件的需求。 请参阅 [2] 和 [3]。
将以下行附加到 /etc/easy-rsa/vars
/etc/easy-rsa/vars
set_var EASYRSA_DIGEST "sha512" # Default sha256 set_var EASYRSA_NS_SUPPORT "yes" # for Netscape compatibility, deprecated
对于椭圆曲线
/etc/easy-rsa/vars
set_var EASYRSA_ALGO ec set_var EASYRSA_CURVE secp521r1
或对于 扭曲爱德华曲线
/etc/easy-rsa/vars
set_var EASYRSA_ALGO ed set_var EASYRSA_CURVE ed25519
现在设置 PKI 并生成 CA 证书
# cd /root # export EASYRSA=/etc/easy-rsa # export EASYRSA_VARS_FILE=/etc/easy-rsa/vars # easyrsa init-pki # easyrsa build-ca
OpenVPN 服务器文件
一个功能完善的 OpenVPN 服务器需要以下内容:
- CA 的公共证书
- Diffie-Hellman (DH) 参数文件(当不使用带有椭圆曲线的 TLS 时,TLS 模式需要)。
- 服务器密钥对(公共证书和私钥)。
- 基于哈希的消息认证码 (HMAC) 密钥。
完成本文中概述的步骤后,用户将在服务器上生成以下文件:
/etc/openvpn/server/ca.crt
/etc/openvpn/server/dh.pem
(当不使用带有椭圆曲线的 TLS 时)/etc/openvpn/server/servername.crt
和/etc/openvpn/server/servername.key
/etc/openvpn/server/ta.key
CA 公共证书
上一步中生成的 CA 公共证书 /etc/easy-rsa/pki/ca.crt
需要复制到将运行 OpenVPN 的机器上。
在 CA 机器上
# scp /etc/easy-rsa/pki/ca.crt archie@hostname-of-openvpn-server:/tmp/ca.crt
在 OpenVPN 服务器机器上
# mv /tmp/ca.crt /etc/openvpn/server/ # chown openvpn:network /etc/openvpn/server/ca.crt
服务器证书和私钥
在 OpenVPN 服务器机器上,安装 easy-rsa 并为服务器生成密钥对
# cd /etc/easy-rsa # easyrsa init-pki # easyrsa gen-req servername nopass # cp /etc/easy-rsa/pki/private/servername.key /etc/openvpn/server/
这将创建两个文件:
/etc/easy-rsa/pki/reqs/servername.req
/etc/easy-rsa/pki/private/servername.key
Diffie-Hellman (DH) 参数文件
在 OpenVPN 服务器机器上,创建初始 dh.pem 文件
# openssl dhparam -out /etc/openvpn/server/dh.pem 2048
基于哈希的消息认证码 (HMAC) 密钥
在 OpenVPN 服务器机器上,创建 HMAC 密钥
# openvpn --genkey secret /etc/openvpn/server/ta.key # chown openvpn:network /etc/openvpn/server/ta.key
如果使用椭圆曲线,则使用以下命令生成 HMAC 密钥
# openvpn --genkey tls-auth /etc/openvpn/server/ta.key # chown openvpn:network /etc/openvpn/server/ta.key
这将用于向所有 SSL/TLS 握手数据包添加额外的 HMAC 签名。 此外,任何不具有正确 HMAC 签名的 UDP 数据包都将被立即丢弃,从而防止:
- 端口扫描。
- 针对 OpenVPN UDP 端口的 DOS 攻击。
- 来自未经授权机器的 SSL/TLS 握手启动。
- SSL/TLS 实现中任何可能的缓冲区溢出漏洞。
OpenVPN 客户端文件
客户端证书和私钥
任何机器都可以生成客户端文件,前提是安装了 easy-rsa。
如果未初始化 pki,请通过以下方式进行初始化:
# cd /etc/easy-rsa # easyrsa init-pki
/etc/easy-rsa/vars
中定义 EC 配置然后导出它,来使用椭圆曲线代替 RSA 作为客户端证书。# export EASYRSA=$(pwd) # export EASYRSA_VARS_FILE=/etc/easy-rsa/vars
否则,可以不使用环境变量,而是使用相应的选项,例如:
# easyrsa --use-algo=ec --curve=secp521r1 --digest=sha512 init-pki
生成客户端密钥和证书
# cd /etc/easy-rsa # easyrsa gen-req client1 nopass
这将创建两个文件:
/etc/easy-rsa/pki/reqs/client1.req
/etc/easy-rsa/pki/private/client1.key
可以根据需要多次重复 gen-req 集,以用于其他客户端。
签名证书并将它们传递回服务器和客户端
在 CA 上获取和签名证书
服务器和客户端证书需要由 CA 签名,然后传输回 OpenVPN 服务器/客户端。
在 OpenVPN 服务器(或用于生成证书/密钥对的机器)上
# cp /etc/easy-rsa/pki/reqs/*.req /tmp # chown archie /tmp/*.req
安全地将文件传输到 CA 机器进行签名
$ scp /tmp/*.req archie@hostname-of-CA:/tmp
在 CA 机器上,导入和签名证书请求
# cd /etc/easy-rsa # easyrsa import-req /tmp/servername.req servername # easyrsa import-req /tmp/client1.req client1 # easyrsa sign-req server servername # easyrsa sign-req client client1
这将创建以下已签名证书,这些证书可以传输回各自的机器:
/etc/easy-rsa/pki/issued/servername.crt
/etc/easy-rsa/pki/issued/client1.crt
剩余的 .req 文件可以安全删除
# rm -f /tmp/*.req
将签名证书传递回服务器和客户端
在 CA 机器上,复制已签名的证书并将它们传输到服务器/客户端
# cp /etc/easy-rsa/pki/issued/*.crt /tmp # chown archie /tmp/*.crt $ scp /tmp/*.crt archie@hostname-of-openvpn_server:/tmp
在 OpenVPN 服务器上,将证书移动到位并重新分配所有权。 对于服务器:
# mv /tmp/servername.crt /etc/openvpn/server/ # chown openvpn:network /etc/openvpn/server/servername.crt
对于客户端:
# mv /tmp/clientname.crt /etc/openvpn/client/ # chown openvpn:network /etc/openvpn/client/clientname.crt
就这样。 要生成客户端配置文件。 请参阅:OpenVPN#ovpngen。
吊销证书并提醒 OpenVPN 服务器
吊销证书
随着时间的推移,可能有必要吊销证书,从而拒绝受影响的用户访问。 此示例吊销 “client1” 证书。
在 CA 机器上
# cd /etc/easy-rsa # easyrsa revoke client1 # easyrsa gen-crl
这将生成 CRL 文件 /etc/easy-rsa/pki/crl.pem
,该文件需要传输到 OpenVPN 服务器并在那里激活。
提醒 OpenVPN 服务器
在 CA 机器上
# cp /etc/easy-rsa/pki/crl.pem /tmp # chown archie /tmp/crl.pem
在 OpenVPN 机器上,复制 crl.pem
并通知服务器读取它
# mv /tmp/crl.pem /etc/openvpn/server/ # chown openvpn:network /etc/openvpn/server/crl.pem
编辑 /etc/openvpn/server/server.conf
,取消注释 crl-verify 指令,然后重启 openvpn-server@server.service 以重新读取它
/etc/openvpn/server/server.conf
. crl-verify /etc/openvpn/server/crl.pem .
专门针对容器化 Openvpn 的简短示例
本节专门为希望在 Linux 容器 (LXC) 中运行 Openvpn 的用户准备。 以下代码旨在粘贴到 root shell 中; 标准哈希已被省略,以便于复制/粘贴操作。 建议打开两个不同的 shell 窗口,一个用于主机,一个用于容器。
在主机上
CONTAINERNAME=foo /etc/easy-rsa easyrsa init-pki && easyrsa build-ca cp /etc/easy-rsa/pki/ca.crt /var/lib/lxc/$CONTAINERNAME/rootfs/etc/openvpn/server/
在容器中
cd /etc/easy-rsa && easyrsa init-pki for i in server client; do easyrsa gen-req $i nopass; done cp /etc/easy-rsa/pki/private/server.key /etc/openvpn/server/ openssl dhparam -out /etc/openvpn/server/dh.pem 2048 openvpn --genkey secret /etc/openvpn/server/ta.key
返回主机
easyrsa import-req /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/reqs/junk.req junk easyrsa import-req /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/reqs/client.req client easyrsa sign-req client client easyrsa sign-req server server mkdir /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/issued/ mkdir /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/signed/ cp /etc/easy-rsa/pki/issued/*.crt /var/lib/lxc/$CONTAINERNAME/rootfs/etc/easy-rsa/pki/issued/
这将为客户端提供制作 OpenVPN 兼容隧道配置文件所需的文件,并为服务器提供所需的服务器密钥文件。 要生成客户端配置文件,请参阅 OpenVPN#ovpngen。