rabbitmq使用TLS支持SSL加密处理

本文档详细介绍了如何为RabbitMQ设置TLS加密传输,包括使用tls-gen工具生成证书,使用Java的keytool生成相应配置,修改RabbitMQ配置文件以启用TLS,并展示了一个Java客户端的TLS连接示例。主要步骤涉及证书生成、Java keystore创建、RabbitMQ配置以及客户端连接测试。
摘要由CSDN通过智能技术生成

最近在开发过程中, 有收到要求,rabbitmq 不能使用明文传输,常规想法就是TLS加密传输。看到rabbitmq 官网有提供TLS支持的说明。

Rabbitmq 加密传输由2种方式:

  1. 使用TLS加密直连
  2. 通过类似HA代理的方式从https转换成http 比如nginx, TLS_termination_proxy等都可以实现

官网也阐述了其他一些ssl支持的说明,这边就不介绍了。详细内容查阅官网

本文使用的rabbitmq 环境是,依赖docker 构建的rabbitmq 3.7.28版本的试验环境。

这边具体说一下,怎么构建TLS链接。

步骤1:使用TLS工具生成证书(开发测试环境),生产环境建议使用商业的CA机构制作的证书文件

git clone https://github.com/michaelklishin/tls-gen tls-gen
cd tls-gen/basic
# private key password
make PASSWORD=密码
make verify
make info
ls -l ./result

其中make PASSWORD=密码 这一行命名是生成证书的过程,其他几行都是校验检测,可以不执行。

make PASSWORD=rabbit
python3 profile.py regenerate --password "rabbit" \
--common-name izbp1exs0zcohfndb4w0o5z \
--client-alt-name izbp1exs0zcohfndb4w0o5z \
--server-alt-name izbp1exs0zcohfndb4w0o5z \
--days-of-validity 3650 \
--key-bits 2048
Removing /mnt/tls-gen/basic/testca
Removing /mnt/tls-gen/basic/result
Removing /mnt/tls-gen/basic/server
Removing /mnt/tls-gen/basic/client
Will generate a root CA and two certificate/key pairs (server and client)
=>	[openssl_req]
Generating a 2048 bit RSA private key
...........................................................+++
....................+++
writing new private key to '/mnt/tls-gen/basic/testca/private/cakey.pem'
-----
=>	[openssl_x509]
Will generate leaf certificate and key pair for server
Using izbp1exs0zcohfndb4w0o5z for Common Name (CN)
Using parent certificate path at /mnt/tls-gen/basic/testca/cacert.pem
Using parent key path at /mnt/tls-gen/basic/testca/private/cakey.pem
Will use RSA...
=>	[openssl_genpkey]
..........................................................+++
...........................................................+++
=>	[openssl_req]
=>	[openssl_ca]
Using configuration from /tmp/tmpaxii46i1
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'izbp1exs0zcohfndb4w0o5z'
organizationName      :ASN.1 12:'server'
localityName          :ASN.1 12:'$$$$'
Certificate is to be certified until Nov 13 15:01:00 2030 GMT (3650 days)

Write out database with 1 new entries
Data Base Updated
=>	[openssl_pkcs12]
Will generate leaf certificate and key pair for client
Using izbp1exs0zcohfndb4w0o5z for Common Name (CN)
Using parent certificate path at /mnt/tls-gen/basic/testca/cacert.pem
Using parent key path at /mnt/tls-gen/basic/testca/private/cakey.pem
Will use RSA...
=>	[openssl_genpkey]
....................+++
.......+++
=>	[openssl_req]
=>	[openssl_ca]
Using configuration from /tmp/tmpaxii46i1
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'izbp1exs0zcohfndb4w0o5z'
organizationName      :ASN.1 12:'client'
localityName          :ASN.1 12:'$$$$'
Certificate is to be certified until Nov 13 15:01:00 2030 GMT (3650 days)

Write out database with 1 new entries
Data Base Updated
=>	[openssl_pkcs12]
Done! Find generated certificates and private keys under ./result!
python3 profile.py verify
Will verify generated certificates against the CA...
Will verify client certificate against root CA
/mnt/tls-gen/basic/result/client_certificate.pem: OK
Will verify server certificate against root CA
/mnt/tls-gen/basic/result/server_certificate.pem: OK

上述命令会生成一些目录和证书文件

其中 result 目录,将CA buddle, server ,client 证书信息都汇集了一些,没有说明不同。

步骤2: 使用jdk的keytool 生成Java相关的配置信息, 中间过程,需要输入密码信息

keytool -import -alias server1   -file /mnt/rabbitmq/cert/server_certificate.pem  -keystore /mnt/rabbitmq/cert/rabbitstore

这个过程其实就是想rabbitmq 服务端的证书适配成符合Java规则的rabbitstore文件,注意这个是server端的certificate.

输出结果:

Enter keystore password:
Re-enter new password:
Owner: O=server, CN=izbp1exs0zcohfndb4w0o5z
Issuer: L=$$$$, CN=TLSGenSelfSignedtRootCA
Serial number: 1
Valid from: Sun Nov 15 21:54:44 CST 2020 until: Wed Nov 13 21:54:44 CST 2030
Certificate fingerprints:
	 MD5:  E0:84:44:70:74:27:5D:CE:09:CF:02:63:8E:65:01:1B
	 SHA1: F4:42:AF:0A:6E:B7:C9:D6:44:04:DB:E0:61:88:AD:BD:46:B4:3B:EE
	 SHA256: C0:C9:79:27:05:B9:09:7C:F0:8B:3A:FD:14:C0:21:16:B6:58:F9:12:89:11:5C:08:F1:EC:53:55:86:DA:6F:7D
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

Extensions:

#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 3B B1 04 9E D9 66 1A 5C   7A B6 F8 38 11 79 17 A2  ;....f.\z..8.y..
0010: 7C 44 6F 9C                                        .Do.
]
]

#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:false
  PathLen: undefined
]

#3: ObjectId: 2.5.29.37 Criticality=false
ExtendedKeyUsages [
  serverAuth
]

#4: ObjectId: 2.5.29.15 Criticality=false
KeyUsage [
  DigitalSignature
  Key_Encipherment
]

#5: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
  DNSName: izbp1exs0zcohfndb4w0o5z
  DNSName: izbp1exs0zcohfndb4w0o5z
  DNSName: localhost
]

#6: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 65 45 D5 3F C8 13 F1 C4   F8 DD A8 28 14 61 0E 7E  eE.?.......(.a..
0010: 19 54 AB AA                                        .T..
]
]

Trust this certificate? [no]:
Certificate was not added to keystore
[root@izbp1exs0zcohfndb4w0o5z cert]# keytool -import -alias server1   -file /mnt/rabbitmq/cert/server_certificate.pem  -keystore /mnt/rabbitmq/cert/rabbitstore
Enter keystore password:
Re-enter new password:
Owner: O=server, CN=izbp1exs0zcohfndb4w0o5z
Issuer: L=$$$$, CN=TLSGenSelfSignedtRootCA
Serial number: 1
Valid from: Sun Nov 15 21:54:44 CST 2020 until: Wed Nov 13 21:54:44 CST 2030
Certificate fingerprints:
	 MD5:  E0:84:44:70:74:27:5D:CE:09:CF:02:63:8E:65:01:1B
	 SHA1: F4:42:AF:0A:6E:B7:C9:D6:44:04:DB:E0:61:88:AD:BD:46:B4:3B:EE
	 SHA256: C0:C9:79:27:05:B9:09:7C:F0:8B:3A:FD:14:C0:21:16:B6:58:F9:12:89:11:5C:08:F1:EC:53:55:86:DA:6F:7D
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

Extensions:

#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 3B B1 04 9E D9 66 1A 5C   7A B6 F8 38 11 79 17 A2  ;....f.\z..8.y..
0010: 7C 44 6F 9C                                        .Do.
]
]

#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:false
  PathLen: undefined
]

#3: ObjectId: 2.5.29.37 Criticality=false
ExtendedKeyUsages [
  serverAuth
]

#4: ObjectId: 2.5.29.15 Criticality=false
KeyUsage [
  DigitalSignature
  Key_Encipherment
]

#5: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
  DNSName: izbp1exs0zcohfndb4w0o5z
  DNSName: izbp1exs0zcohfndb4w0o5z
  DNSName: localhost
]

#6: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 65 45 D5 3F C8 13 F1 C4   F8 DD A8 28 14 61 0E 7E  eE.?.......(.a..
0010: 19 54 AB AA                                        .T..
]
]

#####这边要求输入yes
Trust this certificate? [no]:  yes
Certificate was added to keystore

步骤3 配置rabbit MQ 配置文件

###授权方式, 其实就是再默认的基础上加一个EXTERNAL, 如果单独配置EXTERNAL, java 客户端会出现无法找不到auth_mechanisms的问题, 这个具体还不知道原因
auth_mechanisms.1 = PLAIN
auth_mechanisms.2 = AMQPLAIN
auth_mechanisms.3 = EXTERNAL

management_agent.disable_metrics_collector = true

ssl_options.client_renegotiation = false
ssl_options.secure_renegotiate = true


###禁止 明文tcp 连接
listeners.tcp = none

##管理端只允许本地连接
management.tcp.ip = 127.0.0.1
management.tcp.port = 15672
ssl_options.password=rabbit
###tls 端口
listeners.ssl.default = 5671
###tls工具,将需要的文件存放再result 目录中
ssl_options.cacertfile = /mnt/tls-gen/basic/result/ca_certificate.pem
ssl_options.certfile   = /mnt/tls-gen/basic/result/server_certificate.pem
ssl_options.keyfile    = /mnt/tls-gen/basic/result/server_key.pem


ssl_options.verify     = verify_peer
ssl_options.fail_if_no_peer_cert = true
ssl_cert_login_from = common_name

###支持TLS协议,
ssl_options.versions.1 = tlsv1
ssl_options.versions.2 = tlsv1.1
ssl_options.versions.3 = tlsv1.2

###TLS加密cipher 顺序
ssl_options.honor_cipher_order = true
ssl_options.honor_ecc_order    = true
###TLS加密cipher
ssl_options.ciphers.1=ECDHE-ECDSA-AES256-GCM-SHA384
ssl_options.ciphers.2=ECDHE-RSA-AES256-GCM-SHA384
ssl_options.ciphers.3=ECDH-ECDSA-AES256-GCM-SHA384
ssl_options.ciphers.4=ECDH-RSA-AES256-GCM-SHA384
ssl_options.ciphers.5=DHE-RSA-AES256-GCM-SHA384
ssl_options.ciphers.6=DHE-DSS-AES256-GCM-SHA384
ssl_options.ciphers.7=ECDHE-ECDSA-AES128-GCM-SHA256
ssl_options.ciphers.8=ECDHE-RSA-AES128-GCM-SHA256
ssl_options.ciphers.9=ECDH-ECDSA-AES128-GCM-SHA256
ssl_options.ciphers.10=ECDH-RSA-AES128-GCM-SHA256
ssl_options.ciphers.11=DHE-RSA-AES128-GCM-SHA256
ssl_options.ciphers.12=DHE-DSS-AES128-GCM-SHA256
ssl_options.ciphers.13=ECDHE-ECDSA-AES256-SHA384
ssl_options.ciphers.14=ECDHE-RSA-AES256-SHA384
ssl_options.ciphers.15=ECDHE-ECDSA-DES-CBC3-SHA
ssl_options.ciphers.16=ECDH-ECDSA-AES256-SHA384
ssl_options.ciphers.17=ECDH-RSA-AES256-SHA384
ssl_options.ciphers.18=DHE-DSS-AES256-SHA256
ssl_options.ciphers.19=AES256-GCM-SHA384
ssl_options.ciphers.20=AES256-SHA256
ssl_options.ciphers.21=ECDHE-ECDSA-AES128-SHA256
ssl_options.ciphers.22=ECDHE-RSA-AES128-SHA256
ssl_options.ciphers.23=ECDH-ECDSA-AES128-SHA256
ssl_options.ciphers.24=ECDH-RSA-AES128-SHA256
ssl_options.ciphers.25=DHE-DSS-AES128-SHA256
ssl_options.ciphers.26=AES128-GCM-SHA256
ssl_options.ciphers.27=AES128-SHA256
ssl_options.ciphers.28=ECDHE-ECDSA-AES256-SHA
ssl_options.ciphers.29=ECDHE-RSA-AES256-SHA
ssl_options.ciphers.30=DHE-DSS-AES256-SHA
ssl_options.ciphers.31=ECDH-ECDSA-AES256-SHA
ssl_options.ciphers.32=ECDH-RSA-AES256-SHA
ssl_options.ciphers.33=AES256-SHA
ssl_options.ciphers.34=ECDHE-ECDSA-AES128-SHA
ssl_options.ciphers.35=ECDHE-RSA-AES128-SHA
ssl_options.ciphers.36=DHE-DSS-AES128-SHA
ssl_options.ciphers.37=ECDH-ECDSA-AES128-SHA
ssl_options.ciphers.38=ECDH-RSA-AES128-SHA
ssl_options.ciphers.39=AES128-SHA

步骤4 Java 客户端连接测试

这边说明一下,官网的demo,大部分都是对的,但是会有些小问题
比如: 需要将factory.enableHostnameVerification(); 取消。

    public static void main(String[] args) throws Exception {
       // tls 执行命令中设置的密码 make PASSWORD=rabbit
        char[] passphrase = "rabbit".toCharArray();
        KeyStore ks = KeyStore.getInstance("PKCS12");
        //tls生成的result目录下的client_key.p12
        ks.load(new FileInputStream("D:\\work\\client_key.p12"), passphrase);

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, passphrase);
  		//keytools 生成过程中,设置的密码
        char[] trustPassphrase = "rabbit".toCharArray();
        KeyStore tks = KeyStore.getInstance("JKS");
        //keytools 生成的rabbitstore
        tks.load(new FileInputStream("D:\\work\\rabbitstore"), trustPassphrase);

        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(tks);

        SSLContext c = SSLContext.getInstance("TLSv1.2");
        c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("IP地址");
        factory.setPort(5671);
        factory.useSslProtocol(c);
        factory.setUsername("admin");
        factory.setPassword("admin");
//        factory.enableHostnameVerification();

        Connection conn = factory.newConnection();
        Channel channel = conn.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };
        channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
        });
    }
  

上面就是基本的rabbitmq tls 的基础支持。

Spring Boot是一个非常流行的Java Web框架,它简化了Java应用程序的开发和部署过程。 RabbitMQ是一个开源的消息代理,它支持多种协议,包括AMQP、STOMP和MQTT等。TLS协议则是一种加密传输协议,它可以保证数据在传输过程中的安全性。 在Spring Boot应用程序中使用RabbitMQ需要引入相应的依赖,可以使用Maven或Gradle来进行管理。同时,为了保证消息的安全传输,我们可以使用TLS协议对消息进行加密传输。 以下是使用Spring Boot和RabbitMQ进行消息传输并加密的简单示例: 1. 引入依赖 在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-rsa</artifactId> </dependency> ``` 2. 配置RabbitMQTLS 在application.properties文件中添加以下配置: ```properties spring.rabbitmq.host=localhost spring.rabbitmq.port=5671 spring.rabbitmq.username=user spring.rabbitmq.password=password spring.rabbitmq.ssl.enabled=true spring.rabbitmq.ssl.key-store=file:/path/to/keystore spring.rabbitmq.ssl.key-store-password=changeit spring.rabbitmq.ssl.trust-store=file:/path/to/truststore spring.rabbitmq.ssl.trust-store-password=changeit ``` 其中,key-store和trust-store分别为用于TLS加密的密钥库和信任库文件路径,需要根据实际情况进行配置。 3. 发送和接收消息 在Spring Boot应用程序中使用RabbitTemplate来发送和接收消息,示例代码如下: ```java @Service public class RabbitMQService { @Autowired private RabbitTemplate rabbitTemplate; public void send(String message) { rabbitTemplate.convertAndSend("exchange", "routingKey", message); } @RabbitListener(queues = "queue") public void receive(String message) { System.out.println("Received message: " + message); } } ``` 其中,send方法用于发送消息,receive方法用于接收消息。在这个例子中,我们将消息发送到名为exchange的交换机,使用名为routingKey的路由键进行路由,然后将消息发送到名为queue的队列中进行消费。 以上就是在Spring Boot应用程序中使用RabbitMQTLS进行消息传输的简单示例。需要注意的是,这只是一个基本的示例,实际应用中还需要进行更多的配置和处理,以确保消息传输的安全和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值