RabbitMQ DotNet客户端无法连接SSL。

3
我们正在尝试制作一个 PoC,以展示在同一组织中,使用不同语言编写的应用程序可以通过 RabbitMQ broker 进行通信。我们运行原始的 RabbitMQ docker 镜像rabbitmq:3.6.1-management和原始的 haproxy docker 镜像haproxy:1.6.5,haproxy镜像支持 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端口关闭,则连接失败并显示"connection refused"错误。Go和Node.js代码证明我的SSL设置是正确的。.Net客户端的错误表明SSL设置没有生效的机会。我使用debian jessie和Mono,请问我是否漏掉了什么显而易见的问题?

你的 rabbitmq.config 长什么样子? - cantSleepNow
我已经更新了原始帖子,其中包含RabbitMQ配置。这是一个默认配置。 - Andrey.Kozyrev
2个回答

2
这是RabbitMQ .net客户端3.6.2库的一个问题,它在使用SSL时没有遵守指定的端口。该问题已经得到修复,并将在3.6.3发布时可用(他们会与服务器同步发布,所以不知道这可能何时发布)。
您的选择如下: - 使用旧版本的.net客户端 - 从最新源代码构建.net客户端 - 如果可以,请使用标准端口 - 等待3.6.3发布

0

我曾遇到过与连接到docker rabbitmq容器的masstransit Net Core客户端类似的问题。以下是我的配置方案,可行,可能对您有用:

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

Docker-compose:

...
  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)

为了避免我的证书中出现服务器名称不匹配的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接