RabbitMQ(五)

SSL

官方地址:http://www.rabbitmq.com/ssl.html

百科:

SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。

分为 单向认证 和 双向认证。RabbitMQ 采用的是双向认证方式。

一、配置过程:

# mkdir testca
# cd testca
# mkdir certs private
# chmod 700 private
# echo 01 > serial
# touch index.txt

下面这段保存成 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 = 365
default_md = sha256

policy = testca_policy
x509_extensions = certificate_extensions

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

[ certificate_extensions ]
basicConstraints = CA:false

[ req ]
default_bits = 2048
default_keyfile = ./private/cakey.pem
default_md = sha256
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 证书

# openssl req -x509 -config openssl.cnf -newkey rsa:2048 -days 365 -out cacert.pem -outform PEM -subj /CN=MyTestCA/ -nodes
# openssl x509 -in cacert.pem -out cacert.cer -outform DER

服务器 证书

# cd ..
# ls
testca
# mkdir server
# cd server
# openssl genrsa -out key.pem 2048
# openssl req -new -key key.pem -out req.pem -outform PEM -subj /CN=$(hostname)/O=server/ -nodes
# cd ../testca
# openssl ca -config openssl.cnf -in ../server/req.pem -out ../server/cert.pem -notext -batch -extensions server_ca_extensions
# cd ../server
# openssl pkcs12 -export -out keycert.p12 -in cert.pem -inkey key.pem -passout pass:MySecretPassword

客户端 证书

# cd ..
# ls
server testca
# mkdir client
# cd client
# openssl genrsa -out key.pem 2048
# openssl req -new -key key.pem -out req.pem -outform PEM -subj /CN=$(hostname)/O=client/ -nodes
# cd ../testca
# openssl ca -config openssl.cnf -in ../client/req.pem -out ../client/cert.pem -notext -batch -extensions client_ca_extensions
# cd ../client
# openssl pkcs12 -export -out keycert.p12 -in cert.pem -inkey key.pem -passout pass:MySecretPassword

将 testca/cacert.pem、server/cert.pem、server/key.pem 复制到 /etc/rabbitmq/ssl/ 目录下面,记得查看权限,否则报 read timeout 异常

添加配置文件

二、java代码测试

cmd命令:

C:Program FilesJavajdk1.8.0_25>keytool -import -alias server1 -file D:opensslinservercert.pem -keystore D:opensslinserver abbitstore

项目截图:(拷贝 client/keycert.p12 和 rabbitstore 到项目中)

import java.io.FileInputStream;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.GetResponse;


public class Example2 {
    
     public static void main(String[] args) throws Exception
     {
       char[] keyPassphrase = "MySecretPassword".toCharArray();
       KeyStore ks = KeyStore.getInstance("PKCS12");
       
       ks.load(new FileInputStream(Class.class.getResource("/").getPath() + "keycert.p12"), keyPassphrase);

       KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
       kmf.init(ks, keyPassphrase);

       char[] trustPassphrase = "rabbitstore".toCharArray();
       KeyStore tks = KeyStore.getInstance("JKS");
       tks.load(new FileInputStream(Class.class.getResource("/").getPath() + "rabbitstore"), trustPassphrase);

       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("");
       factory.setPort(5671);
       
       factory.setUsername("");
       factory.setPassword("");
       
       factory.useSslProtocol(c);

       Connection conn = factory.newConnection(); 
       Channel channel = conn.createChannel();

       channel.queueDeclare("rabbitmq-java-test", false, true, true, null);
       channel.basicPublish("", "rabbitmq-java-test", null, "Hello, World".getBytes());


       GetResponse chResponse = channel.basicGet("rabbitmq-java-test", 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();
   }
}

结果:

三、c#代码测试

导入自颁发证书

using RabbitMQ.Client;
using RabbitMQ.Util;
using System;
using System.Net.Security;
using System.Text;

namespace TestSSL
{
    class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                ConnectionFactory cf = new ConnectionFactory()
                    {
                        HostName = "",
                        Port = 5671,
                        UserName = "",
                        Password = ""
                    };
                cf.Ssl.ServerName = "10-10-43-207"; //必须同服务器证书中设置的 CN 名称一致
                cf.Ssl.CertPath = AppDomain.CurrentDomain.BaseDirectory + "client\keycert.p12";
                cf.Ssl.CertPassphrase = "MySecretPassword";
                cf.Ssl.AcceptablePolicyErrors = //SslPolicyErrors.RemoteCertificateNameMismatch |
                                                SslPolicyErrors.RemoteCertificateNotAvailable |
                                                SslPolicyErrors.RemoteCertificateChainErrors;
                cf.Ssl.Enabled = true;

                using (IConnection conn = cf.CreateConnection())
                {
                    using (IModel ch = conn.CreateModel())
                    {
                        ch.QueueDeclare("rabbitmq-dotnet-test", false, false, false, null);
                        ch.BasicPublish("", "rabbitmq-dotnet-test", null,
                                        Encoding.UTF8.GetBytes("Hello, World"));
                        BasicGetResult result = ch.BasicGet("rabbitmq-dotnet-test", true);
                        if (result == null)
                        {
                            Console.WriteLine("No message received.");
                        }
                        else
                        {
                            Console.WriteLine("Received:");
                            DebugUtil.DumpProperties(result, Console.Out, 0);
                        }
                        ch.QueueDelete("rabbitmq-dotnet-test");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.InnerException);
            }

            Console.ReadKey(true);
        }
    }
}

结果:

原文地址:https://www.cnblogs.com/tq1226112215/p/5910032.html