GPrabhudas opened a new issue #489:
URL: https://github.com/apache/pulsar-client-go/issues/489
### Description:
Failing to connect to broker because cert verification fails with error:
`x509: cannot validate certificate for xxx.xxx.xxx.xxx because it doesn't
contain any IP SANs`
Assume pulsar cluster with below details
- cluster url : `my.test.pulsar.cluster.com`
- Size of Cluster : `assume 10 nodes.`
- Cert: Cert generated using [LetsEncrypt](https://letsencrypt.org/) <br />
- DNS : `my.test.pulsar.cluster.com`
- SANs : without SANs
Every node in the cluster have same(above) certificate.
#### Error :
```sh
INFO[0000] [Connecting to broker]
remote_addr="pulsar+ssl://my.test.pulsar.cluster.com:6651"
INFO[0001] [TCP connection established] local_addr="172.xxx.xxx.xxx:56320"
remote_addr="pulsar+ssl://my.test.pulsar.cluster.com:6651"
INFO[0001] [Connection is ready] local_addr="172.xxx.xxx.xxx:56320"
remote_addr="pulsar+ssl://my.test.pulsar.cluster.com:6651"
INFO[0002] [Connecting to broker]
remote_addr="pulsar+ssl://xxx.xxx.xxx.xxx:6651"
WARN[0002] [Failed to connect to broker.] error="x509: cannot validate
certificate for xxx.xxx.xxx.xxx because it doesn't contain any IP SANs"
remote_addr="pulsar+ssl://xxx.xxx.xxx.xxx:6651"
INFO[0002] [Connection closed]
remote_addr="pulsar+ssl://xxx.xxx.xxx.xxx:6651"
ERROR[0002] [Failed to create producer] error="connection error"
topic=testtopic-partition-0 ERRO[0002] [Failed to create producer]
error="connection error" topic=testtopic-partition-0 2021/03/18 16:33:20
connection error
```
If you look at the logs, first it tries to connect using DNS and the TCP
connection establishes without error.
Next it tries to use Broker IP address to create producer and fails.
### Resolutions:
- Add IP address of all the nodes in `subjectAltName` extension of cert.
Which I dont think is a good option if the size of cluster grows and there is
also a limit of sans in a cert.
- Set ServerName i.e
[tls.Config.ServerName](https://github.com/golang/go/blob/master/src/crypto/tls/common.go#L243)
. Which is currently not possible
because it is being read from [physical
address](https://github.com/apache/pulsar-client-go/blob/master/pulsar/internal/connection.go#L829).
Since it is reading from physical address(ex: `
pulsar+ssl://xxx.xxx.xxx.xxx:6651`), `ServerName` would be an IP address
`xxx.xxx.xxx.xxx` which doesn't match with the dns `my.test.pulsar.cluster.com`
and fails to create producer.
#### Consideration :
I'm trying to find out a way to set `ServerName` something like below.
```go
//
https://github.com/apache/pulsar-client-go/blob/master/pulsar/client.go#L78
// Add ServerName feild to ClientOptions
type ClientOptions struct {
// ... existing fields
ServerName string
}
//
https://github.com/apache/pulsar-client-go/blob/master/pulsar/internal/connection.go#L49
// Add ServerName field to TLSOptions
type TLSOptions struct {
// ... existing fields
ServerName string
}
//
https://github.com/apache/pulsar-client-go/blob/master/pulsar/internal/connection.go#L829
// Modify method `getTLSConfig` as follows
if c.tlsOptions.ValidateHostname {
// If ServerName is already set, use it
if c.tlsOptions.ServerName != "" {
tlsConfig.ServerName = c.tlsOptions.ServerName
} else {
// otherwise infer from physical address
tlsConfig.ServerName = c.physicalAddr.Hostname()
}
}
```
I'm happy to use any other alternative if already available. And if at all
above changes looks good, I'll raise a PR for this.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]