RabbitMQ DotNet 客户端不连接到 SSL

RabbitMQ DotNet Client does not connect to SSL

我们正在尝试制作一个 PoC,表明用不同语言编写的应用程序可以在一个组织中通过 RabbitMQ 代理进行通信。我们 运行 vanilla RabbitMQ docker image rabbitmq:3.6.1-management 和 vanilla haproxy docker image haproxy:1.6.5 执行 SSL:

frontend amqp_front
    bind *:5672 tcp-ut 5s
    mode tcp
    timeout client 60s
    timeout client-fin 1s
    no option clitcpka
    default_backend amqp_back

frontend amqp_front_ssl
    bind *:5671 tcp-ut 5s ssl crt /etc/certs/haproxy/rmq.pem ca-file /etc/certs/haproxy/root.crt verify required
    mode tcp
    timeout client 60s
    timeout client-fin 1s
    no option clitcpka
    acl client ssl_c_s_dn(CN) -m str cli
    tcp-request content reject if !client
    default_backend amqp_back

RabbitMQ 配置为:

[
  {rabbit,
    [
      { tcp_listeners, [ 5672 ] },
      { ssl_listeners, [ ] },
      {default_pass, <<"pwd">>},
      {default_user, <<"usr">>},
      {default_vhost, <<"default">>},
      {loopback_users, []}
    ]
  },
  { rabbitmq_management, [
      { listener, [
        { port, 15672 },
        { ssl, false }
        ]
      }
    ]
  }
].

我们在 Go & Node.js 中编写了一个简单的代码,它们都加载 root.crt,cli.crt & cli.key 并成功连接到 SSL 端口 5671 并使用。

尝试使用 RabbitMQ.Client.dll(版本 3.6.0、3.6.1、3.6.2)在 .Net 中编写相同的简单代码但失败了:

X509Store store = new X509Store (StoreName.Root, StoreLocation.LocalMachine);
store.Open (OpenFlags.ReadOnly);

var factory = new ConnectionFactory ();
factory.Ssl.Enabled = true;
factory.Ssl.ServerName = "rmq";
factory.Ssl.Certs = store.Certificates;
factory.Ssl.CertPassphrase = "";
factory.HostName = "localhost";
factory.Port = 5671;
factory.UserName = "usr";
factory.Password = "pwd";
factory.VirtualHost = "default";

var conn = factory.CreateConnection ()

.Net 客户端会忽略端口 5671 而忽略上述设置,它只会转到 5672。如果 5672 打开 - 连接到它,如果 5672 关闭 - 失败并拒绝连接。

Go 中的代码和 Node.js 证明我的 SSL 设置是有效的。 .Net 客户端的错误显示 SSL 东西甚至没有机会跳入。

我正在使用 debian jessie 和 Mono。

我是不是遗漏了什么明显的东西?

这是 RabbitMQ .net 客户端 3.6.2 库在使用 SSL 时不遵守指定端口的问题。

它已经被修复,将在 3.6.3 发布时可用(他们与服务器同步发布,所以不知道什么时候发布)。

您的选择是:-

  • 使用旧版本的 .net 客户端
  • 从最新源构建 .net 客户端
  • 尽可能使用标准端口
  • 等待3.6.3发布

我在从 masstransit Net Core Client 连接到 docker rabbitmq 容器时遇到了类似的问题。以下是我的配置,有效,可以用:

一些注意事项: Masstransit:5.1.5,Net Core 版本:2.2

Docker-撰写:

...
  bus_rabbitmq:
    image: rabbitmq:3-management
    hostname: docker-host
    environment:
      RABBITMQ_DEFAULT_VHOST: "databus"
      RABBITMQ_SSL_CACERTFILE: "/app/certs/dev/myCA.pem"
      RABBITMQ_SSL_CERTFILE: "/app/certs/dev/rabbitmq/rabbit-server.crt"
      RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT: "false"
      RABBITMQ_SSL_KEYFILE: "/app/certs/dev/rabbitmq/rabbit-server.key"
      RABBITMQ_SSL_VERIFY: "verify_peer"
      RABBITMQ_MANAGEMENT_SSL_CACERTFILE: "/app/certs/dev/myCA.pem"
      RABBITMQ_MANAGEMENT_SSL_CERTFILE: "/app/certs/dev/rabbitmq/rabbit-server.crt"
      RABBITMQ_MANAGEMENT_SSL_FAIL_IF_NO_PEER_CERT: "false"
      RABBITMQ_MANAGEMENT_SSL_VERIFY: "verify_peer"
      RABBITMQ_MANAGEMENT_SSL_KEYFILE: "/app/certs/dev/rabbitmq/rabbit-server.key"
    ports:
      - "15672:15672"
      - "15671:15671"
      - "5672:5672"
      - "5671:5671"
    volumes:
    - ./certs:/app/certs
    networks:
      - local_network
...

客户端配置:

...
var rabbitCredentials = CredentialsService.RetrieveRabbitMqCredentials();

builder.Register(c =>
    {
        return Bus.Factory.CreateUsingRabbitMq(sbc =>
        {
            sbc.Host(rabbitCredentials.RabbitConnectionString, 5671, rabbitCredentials.RabbitVHost, h =>
            {
                var certData = CertsService.RetrieveCertificateInfo(ServiceType.RabbitMq);

                h.Username(rabbitCredentials.UserName);
                h.Password(rabbitCredentials.Password);
                h.Heartbeat(10);
                h.UseSsl(s =>
                {
                    s.Protocol = SslProtocols.Tls12;
                    s.Certificate = X509Certificate.CreateFromCertFile(certData.Path);
                    s.AllowPolicyErrors(SslPolicyErrors.RemoteCertificateNameMismatch);
                    s.UseCertificateAsAuthenticationIdentity = false;
                });
            });

            sbc.ReceiveEndpoint("data_queue", ec =>
            {
                // loading consumers
                ec.LoadFrom(c);

                // loading saga state machines
                //ec.LoadStateMachineSagas(c);
            });
        });
    })
    .As<IBusControl>()
    .As<IPublishEndpoint>()
    .SingleInstance();
...

我需要使用:

AllowPolicyErrors(SslPolicyErrors.RemoteCertificateNameMismatch)

以避免我的证书中的服务器名称不匹配。