RMQ的SSL配置最佳实践

Erlang语言的安装

erlang是RabbitMQ的运行环境,为什么要强调安装erlang,如果你随便去下载erlang官网的包,可能会缺少很多依赖,如果你已经安装好了erlang,执行命令看是否和以下结果一致。

如果执行后有error,没有supported输出,请重新安装

重装erlang

在RabbitMQ官方网站有一段话,说明了ssl环境需要erlang哪些扩展包。

Erlang/OTP Requirements for TLS Support

In order to support TLS connections, RabbitMQ needs TLS and crypto-related modules to be available in the Erlang/OTP installation. The recommended Erlang/OTP version to use with TLS is the most recent supported Erlang release. Earlier versions, even if they are supported, may work for most certificates but have known limitations (see below).

The Erlang asn1, crypto, public_key, and ssl libraries (applications) must be installed and functional. On Debian and Ubuntu this is provided by the erlang-asn1, erlang-crypto, erlang-public-key, and erlang-ssl packages, respectively. The zero dependency Erlang RPM for RabbitMQ includes the above modules.

If Erlang/OTP is compiled from source, it is necessary to ensure that configure finds OpenSSL and builds the above libraries.

大概意思是安装erlang前你的系统中必须已经安装了openssl,然后erlang开启ssl需要哪些依赖包,最终他给了一个0依赖的erlang下载地址,这个erlang包他默认包含了所有ssl需要的依赖。然后他给出的erlang和RabbitMQ的版本对比,下载你需要的版本.

erlang版本参考地址

0依赖的erlang下载

rpm安装过后,将erl命令地址配置到环境变量中,如果在重装过程中遇到了文件冲突,使用如下指令。

rpm -Uivh erlang.rpm --replacefiles复制代码

erlang环境装好后,RabbitMQ安装就不再介绍,使用rpm安装就行,没有什么坑。

配置RabbitMQ的SSL端口

接下来会简述证书生成,ssl端口开放

下载SSL证书生成器

git clone https://github.com/Berico-Technologies/CMF-AMQP-Configuration.git复制代码

生成证书

cd CMF-AMQP-Configuration/ssl复制代码

配置当前目录下的openssl.cnf,基本上不需要改动,证书默认生成后的有效期是一年,如果需要延长可以修改default_days = 365.

生成证书签发机构

该脚本是会在当前目录下生成一个ca目录,里面存放着一些证书颁发机构信息,和已经签发的证书记录

sh setup_ca.sh RabbitSSL复制代码

RabbitSSL: 签发机构名称,自定义。

生成服务端公钥,和私钥

该脚本是会在当前目录下生成一个server目录,里面存放着服务端的公钥,和私钥文件。该文件生成后会在ca目录文件中有签发记录。

sh make_server_cert.sh rabbit-server rabbit复制代码

rabbit-server: 生成的密钥前缀名,自定义。

rabbit: 访问该密钥的密码,自定义。

生成客户端公钥,和私钥

该脚本是会在当前目录下生成一个client目录,里面存放着客户端的公钥,和私钥文件。该文件生成后会在ca目录文件中有签发记录。

sh create_client_cert.sh rabbit-client rabbit复制代码

rabbit-client: 生成的密钥前缀名,自定义。

rabbit: 访问该密钥的密码,自定义。

生成客户端需要的证书

不同的语言操作方式不一样,这里我们使用的是java语言,使用java的keytool工具生成,首先确保已经安装java并且在环境变量中已经配置

keytool -import -alias rabbit-server -file server/rabbit-server.cert.pem -keystore rabbitStore -storepass rabbit复制代码

用服务端的公钥生成证书,这个步骤很关键,该证书用于客户端和服务端通信。

server/rabbit-server.cert.pem: 上个步骤已经生成好的服务端公钥

如果需要删除已经生成的证书,可执行以下命令

keytool -delete -alias rabbit-server -keystore rabbitStore -storepass rabbit复制代码

证书生成结束步骤检查

如果你跟着文章一步一步做到这,说明你离成功就只差最后一步了,接下来检查我们前几个步骤的结果,经过几个步骤我们在CMF-AMQP-Configuration/ssl/目录下生成了:

ca

server

client

rabbitStore 证书

如果以上的几个目录和这个证书都存在,说明该大步骤已经完美结束。接下来进入最关键的一步了。

修改RabbitMQ的SSL配置

接下来的步骤就比较关键了,需要用到我们上面所有生成的文件,将它们配置到RabbitMQ的config文件中.

将ca,server,client,rabbitStore拷贝到/etc/rabbitmq目录下

cp -r ca server client rabbitStore /etc/rabbitmq/ssl复制代码

如果/etc/rabbitmq目录下没有rabbitmq.config,创建该文件。

vim /etc/rabbitmq/rabbitmq.config复制代码

将以下配置复制到rabbitmq.config中

%%Disable SSLv3.0 and TLSv1.0 support.[    {ssl, [{versions, ['tlsv1.2', 'tlsv1.1']}]},    {rabbit, [        {tcp_listeners, [5672]},        {ssl_listeners, [5671]},        {ssl_options, [{cacertfile,"/etc/rabbitmq/ssl/ca/cacert.pem"},            {certfile,"/etc/rabbitmq/ssl/server/rabbit-server.cert.pem"},            {keyfile,"/etc/rabbitmq/ssl/server/rabbit-server.key.pem"},            {verify, verify_peer},            {ciphers, ["ECDHE-ECDSA-AES256-GCM-SHA384","ECDHE-RSA-AES256-GCM-SHA384",                        "ECDHE-ECDSA-AES256-SHA384","ECDHE-RSA-AES256-SHA384", "ECDHE-ECDSA-DES-CBC3-SHA",                        "ECDH-ECDSA-AES256-GCM-SHA384","ECDH-RSA-AES256-GCM-SHA384","ECDH-ECDSA-AES256-SHA384",                        "ECDH-RSA-AES256-SHA384","DHE-DSS-AES256-GCM-SHA384","DHE-DSS-AES256-SHA256",                        "AES256-GCM-SHA384","AES256-SHA256","ECDHE-ECDSA-AES128-GCM-SHA256",                        "ECDHE-RSA-AES128-GCM-SHA256","ECDHE-ECDSA-AES128-SHA256","ECDHE-RSA-AES128-SHA256",                        "ECDH-ECDSA-AES128-GCM-SHA256","ECDH-RSA-AES128-GCM-SHA256","ECDH-ECDSA-AES128-SHA256",                        "ECDH-RSA-AES128-SHA256","DHE-DSS-AES128-GCM-SHA256","DHE-DSS-AES128-SHA256",                        "AES128-GCM-SHA256","AES128-SHA256","ECDHE-ECDSA-AES256-SHA",                        "ECDHE-RSA-AES256-SHA","DHE-DSS-AES256-SHA","ECDH-ECDSA-AES256-SHA",                        "ECDH-RSA-AES256-SHA","AES256-SHA","ECDHE-ECDSA-AES128-SHA",                        "ECDHE-RSA-AES128-SHA","DHE-DSS-AES128-SHA","ECDH-ECDSA-AES128-SHA",                                                "ECDH-RSA-AES128-SHA","AES128-SHA"]},            {honor_cipher_order, true},            {fail_if_no_peer_cert, true},            {versions, ['tlsv1.2', 'tlsv1.1']}        ]},        {auth_mechanisms,['PLAIN', 'AMQPLAIN', 'EXTERNAL']}    ]}].

在以上配置中我们将证书颁发机构以及服务端的公钥和私钥配置进去了。client目录和rabbitStore是给客户端使用的,我们使用5671端口作为我们ssl通信端口,5672保持不变,继续为内网tcp提供服务

重启rabbitmq服务

以下命令是参考,每个人服务安装方式不一样,总之将它重启就可以

systemctl restart rabbit-server.service

查看rabbitmq日志输出

less /var/log/rabbitmq/xxx.log

log显示成这样,代表ssl开启成功

或者访问网页查看5671是否开启ssl

如上,ssl服务已经开启.最后一步代码测试

编写Java代码测试证书授权

将前面还没有用到的client目录和rabbitStore证书拷贝的项目中,放入到resource目录下,执行以下代码做测试;

publicclassSslReceiver{publicstaticvoidmain(String[] args)throwsTimeoutException{        String classpath = SslReceiver.class.getResource("/").getPath();//证书密码char[] sslPwd ="rabbit".toCharArray();//读取client密钥,和rabbitStore证书try(InputStream sslCardStream =newFileInputStream(classpath +"keyStore/client/rabbit-client.keycert.p12");            InputStream rabbitStoreStream =newFileInputStream(classpath +"keyStore/rabbitStore")) {//加载秘钥KeyStore ks = KeyStore.getInstance("PKCS12");            ks.load(sslCardStream, sslPwd);            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");            keyManagerFactory.init(ks, sslPwd);//读取授权证书,只含有服务端的公钥KeyStore jks = KeyStore.getInstance("JKS");            jks.load(rabbitStoreStream, sslPwd);            TrustManagerFactory keyStoreManager = TrustManagerFactory.getInstance("SunX509");            keyStoreManager.init(jks);            SSLContext context = SSLContext.getInstance("TLSv1.2");            context.init(keyManagerFactory.getKeyManagers(), keyStoreManager.getTrustManagers(),null);            ConnectionFactory factory =newConnectionFactory();            factory.setUsername("rabbitTest");            factory.setPassword("123456");            factory.setHost("127.0.0.1");            factory.setPort(5671);            factory.setAutomaticRecoveryEnabled(true);//设置sslContextfactory.useSslProtocol(context);            Connection connection = factory.newConnection();            Channel channel = connection.createChannel();            channel.queueDeclare("rabbitmq-queue",false,true,true,null);//rabbitmq-queue是rabbitmq队列channel.basicPublish("","rabbitmq-queue",null,"Test,Test".getBytes());            GetResponse chResponse = channel.basicGet("rabbitmq-queue",false);if(chResponse ==null){                System.out.println("No message retrieved");            }else{byte[] body = chResponse.getBody();                System.out.println("Recieved: "+newString(body));            }            channel.close();            connection.close();        }catch(KeyStoreException | UnrecoverableKeyException | KeyManagementException                | CertificateException | NoSuchAlgorithmException | IOException e) {            log.error("SSL证书解析失败", e);        }    }}

如果收到了那条消息,到此ssl结束,如果有异常信息,请在启动jvm中传递参数-Djavax.net.debug=all,查看连接过程,在结合服务端/var/log/rabbitmq下的log一起分析!通常来讲,如果你将我的每一步复制,不可能出现问题。完结!

在此我向大家推荐一个架构学习交流群。交流学习群号:938837867 暗号:555 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容