跳至主内容
版本:4.2

使用 TLS 保护集群(节点间)和 CLI 工具通信

概述

RabbitMQ 节点接受来自客户端对等集群节点以及CLI 工具的连接。

主要的TLSTLS 故障排除指南解释了如何使用 TLS 保护客户端连接。可能希望为另外两种连接类型添加一层加密和额外的身份验证层。本指南将对此进行说明。

切换节点间和 CLI 工具通信需要配置一些运行时标志。它们为节点提供一个CA 证书包和一套证书/密钥对。CLI 工具也必须配置为使用证书/密钥对,因为启用 TLS 的节点将不接受来自 CLI 工具和对等节点的未加密连接。

本指南假设读者熟悉主要 TLS 指南中涵盖的TLS 基础知识对等验证(身份验证)。

本指南还假设您已经为每个集群节点以及 CLI 工具将使用的每个主机生成了 CA 证书包和证书/密钥对。在生产环境中,这些证书通常由运维人员或部署工具生成。对于开发和实验,可以使用 OpenSSL 和 Python 快速生成它们

本指南将引用三个文件

  • ca_certificate.pem:证书颁发机构包
  • server_certificate.pem:将由配置的节点(和/或 CLI 工具)使用的证书(公钥)
  • server_key.pem:将由配置的节点(和/或 CLI 工具)使用的私钥

在开始之前,请确保您已准备好这些文件。

基础知识

配置节点通过启用 TLS 的连接进行通信涉及几个步骤。对于支持的 Erlang 版本,有两种方法可以做到这一点。

所有支持的操作系统上的步骤都非常相似,但由于 shell 语言不同,Windows 上的细节略有不同

策略一包括以下步骤

  • 使用运行时标志 -proto_dist inet_tls 告知节点使用加密的节点间连接
  • 将用于节点的公钥和私钥合并到单个文件中
  • 使用另一个运行时标志 -ssl_dist_opt server_certfile 告知节点在哪里可以找到其证书和私钥
  • 使用其他 -ssl_dist_opt 选项告知节点任何期望的附加 TLS 设置,例如:-ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true 以启用安全重协商

策略二非常相似,但不是指定一组运行时标志,而是可以在一个类似于 RabbitMQ 的advanced.config 文件的文件中指定这些选项,并且运行时将指向该文件。因此,步骤是

  • 使用运行时标志 -proto_dist inet_tls 告知节点使用加密的节点间连接
  • 部署一个节点间 TLS 设置文件,其中包含有关证书/密钥对位置、CA 包位置、使用的 TLS 设置等信息
  • 使用另一个运行时标志 -ssl_dist_optfile 告知节点在哪里可以找到其节点间 TLS 设置文件

我们鼓励运维人员选择最适合其所选部署工具的策略。

通过这两种选项,都使用环境变量将这些选项传递给运行时。这最好使用 rabbitmq-env.conf 来完成,正如配置指南中所解释的那样。

一旦节点配置了使用 TLS 的节点间连接,CLI 工具(如 rabbitmqctlrabbitmq-diagnostics)也必须使用 TLS 与节点通信。纯 TCP 连接将失败。

部署节点间 TLS

在证书/密钥对文件和配置就绪后,就可以启动新节点了。请注意,可能需要先停止节点,然后部署文件和配置,最后启动节点。这是因为配置为使用 TLS 的 CLI 工具将无法连接到不期望 TLS 连接的 CLI 工具的节点。

为了使节点和 CLI 工具成功执行 TLS 握手和对等验证,与初始节点相同的对等验证示例、其他节点和 CLI 工具使用的证书/密钥对必须由相同的证书颁发机构签名,或者是一个在所有集群节点上都受信任的不同 CA。

这与客户端和插件 TLS 连接的对等验证工作方式没有区别。

可以为所有节点和 CLI 工具重用单个证书/密钥对。证书还可以使用通配符主题备用名称 (SAN) 或通用名称 (CN),例如 *.rabbitmq.example.local,它可以匹配集群中的每个主机名。

策略一(使用单独标志)在 Linux、macOS 和 BSD 上

合并证书和私钥

本指南中介绍的第一种策略要求将节点的公钥和私钥合并到一个文件中。我们称之为组合密钥文件。要合并它们,只需将私钥文件(下例中的 server_key.pem)附加到公钥文件(server_certificate.pem)的末尾,从新行开始。

cat server_certificate.pem server_key.pem > combined_keys.pem

这可以使用文本编辑器完成,而不仅仅是 cat 等命令行工具。

配置节点间 TLS 的单独运行时标志

假设上述部分中的组合密钥文件已准备好,接下来我们推断 Erlang TLS 库路径,并在 rabbitmq-env.conf 中导出 ERL_SSL_PATH 指向它。

# These commands ensure that `ERL_SSL_PATH` is the first line in
# /etc/rabbitmq/rabbitmq-env.conf and will preserve the existing
# contents of that file if it already exists

erl -noinput -eval 'io:format("ERL_SSL_PATH=~s~n", [filename:dirname(code:which(inet_tls_dist))])' -s init stop > /tmp/ssl-path.txt
cat /tmp/ssl-path.txt /etc/rabbitmq/rabbitmq-env.conf > /tmp/new-rabbitmq-env.conf
mv -f /tmp/new-rabbitmq-env.conf /etc/rabbitmq/rabbitmq-env.conf

这将使节点能够从该路径加载用于加密节点间通信的模块 inet_tls_dist

第二步是使用 -proto_dist inet_tls 运行时标志告知运行时使用该模块。与所有其他运行时标志一样,SERVER_ADDITIONAL_ERL_ARGS 是传递它们最方便且兼容的方式。

请注意,此处**必须**使用双引号,因为环境变量的值是多行的。

# -pa $ERL_SSL_PATH prepends the directory ERL_SSL_PATH points at to the code path
# -proto_dist inet_tls tells the runtime to encrypt inter-node communication
# -ssl_dist_opt server_certfile /path/to/combined_keys.pem tells the runtime
# where to find the combined certificate/key file
# -ssl_dist_opt server_password password required if the private key is encrypted
#
SERVER_ADDITIONAL_ERL_ARGS="-pa $ERL_SSL_PATH \
-proto_dist inet_tls \
-ssl_dist_opt server_certfile /path/to/combined_keys.pem \
-ssl_dist_opt server_password password

下一步是在前一个示例的基础上,为节点间 TLS 连接启用安全重协商。虽然这是可选的,但强烈推荐。可以使用相同的 -ssl_dist_opt 来启用更多与 TLS 相关的设置。此示例中不包含这些设置。

# -pa $ERL_SSL_PATH prepends the directory ERL_SSL_PATH points at to the code path
# -proto_dist inet_tls tells the runtime to encrypt inter-node communication
# -ssl_dist_opt server_certfile /path/to/combined_keys.pem tells the runtime
# where to find the combined certificate/key file
# -ssl_dist_opt server_password password required if the private key is encrypted
# -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true enables an additional TLS setting: secure renegotiation
SERVER_ADDITIONAL_ERL_ARGS="-pa $ERL_SSL_PATH \
-proto_dist inet_tls \
-ssl_dist_opt server_certfile /path/to/combined_keys.pem \
-ssl_dist_opt server_password password \
-ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true"

一旦节点配置了使用 TLS 的节点间连接,CLI 工具(如 rabbitmqctlrabbitmq-diagnostics)也必须使用 TLS 与节点通信。纯 TCP 连接将失败。

这与上述示例使用 SERVER_ADDITIONAL_ERL_ARGS 的方式非常相似,但这次环境变量是 RABBITMQ_CTL_ERL_ARGS。它控制 CLI 工具使用的运行时标志。

这是完整的 /etc/rabbitmq/rabbitmq-env.conf 文件

# IMPORTANT:
# the following path is system dependent (will
# change depending on the Erlang version, distribution,
# and installation method used). Please double check it before proceeding!
ERL_SSL_PATH="/usr/lib64/erlang/lib/ssl-9.4/ebin"

# -pa $ERL_SSL_PATH prepends the directory ERL_SSL_PATH points at to the code path
# -proto_dist inet_tls tells the runtime to encrypt inter-node communication
# -ssl_dist_opt server_certfile /path/to/combined_keys.pem tells the runtime
# where to find the combined certificate/key file
# -ssl_dist_opt server_password password required if the private key is encrypted
# -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true enables an additional TLS setting: secure renegotiation
SERVER_ADDITIONAL_ERL_ARGS="-pa $ERL_SSL_PATH \
-proto_dist inet_tls \
-ssl_dist_opt server_certfile /path/to/combined_keys.pem \
-ssl_dist_opt server_password password \
-ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true"

# Same settings as above but for CLI tools
RABBITMQ_CTL_ERL_ARGS="-pa $ERL_SSL_PATH \
-proto_dist inet_tls \
-ssl_dist_opt server_certfile /path/to/combined_keys.pem \
-ssl_dist_opt server_password password \
-ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true"

策略二(使用单个 TLS 选项文件)在 Linux、macOS 和 BSD 上

为节点间 TLS 使用单独的设置文件

现代 Erlang 版本支持一个运行时标志 -ssl_dist_optfile,它可以使用单个文件通过 TLS 配置节点间通信。这简化了在命令行上传递的参数。

这是使用此设置的完整 /etc/rabbitmq/rabbitmq-env.conf 文件。请注意,-ssl_dist_optfile 文件的名称不重要,但它必须存储在实际的 rabbitmq 用户可读的位置。

# NOTE: the following path is system dependent and will change between Erlang
# versions
ERL_SSL_PATH="/usr/lib64/erlang/lib/ssl-9.4/ebin"

# -pa $ERL_SSL_PATH prepends the directory ERL_SSL_PATH points at to the code path
# -proto_dist inet_tls tells the runtime to encrypt inter-node communication
# -ssl_dist_optfile tells the runtime where to find its inter-node TLS configuration file
SERVER_ADDITIONAL_ERL_ARGS="-pa $ERL_SSL_PATH
-proto_dist inet_tls
-ssl_dist_optfile /etc/rabbitmq/inter_node_tls.config"

RABBITMQ_CTL_ERL_ARGS="-pa $ERL_SSL_PATH
-proto_dist inet_tls
-ssl_dist_optfile /etc/rabbitmq/inter_node_tls.config"

下面是一个示例 /etc/rabbitmq/inter_node_tls.config 文件,它使用单独的服务器证书和私钥文件,启用对等验证并要求对等节点提供证书。

[
{server, [
{cacertfile, "/full/path/to/ca_certificate.pem"},
{certfile, "/full/path/to/server_certificate.pem"},
{keyfile, "/full/path/to/server_key.pem"},
{password, "password-if-keyfile-is-encrypted"},
{secure_renegotiate, true},
{verify, verify_peer},
{fail_if_no_peer_cert, true}
]},
{client, [
{cacertfile, "/full/path/to/ca_certificate.pem"},
{certfile, "/full/path/to/client_certificate.pem"},
{keyfile, "/full/path/to/client_key.pem"},
{password, "password-if-keyfile-is-encrypted"},
{secure_renegotiate, true},
{verify, verify_peer}
]}
].

这些选项在Erlang/OTP 文档中有进一步记录。

Windows

上述针对 Linux、macOS 和 BSD 系统的两种策略都可以在 Windows 上使用。所有基本原理都相同。

但是,Windows 上存在一些细微差别。首先,由于 Windows shell 解析规则,输出 inet_tls_dist 模块位置的命令不同。它看起来像这样

erl -noinput -eval "io:format(""ERL_SSL_PATH=~s~n"", [filename:dirname(code:which(inet_tls_dist))])" -s init stop

接下来,包含自定义环境变量的文件在 Windows 上名为 rabbitmq-env-conf.bat。此文件**必须**保存在安装 RabbitMQ 的管理员用户的 %AppData%\RabbitMQ 目录中。

这是一个使用 -ssl_dist_opfile 设置(上面介绍的策略二)的完整 rabbitmq-env-conf.bat 文件。注意使用正斜杠作为目录分隔符。

@echo off
rem NOTE: If spaces are present in any of these paths,
rem double quotes must be used.

rem NOTE: the following path is **system dependent** and will vary between Erlang versions
rem and installation paths
set SSL_PATH="C:/Program Files/erl10.0.1/lib/ssl-9.0/ebin"

rem -pa $ERL_SSL_PATH prepends the directory ERL_SSL_PATH points at to the code path
rem -proto_dist inet_tls tells the runtime to encrypt inter-node communication
rem -ssl_dist_optfile tells the runtime where to find its inter-node TLS configuration file
set SERVER_ADDITIONAL_ERL_ARGS=-pa %SSL_PATH% ^
-proto_dist inet_tls ^
-ssl_dist_optfile C:/Users/rmq_user/AppData/Roaming/RabbitMQ/inter_node_tls.config

rem Same as above but for CLI tools
set CTL_ERL_ARGS=-pa %SSL_PATH% ^
-proto_dist inet_tls ^
-ssl_dist_optfile C:/Users/rmq_user/AppData/Roaming/RabbitMQ/inter_node_tls.config

下面是一个示例 inter_node_tls.config 文件。与其他操作系统一样,如果需要,还可以设置更多TLS 选项

[
{server, [
{cacertfile, "C:/Path/To/ca_certificate.pem"},
{certfile, "C:/Path/To/server_certificate.pem"},
{keyfile, "C:/Path/To/server_key.pem"},
{password, "password-if-keyfile-is-encrypted"},
{secure_renegotiate, true},
{verify, verify_peer},
{fail_if_no_peer_cert, true}
]},
{client, [
{cacertfile, "C:/Path/To/ca_certificate.pem"},
{certfile, "C:/Path/To/client_certificate.pem"},
{keyfile, "C:/Path/To/client_key.pem"},
{password, "password-if-keyfile-is-encrypted"},
{secure_renegotiate, true},
{verify, verify_peer}
]}
].
© . This site is unofficial and not affiliated with VMware.