ActiveMQ-带有Python STOMP客户端的STOMP + SSL [英] ActiveMQ - STOMP+SSL with Python STOMP client

查看:269
本文介绍了ActiveMQ-带有Python STOMP客户端的STOMP + SSL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任何人都可以向我解释如何将SSL添加到我正在使用的Python STOMP客户端中。
我在ActiveMQ配置文件中添加了stomp + ssl传输连接器,我的基本Python STOMP客户端如下:

Can anyone explain me how to add SSL to the Python STOMP client I'm using. I added the stomp+ssl transport connector in the ActiveMQ configuration file and my basic Python STOMP client is below:

import time
import sys
import stomp
class MyListener(stomp.ConnectionListener):
    def on_error(self, headers, message):
        print('received an error "%s"' % message)
    def on_message(self, headers, message):
        print('received a message "%s"' % message)
conn = stomp.Connection()
conn.set_listener('', MyListener())
conn.start()
conn.connect('admin', 'password', wait=True)
conn.subscribe(destination='/queue/test', id=1, ack='auto')
conn.send(body=' '.join(sys.argv[1:]), destination='/queue/test')
time.sleep(2)
conn.disconnect()






我创建了 http://activemq.apache.org/how-do-i-use- ssl.html 文档并将其添加到代理中的 SSL_OPTS 环境变量中,但是我无法找到如何使用密钥存储区初始化Python STOMP客户端的方法和信托商店。我应该使用 stomp.Connection()方法中给出的SSL参数,如果可以的话,该怎么做?


I created the key store and trust store given in the http://activemq.apache.org/how-do-i-use-ssl.html docs and added them to the SSL_OPTS environment variable in the broker but I'm unable to find how to initialize the Python STOMP client with the key store and trust store. Should I use the SSL paraments given in the stomp.Connection() method, and if yes how to do so?

有人可以解释一下是否还有其他方法可以通过STOMP添加SSL吗?

Can anyone please explain if there is any other way to add SSL over STOMP?

推荐答案

Python STOMP客户端(自4.1.20版开始)使用 SSLContext 来处理其密钥对/证书,因此没有理由为客户端生成Java KeyStore。

The Python STOMP client (as of version 4.1.20) uses an SSLContext to process its key pair/certificate, so there is no reason to produce a Java KeyStore for the client.

考虑到这一点,让我们完成设置ApacheMQ以支持SSL封装的STOMP连接的整个过程。以下过程已在ApacheMQ 5.15.4上进行了测试。我们通过在代理和客户端之间手动移动自签名证书来显式地建立双向信任。使用证书颁发机构也是可以的,但是如何做是一个不同的问题。

With this in mind, let us go through the entire process of setting up ApacheMQ to support SSL-wrapped STOMP connections. The process below has been tested on ApacheMQ 5.15.4. We explicitly set up two-way trust by manually moving self-signed certificates between the broker and client; using a certificate authority is also possible but how to do so is a different question.

如上所述,在Python方面,KeyStore几乎没有用,并且由于 SSLContext 期望使用PEM编码的证书,我们不妨创建密钥对和证书手动操作(即使用 openssl )。首先,在客户端计算机上,让我们创建一个4096位RSA密钥:

As mentioned above, on the Python side of things, a KeyStore will have little use, and since SSLContext expects PEM encoded certificates, we might as well create the key pair and certificate by hand (that is, using openssl). First, on the client machine, let us create a 4096-bit RSA key:

openssl genrsa -out client.key 4096

使用此功能,将公钥部分转换为证书,并用密钥本身进行签名;因为我们将手动将证书移至代理,所以自签名证书不是问题:

Using this, turn the public key part into a certificate and sign it with the key itself; since we will be manually moving the certificate to the broker, self-signing the certificate is not an issue:

openssl req -new -out client.csr -key client.key
openssl x509 -req -days 365 -in client.csr -signkey client.key -out client.pem
rm client.csr

STOMP客户端将同时需要签名证书 client.pem ,和私钥 client.key ,而经纪人只需要证书。

The STOMP client will need both the signed certificate, client.pem, and the private key, client.key, while the broker will only need the certificate.

在代理上,我们可以遵循Apache指南的第一部分,并使用Java keytool 创建一个带有服务器密钥的密钥库:

On the broker, we can follow the first part of the Apache guide and use the Java keytool to create a KeyStore with a key for the server:

keytool -genkeypair -alias broker -keyalg RSA -keysize 4096 -keystore broker.ks

在提示输入名字和姓氏时,提供服务器的主机名,在我们的示例中只需简单地成为 localhost ;如果代理和客户端在不同的服务器上运行,请确保将其设置为Python客户端最终用来识别代理的内容:

When prompted for "first and last name", provide the hostname of the server, which in our example we will take simply to be localhost; if the broker and client are running on different servers, make sure that this is set to whatever the Python client will end up using to identify the broker:

What is your first and last name?
  [Unknown]:  localhost

所有其他输入值都可以保留为未知。

All other input values can be left as "Unknown".

最终,我们只希望允许具有我们已知证书的客户端与代理建立连接,因此在此时复制上面生成给客户端的c> client.pem 并通过

At the end of the day, we will only want to allow connections to the broker from clients with certificates that we know, so at this point copy the client.pem generated above to the broker and add it to a trust store through

keytool -import -alias client -keystore broker.ts -file client.pem

如果经纪人允许

默认情况下,全部通过STOMP的连接(实际上是所有连接)都是纯文本连接,为了启用基于SSL的STOMP连接,请将以下< transportConnector /> 添加到 conf / apachemq.xml

By default, all connections through STOMP (and indeed all connections) are plaintext ones, and in order to enable STOMP connections over SSL, add the following <transportConnector /> to conf/apachemq.xml:

<transportConnectors>
    <transportConnector name="stomp+ssl" uri="stomp+nio+ssl://0.0.0.0:61613?transport.enabledProtocols=TLSv1.2&amp;needClientAuth=true" />
</transportConnectors>

请确保删除任何现有的纯文本连接器,例如默认的STOMP连接器,否则客户端将能够只需使用它们并绕过SSL要求即可。还要注意, needClientAuth = true 是强制客户端证书验证的原因。

Make sure to remove any existing plaintext connectors such as the default STOMP connector as otherwise clients will be able to simply use those and bypass the SSL requirement. Note also that needClientAuth=true is what forces client certificate validation; without this, clients are able to connect without providing a trusted certificate.

要配置ApacheMQ以使用上面定义的密钥和信任存储,请定义环境变量<$ c $。 c> ACTIVEMQ_SSL_OPTS 通过(在Unix上)

To configure ApacheMQ to use the key and trust stores defined above, define the environment variable ACTIVEMQ_SSL_OPTS through (on Unix)

export ACTIVEMQ_SSL_OPTS = -Djavax.net.ssl.keyStore=/path/to/broker.ks -Djavax.net.ssl.trustStore=/path/to/broker.ts -Djavax.net.ssl.keyStorePassword=passwordForBrokerKs -Djavax.net.ssl.trustStorePassword=passwordForBrokerTs

或(在Windows上)

or (on Windows)

set ACTIVEMQ_SSL_OPTS=-Djavax.net.ssl.keyStore=C:\path\to\broker.ks -Djavax.net.ssl.trustStore=C:\path\to\broker.ts -Djavax.net.ssl.keyStorePassword=passwordForBrokerKs -Djavax.net.ssl.trustStorePassword=passwordForBrokerTs

这里,这两个密码是在上一步中运行 keytool 之后选择的密码。如果不需要客户端证书验证,只需省略 trustStore trustStorePassword 的配置。

Here, the two passwords are those chosen after running keytool in the previous step. If client certificate validation is not desired, simply leave out the configuration of trustStore and trustStorePassword.

有了这个,ActiveMQ可以照常通过 bin / activemq start 启动。为了确保SSL配置符合期望,请在启动服务器时注意输出的 JVM args 部分。

With this, ActiveMQ can be started as usual through bin/activemq start. To make sure that the SSL configuration matches expectation, pay attention to the JVM args part of the output printed when starting the server.

通过正确设置代理,我们也可以配置客户端。在这里,我们提供 stomp.Connection.set_ssl ,其中包含在第一步中创建的密钥和证书的引用。假设ActiveMQ服务器在localhost:61613上运行,您的测试脚本将变成

With the broker properly set up, we can configure the client as well. Here, we provide stomp.Connection.set_ssl with references to the key and certificate created in the first step. Assuming that the ActiveMQ server is running on localhost:61613, your test script simply becomes

import time
import sys
import stomp

class MyListener(stomp.ConnectionListener):
    def on_error(self, headers, message):
        print('received an error "%s"' % message)
    def on_message(self, headers, message):
        print('received a message "%s"' % message)

host = 'localhost'
port = 61613
conn = stomp.Connection([(host, port)])
conn.set_ssl(for_hosts=[(host, port)], key_file='/path/to/client.key', cert_file='/path/to/client.pem')
conn.set_listener('', MyListener())
conn.start()
conn.connect('admin', 'password', wait=True)
conn.subscribe(destination='/queue/test', id=1, ack='auto')
conn.send(body='test message', destination='/queue/test')
time.sleep(2)
conn.disconnect()

确保ApacheMQ确实在验证c有效证书,我们可以重复步骤1并创建一个新对, client2.key / client2.pem 说,然后用它代替。这样做将导致ApacheMQ打印以下非明智的错误消息:

To make sure that ApacheMQ is indeed validating the client certificate, we could repeat step 1 and create a new pair, client2.key/client2.pem say, and use that instead. Doing so should result in the following non-sensical error message being printed by ApacheMQ:

ERROR | Could not accept connection from null : {}
java.io.IOException: javax.net.ssl.SSLHandshakeException: General SSLEngine problem



验证经纪人证书



现在,细心的读者会注意到我们从未真正将经纪人证书移交给客户,但是事情似乎不管如何。事实证明, stomp.py 的默认行为是完全不执行证书验证,从而允许(活动的)攻击者进行MITM

Validating the broker certificate

Now, the attentive reader will have noticed that we never actually moved the broker certificate to the client, and yet things seem to work regardless. As it turns out, the default behavior of stomp.py is to perform no certificate validation at all, allowing an (active) attacker to MITM the connection.

在滚动自签名证书时,解决此问题所需要做的就是向Python客户端提供实际的代理证书。在代理上,通过

As we are rolling self-signed certificates, all we need to do to fix this situation is to provide the actual broker certificate to the Python client. On the broker, export the certificate through

keytool -exportcert -rfc -alias broker -keystore broker.ks -file broker.pem

并将 broker.pem 移至Python客户。现在,在上面的测试脚本中,通过将SSL配置替换为

and move broker.pem to the Python client. Now, in the test script above, include the certificate by replacing the SSL configuration with

conn.set_ssl(for_hosts=[(host, port)], key_file='/path/to/client.key', cert_file='/path/to/client.pem', ca_certs='/path/to/broker.pem')

如上所述,我们可以通过重复经纪人证书生成过程以创建<$ c来测试这确实在执行正确的验证$ c> broker2.pem ,在测试脚本中使用它,并注意,它将失败并

As above, we can test that this is indeed performing the proper validation by repeating the broker certificate generation process to create a broker2.pem, use that in the test script, and note that it will fail with an

ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:833)

这篇关于ActiveMQ-带有Python STOMP客户端的STOMP + SSL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆