java Rabbitmq ssl 安全连接详细流程(附图)

Rabbitmq ssl 安全连接流程

  • 1 生成证书
    • 2 配置服务端
    • 3 编辑java客户端

1 生成证书

git clone https://github.com/michaelklishin/tls-gen tls-gen

执行生成命令
cd tls-gen/basic
执行make命令(如提示make命令不存在,请安装python3,同时请确保已存在openssl,可通过openssl命令,如进入命令行,则表示存在,123456为后续加载服务端证书和客户端证书的密码)
make PASSWORD=123456
java Rabbitmq ssl 安全连接详细流程(附图)_第1张图片
执行命令后出现如图的四个文件夹
执行make verify命令,出现ok则表明客户端证书与服务端证书匹配

cd result
在result目录下可看到
java Rabbitmq ssl 安全连接详细流程(附图)_第2张图片
使用ca_certificate.pem,server_certificate.pem,server_key.pem,client_key.p12这四个文件。rabbitmq服务端使用ca_certificate.pem,server_certificate.pem,server_key.pem这三个证书,
客户端(java)使用server_certificate.pem生成的truststore文件和client_key.p12这两个证书

证书默认有效期为5年,可修改有效期,tls-gen的basic目录下打开openssl.cnf文件
java Rabbitmq ssl 安全连接详细流程(附图)_第3张图片
修改default_days可修改有效期,再重新执行上述命令,重新生成证书。

生成java客户端truststore
keytool -import -alias server1 -file /path/to/server_certificate.pem -keystore /path/to/rabbitstore
keytool命令是jdk自带的命令,如没有该命令,请安装jdk1.8
server1为信任库中该证书的名字,需要改为自己想要的名称,名称可任意
/path/to/server_certificate.pem 为当前server_certificate.pem证书所在的位置,
/path/to/rabbitstore 最后生成truststore的位置和名称,名称为rabbitstore

2 配置服务端

ca_certificate.pem,server_certificate.pem,server_key.pem,将这三个证书转移到rabbitmq/ssl目录下

编辑配置文件(老版)
[
{rabbit, [
{tcp_listeners, [5672]},
{ssl_listeners, [5671]},
{ssl_options, [{cacertfile,"/etc/rabbitmq/ssl/ca_certificate.pem"},
{certfile, “/etc/rabbitmq/ssl/server_certificate.pem”},
{keyfile, “/etc/rabbitmq/ssl/server_key.pem”},
{verify,verify_peer},
{fail_if_no_peer_cert, true},
{password, “123456”}
]}
]}
].
注意:最后有一个点

编辑配置文件(新版)
listeners.tcp.default = 5672
#默认用户的密码
default_pass = 123456
#默认账号为admin
default_user = admin
#ssl登陆的关键配置,必须打开5671端口,后续客户端要连接5671端口
listeners.ssl.default = 5671
#三个rabbitmq服务端 证书,此处是容器中的路径,不要修改,对应的是宿主机上的/etc/rabbitmq/ssl目录,只要将这三个证书放到宿主机的/etc/rabbitmq/ssl目录下,则此处就可以加载到
ssl_options.cacertfile = /etc/rabbitmq/ssl/ca_certificate.pem
ssl_options.certfile = /etc/rabbitmq/ssl/server_certificate.pem
ssl_options.keyfile = /etc/rabbitmq/ssl/server_key.pem
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true
#make命令执行时的密码
ssl_options.password = 123456
ssl_options.versions.1 = tlsv1.2
ssl_options.versions.2 = tlsv1.1

重启rabbitmq服务,使用15672端口,登录控制台,查看
java Rabbitmq ssl 安全连接详细流程(附图)_第4张图片
显示监听5671端口,则启动成功

3 编辑java客户端

引入pom依赖

<dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.7.0</version>
        </dependency>
		ConnectionFactory factory = new ConnectionFactory();
		//设置ip,根据实际情况进行设置
        factory.setHost("localhost");
		//端口,ssl端口为5671,不可修改
        factory.setPort(5671);
		//123456为生成证书时,执行make的时候的密码
        char[] keyPassphrase = "123456".toCharArray();
        KeyStore ks = KeyStore.getInstance("PKCS12");
		//在执行make命令后,生成的result目录下的client_key.p12文件,按实际情况填写
        ks.load(new FileInputStream("/etc/rabbitmq/ssl/client_key.p12"), keyPassphrase);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, keyPassphrase);
		//执行keytool命令时 要求输入的密码,按实际情况填写
        char[] trustPassphrase = "123456".toCharArray();
        KeyStore tks = KeyStore.getInstance("JKS");
		//执行keytool命令后生成的truststore文件,按实际情况填写
        tks.load(new FileInputStream("/etc/rabbitmq/ssl/rabbitstore"), trustPassphrase);

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

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

        factory.useSslProtocol(c);

        Connection conn = factory.newConnection();
        Channel channel = conn.createChannel();

        channel.queueDeclare("rabbitmq -test", false, true, true, null);
        channel.basicPublish("", "rabbitmq -test", null, "rabbitmq via SSL".getBytes());

        GetResponse chResponse = channel.basicGet("rabbitmq-test", false);
        if (chResponse == null)
        {
            System.out.println("No message retrieved");
        }
        else
        {
            byte[] body = chResponse.getBody();
            System.out.println("Recieved: " + new String(body));
        }

        channel.close();
        conn.close();

出现打印rabbitmq via SSL,则表明连接成功

注意:
经过测试,rabbitmq-server 3.7.4+Erlang20.2.3版本不支持ssl,erlang无法加载服务端证书,导致连接失败,故需使用此组合之后的版本
经验证,rabbitmq-server 3.7.18+Erlang22.3.4.11版本支持ssl,配置文件需要使用老版的配置文件格式

你可能感兴趣的:(java,rabbitmq,ssl)