RabbitMQ内置了对TLS的支持。
本文覆盖了RabbitMQ中与TLS相关的各种主题,重点是客户端连接:
可以为RabbitMQ支持的所有协议启用TLS,不仅仅本章重点介绍的AMQP 0-9-1,HTTP API,节点间和CLI工具也可以配置为使用TLS
对于客户端连接,有两种常见的方法:
这两种方法都有效,各有利弊。本章将重点放在第一种上面,但是部分仍然与第二个相关
为了支持TLS连接,RabbitMQ需要在Erlang/OTP安装中提供TLS和加密相关模块。与TLS一起使用的推荐Erlang/OTP版本是最新支持的Erlang版本。早期版本,即使他们支持,也可能适用于大多数证书,但有已知的限制。
如果预计使用椭圆曲线加密(ECC)密码套件,强烈建议使用最近受支持的Erlang版本。早期版本在ECC支持方面存在已知的限制。
TLS是一个庞大且复杂的主题。在介绍如何在RabbitMQ中启用TLS之前,有必要简要介绍一下本文中使用的一些概念。
TLS有两个主要的目标:加密连接并提供一种对对等方进行身份认证(验证)以防止中间人攻击的方法。两者都是使用一组称为公钥基础设施(PKI)的角色、策略和程序来完成的。
PKI基于可以加密验证的数字身份的概念。这些身份成为证书或更准确的说是证书/密钥对。每个启用TLS的服务器通常都有自己的证书/密钥对,用于计算特定连接的密钥,这将用于加密连接传输中的内容。此外,如果被询问,它可以将其证书(公钥)提供给连接的对方。客户端可能也没用自己的证书。在消息传递和RabbitMQ等工具的上下文中,客户端也很常见使用证书/密钥对,以便服务器可以验证其身份。
证书/密钥对由OpenSSL等工具生成并由称为证书办法机构(CA)的实体签名。CA颁发给用户(程序应用或其他CA)使用的证书,当证书由CA签名时,它们会形成信任链。此信任链可以包含多个CA,但最终会签署应用程序的证书/密钥对(叶证书或最终用户证书)。CA证书链同城一起分布在一个文件中,这样的文件成为CA 包。
这是具有一个根CA和一个叶(服务器或客户端)证书的最基本链实例:
一个包含中间证书的信任链如下:
有些组织签署和颁发证书/密钥对。它们中的大多数时广受新人的CA,并为其服务收取费用。
启用TLS的RabbitMQ节点必须在文件(CA包)、证书(公钥)文件和私钥文件中拥有一组它认为受信任的证书颁发机构证书。这些文件将从本地文件系统中读取,RabbitMQ节点进程的有效用户必须能够读取它们。
启用TLS的连接的两端可以选择验证连接的另一端,这样做时,他们会尝试在对等方提供的证书列表中找到受信任的证书颁发机构,当双方都执行此验证过程时,这成为双向TLS身份验证或mTLS。
本问假定用户可以访问CA和两种格式的证书/密钥对,供不同客户端库使用。这最好使用现有的工具完成
在生产环境,证书由商业CA或者内部安全团队CA生成,在这些情况下,CA捆绑文件可能包含多个证书。只要满足相同的基本文件和路径要求,这不会改变配置RabbitMQ时使用bundle文件的方式。换句话说,无论证书是自签名的还是由受信任的CA颁发的,它们的配置方式都是相同的。
本文假定用户有权访问CA证书文件包和证书/密钥对文件。证书/密钥对由RabbitMQ和客户端使用,这些客户端在启用TLS的端口上连接到服务器。
以下是生成CA和使用该CA生成两个密钥对的例子,一对用于服务器,另外一对用于客户端
git clone [email protected]/rabbitmq/tls-gen.git
cd tls-gen/basic
make PASSWORD=111111
make verify
make info
ls -l ./result
要在RabbitMQ中启用TLS支持,必须将节点配置为知道CA文件包(一个具有多个CA证书的文件)的位置、服务器证书文件和服务器密钥文件。还应启用TLS监听器以了解要侦听启用TLS的客户端连接的端口,可以配置更多与TLS相关的东西。
以下是与TLS相关的基本配置设置:
配置密钥 | 描述 |
---|---|
listeners.ssl | 用于监听TLS连接的端口列表 |
ssl_options.cacertfile | CA文件路径 |
ssl_options.certfile | 服务器证书文件路径 |
ssl_options.keyfile | 服务器密钥文件路径 |
ssl_options.verify | 是否启用对等验证 |
ssl_options.fail_if_no_peer_cert | 设置为true时,如果客户端未i额能提供证书,TLS连接将被拒绝 |
这些选项在配置文件中提供。下面时一个配置文件的示例,它将在此主键上的所有接口上的端口5671上启动一个TLS监听器:
listeners.ssl.default = 5671
ssl_options.cacertfile = /path/to/ca_certificate.pem
ssl_options.certfile = /path/to/server_certificate.pem
ssl_options.keyfile = /path/to/server_key.pem
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true
可以完全禁用常规(非TLS)监听器。只有启用了TLS的客户端才能连接到这样的节点,并且只有当它们使用正确的端口时:
# disables non-TLS listeners, only TLS-enabled clients will be able to connect
listeners.tcp = none
listeners.ssl.default = 5671
ssl_options.cacertfile = /path/to/ca_certificate.pem
ssl_options.certfile = /path/to/server_certificate.pem
ssl_options.keyfile = /path/to/server_key.pem
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true
TLS设置也可以使用经典配置格式进行配置:
[
{rabbit, [
{ssl_listeners, [5671]},
{ssl_options, [{cacertfile, "/path/to/ca_certificate.pem"},
{certfile, "/path/to/server_certificate.pem"},
{keyfile, "/path/to/server_key.pem"},
{verify, verify_peer},
{fail_if_no_peer_cert, true}]}
]}
].
RabbitMQ必须能够读取其配置的CA证书包、服务器证书和私钥。这些文件必须存在并且具有适当的权限,如果不是这种情况,节点将无法启动或无法接受启用TLS的连接
要验证节点上是否启用了TLS,请重新启动它并检查其日志文件,它应该包含一个关于启用TLS监听器的条目,如下所示:
2020-07-13 21:13:01.015 [info] <0.573.0> started TCP listener on [::]:5672
2020-07-13 21:13:01.055 [info] <0.589.0> started TLS (SSL) listener on [::]:5671
另外一种方法是使用rabbitmq-diagnostics监听器,它应该包含启用TLS的监听器的行:
rabbitmq-diagnostics listeners
#
# ... (some output omitted for brevity)
# => Interface: [::], port: 5671, protocol: amqp/ssl, purpose: AMQP 0-9-1 and AMQP 1.0 over TLS
# ...
私钥可以选择接受密码保护。要提供密码,请使用密码选项:
listeners.ssl.1 = 5671
ssl_options.cacertfile = /path/to/ca_certificate.pem
ssl_options.certfile = /path/to/server_certificate.pem
ssl_options.keyfile = /path/to/server_key.pem
ssl_options.password = t0p$3kRe7
如证书和密钥部分所述,TLS有两个主要目的:加密连接内容和提供一种方法来验证对等方是否可信来防止中间人攻击,攻击者冒充合法可信对方的一类攻击
当建立TLS连接时,客户端和服务器需要花几个步骤进行连接。第一步,当对等方选择交换它们的证书时,交换证书后,对等方可以选择尝试在其CA证书和提供的证书之间建立信任链。这用于验证对等方是它声称的身份(假设私钥没用被盗)。
该过程成为对等验证或对等校验,并遵循称为认证路径验证算法
每个对等点都提供一个证书链,该证书链以“叶”(客户端或服务器)证书开头,并至少一个证书颁发结构证书继续。。。todo。。。
每个启用TLS的工具和TLS实现,包括Erlang/OTP和RabbitMQ,都有一种将一组证书标记为可信的方法。
对此有三种常见的方法
Java安全框架中包含三个主要组件:密钥管理器、信任管理器和密钥存储
对等点使用密钥管理器来管理其证书,在TLS连接/会话期间,密钥管理器将控制向远程对等方发送哪些证书。
对等点使用信任管理器来管理远程证书,在TLS连接/会话期间,信任管理器将控制远程对等方信任哪些证书。信任管理器可用于实现任何证书链验证逻辑
密钥存储是证书存储概念的Java封装,所有的证书必须存储为特定于Java的二进制格式(JKS)或PKCS#12格式,这些格式使用KeyStore类进行管理。在下面的实例中,JKS格式用于将受信任的(服务器)证书添加到存储中,而对于客户端密钥/证书对,将使用tls-gen生成的PKCS#12密钥文件。