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。