RabbitMQ要對外提供服務,考慮到安全性,配置SSL進行訪問,ssl端口5671,內部仍然使用5672進行訪問,兩者同時兼容。
安裝環境
- CentOS 7.5
- Docker 1.13.1
- Git 1.8.3
- jdk 1.8
- RabbitMQ鏡像,rabbitmq:management
證書
RabbitMQ也提供了獲取證書的方案,但是使用過程中出現錯誤,未來得及進行解決,在github上查找到一個項目可以生成證書,遂使用之。
安裝git
要從github上將項目克隆下來,需要有git環境,安裝步驟如下
# yum安裝git
$ yum -y install git
# 配置郵箱以及賬號
$ git config --global user.name = 'xxx'
$ git config --global user.email = 'xxx'
# 查看git配置
$ git config --list
生成證書
1.從github上克隆項目
$ git clone https://github.com/Berico-Technologies/CMF-AMQP-Configuration.git
2.下載完成后,進入CMF-AMQP-Configuration/ssl/目錄
$ cd CMF-AMQP-Configuration/ssl/
3.生成證書簽發機構
$ sh setup_ca.sh xxx
xxx為自定義的證書簽發機構名稱,該腳本會在當前目錄下生成一個ca目錄,存儲證書頒發機構的信息以及已經簽發的一些證書
執行腳本后的ca目錄如下所示
4.生成服務端公鑰和私鑰
$ sh make_server_cert.sh rabbit-server 123456
注釋:
rabbit-server:生成的密鑰前綴名,自定義
123456: 訪問該密鑰的密碼,自定義
執行該腳本后,在當前目錄生成server目錄,存儲服務端公鑰和私鑰,如下所示
5.生成客戶端公鑰和私鑰
$ sh create_client_cert.sh rabbit-client 123456
注釋:
rabbit-client:生成的密鑰前綴名,自定義。
123456: 訪問該密鑰的密碼,自定義。
執行該腳本后,在當前目錄下生成client目錄,存儲客戶端公鑰和私鑰,如下所示
6.生成客戶端需要的證書
使用java的keytool工具生成客戶端需要的證書,用以支持服務端和客戶端進行通信,生成該證書需要提前安裝配置java環境,此處默認已正確安裝java環境,不會安裝的可以參考本人博客
$ keytool -import -alias rabbit-server -file server/rabbit-server.cert.pem -keystore rabbitStore -storepass 123456
注釋:
-import 將已簽名數字證書導入密鑰庫
-alias xxx 指定導入條目的別名
-file server/rabbit-server.cert.pem 需要導入的證書
-keystore xxx 指定密鑰庫的名稱
-storepass xxx 指定密鑰庫的密碼(獲取keystore信息所需的密碼)
經過以上6個步驟,我們一共生成了3個文件夾以及1個文件,分別是server/,client/,ca/以及rabbitStore證書,只要以上幾個文件都存在,那么就表示生成證書成。
安裝RabbitMQ並配置SSL
1.拉取management版本的鏡像
$ docker pull rabbitmq:management
2.先使用以下命令啟動容器
$ docker run --restart=unless-stopped -d -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:management
3.創建文件夾
在宿主機上創建以下文件夾
$ mkdir -p /etc/rabbitmq/ssl
4.拷貝容器中的文件到/etc/rabbitmq/目錄下
$ docker cp rabbitmq:/etc/rabbitmq/conf.d /etc/rabbitmq/
$ docker cp rabbitmq:/etc/rabbitmq/enabled_plugins /etc/rabbitmq/
$ docker cp rabbitmq:/etc/rabbitmq/rabbitmq.conf /etc/rabbitmq/
5.拷貝生成的證書到/etc/rabbitmq/ssl/目錄下
在./CMF-AMQP-Configuration/ssl/目錄下執行以下命令
$ cp -r ca server client rabbitStore /etc/rabbitmq/ssl
6.編輯/etc/rabbitmq/rabbitmq.conf文件,輸入以下內容
# SSL\TLS通信的端口
listeners.ssl.default=5671
# 服務端私鑰和證書文件配置
ssl_options.cacertfile=/etc/rabbitmq/ssl/ca/cacert.pem
ssl_options.certfile=/etc/rabbitmq/ssl/server/rabbit-server.cert.pem
ssl_options.keyfile=/etc/rabbitmq/ssl/server/rabbit-server.key.pem
# 有verify_none和verify_peer兩個選項,verify_none表示完全忽略驗證證書的結果,verify_peer表示要求驗證對方證書
ssl_options.verify=verify_peer
# 若為true,服務端會向客戶端索要證書,若客戶端無證書則中止SSL握手;若為false,則客戶端沒有證書時依然可完成SSL握手
ssl_options.fail_if_no_peer_cert=true
ssl_options.versions.1=tlsv1.2
ssl_options.versions.2=tlsv1.1
ssl_options.ciphers.1 = ECDHE-ECDSA-AES256-GCM-SHA384
ssl_options.ciphers.2 = ECDHE-RSA-AES256-GCM-SHA384
ssl_options.ciphers.3 = ECDHE-ECDSA-AES256-SHA384
ssl_options.ciphers.4 = ECDHE-RSA-AES256-SHA384
ssl_options.ciphers.5 = ECDHE-ECDSA-DES-CBC3-SHA
ssl_options.ciphers.6 = ECDH-ECDSA-AES256-GCM-SHA384
ssl_options.ciphers.7 = ECDH-RSA-AES256-GCM-SHA384
ssl_options.ciphers.8 = ECDH-ECDSA-AES256-SHA384
ssl_options.ciphers.9 = ECDH-RSA-AES256-SHA384
ssl_options.ciphers.10 = DHE-DSS-AES256-GCM-SHA384
ssl_options.ciphers.11= DHE-DSS-AES256-SHA256
ssl_options.ciphers.12 = AES256-GCM-SHA384
ssl_options.ciphers.13 = AES256-SHA256
ssl_options.ciphers.14 = ECDHE-ECDSA-AES128-GCM-SHA256
ssl_options.ciphers.15 = ECDHE-RSA-AES128-GCM-SHA256
ssl_options.ciphers.16 = ECDHE-ECDSA-AES128-SHA256
ssl_options.ciphers.17 = ECDHE-RSA-AES128-SHA256
ssl_options.ciphers.18 = ECDH-ECDSA-AES128-GCM-SHA256
ssl_options.ciphers.19= ECDH-RSA-AES128-GCM-SHA256
ssl_options.ciphers.20 = ECDH-ECDSA-AES128-SHA256
ssl_options.ciphers.21 = ECDH-RSA-AES128-SHA256
ssl_options.ciphers.22 = DHE-DSS-AES128-GCM-SHA256
ssl_options.ciphers.23 = DHE-DSS-AES128-SHA256
ssl_options.ciphers.24 = AES128-GCM-SHA256
ssl_options.ciphers.25 = AES128-SHA256
ssl_options.ciphers.26 = ECDHE-ECDSA-AES256-SHA
ssl_options.ciphers.27 = ECDHE-RSA-AES256-SHA
ssl_options.ciphers.28 = DHE-DSS-AES256-SHA
ssl_options.ciphers.29 = ECDH-ECDSA-AES256-SHA
ssl_options.ciphers.30 = ECDH-RSA-AES256-SHA
ssl_options.ciphers.31= AES256-SHA
ssl_options.ciphers.32 = ECDHE-ECDSA-AES128-SHA
ssl_options.ciphers.33 = ECDHE-RSA-AES128-SHA
ssl_options.ciphers.34 = DHE-DSS-AES128-SHA
ssl_options.ciphers.35 = DHE-DSS-AES128-SHA256
ssl_options.ciphers.36 = ECDH-ECDSA-AES128-SHA
ssl_options.ciphers.37 = ECDH-RSA-AES128-SHA
ssl_options.ciphers.38 = AES128-SHA
注釋:
rabbitmq.conf文件中原有的內容可以直接刪除掉,也可以保留,不影響
也可以不使用上述的rabbitmq.conf文件,而使用rabbitmq.config文件,不過后者需要自己創建,且不可以和rabbitmq.conf共存,RabbitMQ3.7版本以后,推薦使用rabbitmq.conf,因此如果要使用rabbitmq.config,需要先創建,再寫入內容
# 創建rabbitmq.config文件
$ vim 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']}
]}
].
注釋:
rabbitmq.conf和rabbitmq.config任選其一即可,個人認為前者可讀性更好一些,但是編寫的內容相對較多一些
7.刪除前面創建的rabbitmq容器,重新創建
使用以下命令重新創建rabbitmq容器,添加5671端口映射以及/etc/rabbitmq/文件夾的掛載
$ docker run --restart=unless-stopped -d \
-p 5672:5672 -p 15672:15672 -p 5671:5671 \
-v /etc/rabbitmq/:/etc/rabbitmq/ \
--name rabbitmq \
rabbitmq:management
8.驗證5671端口
使用以下命令查看rabbitmq容器啟動時的日志
$ docker logs -f rabbitmq
看到日志中出現以下內容表示配置成功
9.創建可以遠程訪問的用戶
由於guest用戶只能本地訪問,因此需要創建一個可以遠程訪問的用戶
# 進入容器內部
$ docker exec -it rabbitmq bash
# 創建一個用戶名為admin,密碼為123456的用戶
$ rabbitmqctl add_user admin 123456
# 設置用戶權限為超級管理員
$ rabbitmqctl set_user_tags admin administrator
# 授權遠程訪問
$ rabbitmqctl set_permissions -p / admin "." "." ".*"
# 退出容器
$ exit
# 重啟rabbitmq
$ docker restart rabbitmq
10.訪問管理頁面
此時可以使用上面創建的admin用戶遠程訪問管理頁面,地址為http://ip:15672
進入之后可以通過如下方式確認ssl是否配置成功
SpringBoot集成SSL
此處只給出配置ssl的部分,springboot集成rabbitmq的方法可以參考本人博客
spring:
rabbitmq:
addresses: 192.168.216.129:5671
username: admin
password: 123456
virtual-host: /
ssl:
enabled: true
key-store: classpath:keyStore/129/rabbit-client.keycert.p12
key-store-password: 123456
trust-store: classpath:keyStore/129/rabbitStore
trust-store-password: 123456
algorithm: TLSv1.2
trust-store-type: JKS
key-store-type: PKCS12
validate-server-certificate: true
verify-hostname: false
注釋:
addresses: 192.168.216.129:5671 ssl使用的是5671的端口,如果不使用ssl還可以使用5672端口
ssl.enabled 是否啟用ssl,默認false
key-store: 客戶端證書的存儲路徑,前面已經生成,直接拷貝過來即可
key-store-password: 生成客戶端證書的密碼
trust-store: 信任證書的存儲路徑,前面已經生成,直接拷貝過來即可
trust-store-password:生成證書的密碼
verify-hostname:是否驗證hostname,默認是true,需要設置為false,否則啟動報錯(No subject alternative names present),原因是證書中定義的common name和程序運行的機器的domain不匹配,這個感覺沒有必要糾結,直接設置為false即可。