0%

Docker配置rabbitmq with ssl

Docker-compose 配置 rabbitmq-management

带管理面板的rabbitmq,直接加载镜像,管理面板的http端口是 15672,直接拉取镜像就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
version: '3'

services:
rabbitmq:
image: rabbitmq:3.8.14-management-alpine
container_name: rabbitmq
ports:
- 8080:15672
volumes:
- rabbitmq-data:/var/lib/rabbitmq

volumes:
rabbitmq-data:

然后打开 http://localhost:8080/ 初始化用户密码是 guest/guest 。

配置 rabbitmq-management with ssl

  1. 生成证书

直接使用脚本,比较方便 https://github.com/Berico-Technologies/CMF-AMQP-Configuration

1
2
3
4
5
6
7
8
git clone https://github.com/Berico-Technologies/CMF-AMQP-Configuration
cd CMF-AMQP-Configuration/ssl
# MyRabbitMQCA 是自定义CA的名称
sh setup_ca.sh MyRabbitMQCA
# rabbitmq-server 服务器hostname rabbit 是密码
sh make_server_cert.sh rabbitmq rabbit
# rabbit-client 客户端标识 rabbit 是密码
sh create_client_cert.sh rabbit-client rabbit

注意

1)服务器证书的CN需要与hostname一致,不然在创建tls连接时会失败。

2)这个脚本直接创建,通过golang 创建tls连接时,会出现

failed to connect rabbitmq!:x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0

这个错误。处理方式有两种

A. 修正证书的SAN

B. 通过GODEBUG设置x509ignoreCN=0 忽略

B的方式虽然更简单,但是这种绕过的方式必然不是解决方案。

那怎么修正 SAN 呢,参考下面的步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
# 进入 CMF-AMQP-Configuration/ssl 编辑 openssl.conf
# 找到 [ req ] 在末尾添加
req_extensions = v3_req
# 然后在末尾添加 标签 [ v3_req ] [ alt_names ]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = localhost
DNS.2 = rabbitmq
# 这里的DNS就是证书对应的域名,按需要来添加,目前例子中是 rabbitmq,就这么填。这里支持通配符 *,可以做多域名支持

修改 make_server_cert.sh 脚本

1
2
3
4
5
6
7
8
9
# 找到创建证书的地方
openssl req -new -key $sname.key.pem -out $sname.req.pem -outform PEM -subj /CN=$sname/O=server/ -nodes

openssl ca -in ../server/$sname.req.pem -out ../server/$sname.cert.pem -notext -batch -extensions server_ca_extensions

# 追加 -extensions v3_req
openssl req -new -key $sname.key.pem -out $sname.req.pem -outform PEM -subj /CN=$sname/O=server/ -nodes -extensions v3_req

openssl ca -in ../server/$sname.req.pem -out ../server/$sname.cert.pem -notext -batch -extensions server_ca_extensions -extensions v3_req

修改客户端证书,同样

1
2
3
4
5
6
7
# 找到下面两行
openssl req -new -key $cname.key.pem -out $cname.req.pem -outform PEM -subj /CN=$cname/O=client/ -nodes
openssl ca -in ../client/$cname.req.pem -out ../client/$cname.cert.pem -notext -batch -extensions client_ca_extensions

# 追加 -extensions v3_req
openssl req -new -key $cname.key.pem -out $cname.req.pem -outform PEM -subj /CN=$cname/O=client/ -nodes -extensions v3_req
openssl ca -in ../client/$cname.req.pem -out ../client/$cname.cert.pem -notext -batch -extensions client_ca_extensions -extensions v3_req

然后重新生成一遍证书

执行脚本后,复制证书文件,只需要5个。

cacert.pem

rabbitmq.cert.pem 服务端证书

rabbitmq.key.pem 服务端拿证书

rabbitmq-client.cert.pem 客户端证书

rabbitmq-client.key.pem 客户端证书

将文件复制到 cert 目录中,docker-compose 目录结构如下

1
2
3
4
5
6
7
8
9
rabbitmq-folder
|-- docker-compose.yaml
|-- rabbitmq.conf
|-- cert
|-- cacert.pem
|-- rabbitmq.cert.pem
|-- rabbitmq.key.pem
|-- rabbitmq-client.cert.pem
|-- rabbitmq-client.key.pem

到此为止,证书处理完成。

  1. 配置 rabbitmq.conf
1
2
3
4
5
6
7
8
9
loopback_users.guest = false
listeners.ssl.default = 5671
ssl_options.cacertfile = /cert/cacert.pem
ssl_options.certfile = /cert/rabbitmq.cert.pem
ssl_options.fail_if_no_peer_cert = true
ssl_options.keyfile = /cert/rabbitmq.key.pem
ssl_options.verify = verify_peer

management.tcp.port = 15672
  1. 配置compose
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
version: '3'

services:
rabbitmq:
image: rabbitmq:3.8.14-management-alpine
container_name: rabbitmq
hostname: rabbitmq
ports:
- 8080:15672
volumes:
- rabbitmq-data:/var/lib/rabbitmq
- ./rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf
- ./cert:/cert

volumes:
rabbitmq-data:

然后唤起验证

打开浏览器

image-20210330041852295

看到 amqp/ssl 5671 , 配置正常。

后语

在 rabbitmq 的镜像中,可以通过 environment 环境变量,设置

RABBITMQ_MANAGER_SSL_CACERTFILE
RABBITMQ_MANAGEMENT_SSL_CERTFILE
RABBITMQ_MANAGEMENT_SSL_KEYFILE

参考:https://hub.docker.com/_/rabbitmq

来配置证书,但是个人并不喜欢直接这么配置,因为直接使用这个,默认情况management plugin 也会开启了ssl。对于自签证书来说,并不方便。

个人更偏好 management plugin 是 http协议的,外层 nginx 统一处理 ssl 证书。

加上本身rabbitmq的配置文件也是需要自定义的,直接在配置文件修改就行,没必要通过环境变量来设置。


相关资料

rabbitmq镜像 https://hub.docker.com/_/rabbitmq

golang 自签证书双向认证 https://studygolang.com/articles/31646