golang的amqp库提供了使用ssl认证的demo,代码 使用自签名的证书,连接的demo如下
cfg := new(tls.Config)
cfg.RootCAs = x509.NewCertPool()
if ca, err := ioutil.ReadFile(config.RabbitMq.CACert); err == nil {
cfg.RootCAs.AppendCertsFromPEM(ca)
}
if cert, err := tls.LoadX509KeyPair(config.RabbitMq.ClientCert, config.RabbitMq.ClientKey); err == nil {
cfg.Certificates = append(cfg.Certificates, cert)
}
mqUrl := amqp.URI{
Scheme: "amqps",
Host: config.RabbitMq.Host,
Port: config.RabbitMq.Port,
Username: config.RabbitMq.UserName,
Password: config.RabbitMq.PassWord,
Vhost: "test",
}.String()
gologger.Debug().Msgf("rabbitmq url: %s", mqUrl)
conn, err := amqp.DialTLS(mqUrl, cfg)
if err != nil {
gologger.Fatal().Msgf("Failed to connect rabbitmq: %s", err.Error())
}
gologger.Debug().Msgf("%+v", conn)
这个代码在rabbitmq是在localhost搭建的,这段测试代码也是在本地运行的情况下是不会报错的,但是如果将Host换成ip,就会报如下的错误
x509: cannot validate certificate for 192.168.31.69 because it doesn't contain any IP SANs
这应该是自签的证书没带有hostname,导致证书校验失败了,于是翻了一下源码,发现tls.Config有一个InsecureSkipVerify选项,原始的说明如下
InsecureSkipVerify controls whether a client verifies the server's certificate chain and host name. If InsecureSkipVerify is true, crypto/tls accepts any certificate presented by the server and any host name in that certificate. In this mode, TLS is susceptible to machine-in-the-middle attacks unless custom verification is used. This should be used only for testing or in combination with VerifyConnection or VerifyPeerCertificate.
大概意思就是信任任何主机名,但是他不建议这么做,因为容易受到中间人攻击。但是开启这个选项,就可以忽略主机名校验,所以只需将这个值是在为true既可以不校验主机名,然后就可以正常连接到rabbitmq。
cfg.InsecureSkipVerify = true
将这行代码加到amqp.DialTLS前再次连接就不会报错了。