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
注意:证书颁发机构部分所示,也可以通过在 /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 循环)中替换其他名称。 至少,需要为服务器和至少 1 个客户端生成密钥。 显示了通用词语“服务器”和“客户端”,但实际上,这些可以是任何词语,例如容器的主机名或预期用户的名称。 同样,如果需要 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

参见