1. 程式人生 > >RabbitMQ設定SSL相關操作

RabbitMQ設定SSL相關操作

相關檔案

openssl.cnf 檔案配置

[ ca ]                                                     
default_ca = testca                                        

[ testca ]                                                 
dir = .                                                    
certificate = $dir/cacert.pem                              
database = $dir/index.txt                                  
new_certs_dir = $dir/certs                                 
private_key = $dir/private/cakey.pem                       
serial = $dir/serial                                       

default_crl_days = 7                                       
default_days = 10950                                         
default_md = sha1                                          

policy = testca_policy                                     
x509_extensions = certificate_extensions                   

[ testca_policy ]                                          
commonName = supplied                                      
stateOrProvinceName = optional                             
countryName = optional                                     
emailAddress = optional                                    
organizationName = optional                                
organizationalUnitName = optional                          

[ certificate_extensions ]                                 
basicConstraints = CA:false                                

[ req ]                                                    
default_bits = 2048                                        
default_keyfile = ./private/cakey.pem                      
default_md = sha1                                          
prompt = yes                                               
distinguished_name = root_ca_distinguished_name            
x509_extensions = root_ca_extensions                       

[ root_ca_distinguished_name ]                             
commonName = hostname                                      

[ root_ca_extensions ]                                     
basicConstraints = CA:true                                 
keyUsage = keyCertSign, cRLSign                            

[ client_ca_extensions ]                                   
basicConstraints = CA:false                                
keyUsage = digitalSignature                                
extendedKeyUsage = 1.3.6.1.5.5.7.3.2                       

[ server_ca_extensions ]                                   
basicConstraints = CA:false                                
keyUsage = keyEncipherment                                 
extendedKeyUsage = 1.3.6.1.5.5.7.3.1

生成ca檔案,指令碼(setup_ca.sh)內容如下:

#!/bin/bash

hr="-------------------------------------------"
br=""
strength=2048
valid=10950	

message="Usage:  sh setup_ca.sh [certificate authority CN]"

if [ $# -ne 1 ];
then
	echo $message
	exit 2
fi

if [ $1 = "--help" ];
then
	echo $message
	exit 2
fi

certauthCN=
$1 export OPENSSL_CONF=../openssl.cnf if [ ! -d ./ca/ ]; then echo "Creating folder: ca/" mkdir ca echo "Creating folder: ca/private/" mkdir ca/private echo "Creating folder: ca/certs/" mkdir ca/certs echo "Creating folder: ca/serial" echo "01" > ca/serial echo "Creating file: ca/index.txt" touch ca/index.txt fi
cd ca openssl req -x509 -newkey rsa:$strength -days $valid -out cacert.pem -outform PEM -subj /CN=$certauthCN/ -nodes openssl x509 -in cacert.pem -out cacert.cer -outform DER cd ..

生成伺服器證書,指令碼(make_server_cert.sh)內容如下:

#!/bin/bash

hr="-------------------------------------------"
br=""
strength=2048
valid=10950	

message="Usage:  sh make_server_cert.sh [server name] [PKCS12 password]"

if [ $# -ne 2 ];
then
	echo $message
	exit 2
fi

if [ $1 = "--help" ];
then
	echo $message
	exit 2
fi

sname=$1
password=$2

export OPENSSL_CONF=../openssl.cnf

if [ ! -d ./server/ ];
then
	echo "Creating Server folder: server/"
	mkdir server
fi

cd server

echo "Generating key.pem"

openssl genrsa -out key.pem $strength

echo "Generating req.pem"

openssl req -new -key key.pem -out req.pem -outform PEM -subj /CN=$sname/O=server/ -nodes

cd ../ca

echo "Generating cert.pem"

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

cd ../server

echo "Generating keycert.p12"

openssl pkcs12 -export -out keycert.p12 -in cert.pem -inkey key.pem -passout pass:$password

cd ..

生成客戶端證書,指令碼(create_client_cert.sh)內容如下:

#!/bin/bash

hr="-------------------------------------------"
br=""
strength=2048
valid=10950	

message="Usage:  sh create_client_cert.sh [client name] [PKCS12 password]"

if [ $# -ne 2 ];
then
	echo $message
	exit 2
fi

if [ $1 = "--help" ];
then
	echo $message
	exit 2
fi

cname=$1
password=$2

export OPENSSL_CONF=../openssl.cnf

if [ ! -d ./client/ ];
then
	echo "Creating folder: client/"
	mkdir client
fi

cd client

echo "Generating key.pem"

openssl genrsa -out key.pem $strength

echo "Generating req.pem"

openssl req -new -key key.pem -out req.pem -outform PEM -subj /CN=$cname/O=client/ -nodes

cd ../ca

echo "Generating cert.pem"

openssl ca -in ../client/req.pem -out ../client/cert.pem -notext -batch -extensions client_ca_extensions

cd ../client

echo "Generating keycert.p12"

openssl pkcs12 -export -out keycert.p12 -in cert.pem -inkey key.pem -passout pass:$password

cd ..

步驟:

我這裡以Linux為例,目錄是/usr. 寫一下步驟

首先開啟/usr,建立一個資料夾
mkdir testca
拷貝上面所有shell指令碼,然後分步驟執行:
#引數是證書頒發機構名
sh setup_ca.sh MyRabbitMQSSL
 
#生成伺服器證書, 第一個引數是伺服器名,第二個引數是密碼
sh make_server_cert.sh rabbit-server rabbit

#生成客戶端證書,第一個引數是客戶端名稱,第二個引數是密碼
sh create_client_cert.sh rabbit-client  rabbit
keytool匯入證書
keytool -import -alias rabbit-server -file ./server/cert.pem -keystore trustStore -storepass rabbit

此時會提示是否匯入證書,輸入y或者,然後回車

刪除之前匯入過的證書,別名為 rabbit-server

keytool -delete -alias rabbit-server -keystore trustStore -storepass rabbit
配置rabbitmq
vi $rabbitmq_home/etc/rabbitmq/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,"/usr/testca/ca/cacert.pem"},
            {certfile,"/usr/testca/server/cert.pem"},
            {keyfile,"/usr/testca/server/key.pem"},
            {verify, verify_peer},
            {fail_if_no_peer_cert, true},
            {versions, ['tlsv1.2', 'tlsv1.1']}
        ]}
    ]}
].

儲存.

重啟rabbitmq.
#關閉服務
rabbitmqctl stop
#啟動服務
rabbitmq-server -detached
#檢視狀態
rabbitmqctl status

編寫java測試類

import com.rabbitmq.client.Channel;  
import com.rabbitmq.client.Connection;  
import com.rabbitmq.client.ConnectionFactory;  
import com.rabbitmq.client.GetResponse;  
  
import javax.net.ssl.KeyManagerFactory;  
import javax.net.ssl.SSLContext;  
import javax.net.ssl.TrustManagerFactory;  
import java.io.FileInputStream;  
import java.security.KeyStore;  
  
public class ValidatingCert{  
    public static void main(String[] args) throws Exception{
        char[] keyPassphrase = "rabbit".toCharArray();  //證書密碼
        KeyStore ks = KeyStore.getInstance("PKCS12");  
        ks.load(new FileInputStream("keycert.p12"), keyPassphrase);//把client目錄keycert.p12拷貝到專案裡面
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");  
        kmf.init(ks, keyPassphrase);  
  
        char[] trustPassphrase = "rabbit".toCharArray();  //證書密碼
        KeyStore tks = KeyStore.getInstance("JKS");  
        tks.load(new FileInputStream("trustStore"), trustPassphrase);//把/usr/testca/目錄的trustStore拷貝到專案裡面
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");  
        tmf.init(tks);
        SSLContext c = SSLContext.getInstance("TLSv1.1");  
        c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);  
  
        ConnectionFactory factory = new ConnectionFactory();  
        factory.setHost("192.168.0.111");//rabbitmq server
        factory.setPort(5671);
        factory.useSslProtocol(c); 
        Connection conn = factory.newConnection();  
        Channel channel = conn.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: " + new String(body));  
        }  
        channel.close();  
        conn.close();  
    }  
}  

參考:
http://vstars.iteye.com/blog/2229409
https://github.com/Berico-Technologies/CMF-AMQP-Configuration/tree/master/ssl