跳转至内容

Easy-RSA

来自 ArchWiki

设置 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 服务器需要以下文件:

  1. CA 的公共证书
  2. Diffie-Hellman (DH) 参数文件(在不使用椭圆曲线 TLS 时,TLS 模式需要)。
  3. 服务器密钥对(一个公共证书和一个私钥)。
  4. 基于哈希的消息认证码 (HMAC) 密钥。

完成本文档中概述的步骤后,用户将在服务器上生成以下文件:

  1. /etc/openvpn/server/ca.crt
  2. /etc/openvpn/server/dh.pem(使用椭圆曲线 TLS 时不需要)
  3. /etc/openvpn/server/servername.crt/etc/openvpn/server/servername.key
  4. /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) 参数文件

注意:如果您正在使用带有椭圆曲线的 TLS,请跳过此步骤。

在 **OpenVPN 服务器机器**上,创建初始 dh.pem 文件。

# openssl dhparam -out /etc/openvpn/server/dh.pem 2048
注意:虽然可以使用大于 2048 的值(例如 4096),但这需要更长的生成时间,并且在安全性方面的好处很小。但建议 DH 素数的长度与 RSA 密钥的长度匹配。请参阅 [4]

基于哈希的消息认证码 (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
注意:如 证书颁发机构 (CA) 部分所示,也可以通过在 /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 窗口,一个用于宿主机,一个用于容器。

  • 假定 CA 机器是宿主机,服务器机器是容器。
  • 宿主机和容器都需要安装 openvpneasy-rsa
  • 容器需要正在运行。
  • 在下面的 CONTAINERNAME 变量中定义容器的名称。

在主机上

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/
注意:可以在此代码的第二行(for 循环)中替换其他名称。至少需要为服务器和至少一个客户端生成一个密钥。此处显示了通用的 "server" 和 "client" 字词,但实际上它们可以是任何字词,例如容器的主机名或预期用户的名称。同样,如果需要超过 2 个密钥,可以在 for 循环中添加其他字词。如果这样做,请务必为后续步骤中的每个密钥添加相应的行。

在容器中

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

参见