Introduction
- 使用純文字帳號密碼驗證機制,現在會被軟體掃出中風險如下
- The remote Advanced Message Queuing Protocol (AMQP) service supports one or more authentication mechanisms that allow credentials to be sent in the clear.
- 建議修改方式
- Disable cleartext authentication mechanisms in the AMQP configuration.
- 將連線與認證方始改用 External 機制,強制使用 SSL 認證連線
RabbitMQ Server
- 啟用 External 機制
- 開啟cmd
cd至rabbit_server底下的sbin資料夾cd C:\Program Files\RabbitMQ Server\rabbitmq_server-3.9.4\sbin (參考依照實際安裝路徑)
- 檢查是否有rabbitmq-auth-mechanism-ssl plugin ?
rabbitmq-plugins list
- 啟用rabbitmq-auth-mechanism-ssl
- 使用 Administrator 帳號登入
rabbitmq-plugins enable rabbitmq_auth_mechanism_ssl
- 一般帳號登入至以下路徑找到 enabled_plugins 檔案
C:\Users\Administrator\AppData\Roaming\RabbitMQ\enabled_plugins(參考)
直接修改檔案內容將要開啟的 plugin 加入
-
以上設定完成後重啟服務
- 正確啟用後可以再次檢查會有”E”標記
- 使用 Administrator 帳號登入
- 設定 Server 雙向驗證
- 伺服器端需要有以下三個檔案 (需要安裝到系統中)
- Certificate Authority
- Certificate
- Private Key
- 修改 advanced.config (若無此檔可自行新增)
- {ssl, [{versions, [‘tlsv1.2’,
‘tlsv1.1’]}]}, 啟用的tls版本- (使用 tlsv1.2 以上版本, tlsv1.1 協定已棄用,會被掃出中風險)
- {auth_mechanisms,[
‘PLAIN’, ‘EXTERNAL’]}, 啟用的驗證方式- (身份驗證使用 EXTERNAL,PLAIN 明文身份驗證,會被掃出中風險)
-
{ssl_listeners, [5671]}, 指定 ssl port
- {ssl_options, []} 設定ssl連線憑證
- cacertfile 設定Certificate Authority檔案路徑
- certfile 設定Certificate 檔案路徑
- keyfile 設定Private Key 檔案路徑
- {verify, verify_peer} 雙向驗證
- {verify, verify_none} 不驗證Client端憑證
- {fail_if_no_peer_cert, true} Client端沒有提供憑證不可連線
- {fail_if_no_peer_cert, false} Client端沒有提供憑證可連線
- {ssl, [{versions, [‘tlsv1.2’,
- Config 正確設定後可以檢查會有”EXTERNAL”標記
RabbitMQ Client
- 設定 Client 雙向驗證
- Client端也需要有以下三個檔案 (需要安裝到系統中)
- Certificate Authority
- Certificate
- Private Key
-
在 C# 中使用 RabbitMQ.Client 設定Ssl連線時,Ssl.CertPath 所讀取的檔案格式為 PKCS#12 format (參考)
- 所以需要將上述 Certificate & Private Key 合併為 pfx 檔案。
//合併 certificate.crt & private.key 為 pfx 格式 (pass:設定密碼也可留空) openssl pkcs12 -export -in certificate.crt -inkey private.key -out client.pfx -passout pass:
- 或是使用伺服器中 Certificate Authority (CA.crt & CA.Key)產生 Client 端專用憑證。
//生成 client-key openssl genrsa -out client-key.pem //使用 client-key 設定主體名稱生成 signingrequest openssl req -new -key client-key.pem -out signingrequest.csr -subj "/CN=MockClient" //使用 signingrequest & CA.crt & CA.Key 生成 client-cert openssl x509 -req -days 1024 -in signingrequest.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -out client-cert.pem //將 client-cert.pem 格式轉換為 client-cert.crt openssl x509 -in client-cert.pem -out client-cert.crt //合併 client-cert.crt & client-key.pem 為 pfx 格式 (pass:設定密碼也可留空) openssl pkcs12 -export -in client-cert.crt -inkey client-key.pem -out client.pfx -passout pass:
- C# appsettings.json 調整新增參數
//CERT_PATH & CERT_PASSPHRASE 有多個,可以在同一個""內使用;區隔 //支援執行多個host連線驗證 "RABBITMQ_ENDPOINTS": { "EnableSSL": true, //是否要啟用Ssl認證(bool) "CERT_PATH": "path/client.pfx", //設定上述生成的 pfx 檔案路徑 "CERT_PASSPHRASE": "", //生成 pfx 檔案時設定的密碼 }
- C# Client 端連線程式調整
- 使用 appsettings 中設定 bool 值,切換連線方式保留設定彈性。
- 增加 SslOption 設定。
lock (_lock) { //... if (_env.EnableSSL) { var certPathList = _env.CertPath.Split(';'); var certPassphraseList = _env.CertPassphrase.Split(';'); factory = new ConnectionFactory { DispatchConsumersAsync = true, AutomaticRecoveryEnabled = true, AuthMechanisms = new AuthMechanismFactory[] { new ExternalMechanismFactory() }, }; foreach (var item in hostList) { var endPoint = new AmqpTcpEndpoint { HostName = item, Port = Convert.ToInt32(portList[index]), Ssl = new SslOption { Enabled = true, ServerName = item, CertPath = certPathList[index], CertPassphrase = certPassphraseList[index++], Version = SslProtocols.Tls12 } }; addressList.Add(endPoint); } //... } else { //... } } // lock
RabbitMQ Management
- 當Server & Client 都設定好之後。
- 需要再RabbitMQ Admin中添加生成憑證時設定的主機名,供登入時驗證用。
驗證
-
當以上都正確設定完成後,在 RabbitMQ Management 中可以確認,連線已啟用TLS/SSL協議
-
並且 Authentication 確認是使用 EXTERNAL 機制
-
使用 Swagger 測試
-
在網頁測試模擬 Publish 發送訊息
-
後端 Subscribe 接收
-