-
Type: Bug
-
Resolution: Unresolved
-
Priority: Minor - P4
-
None
-
Affects Version/s: None
-
None
libmongoc's happy eyeballs implementation will currently attempt to connect to a server using multiple DNS records, preferring IPv6 records, and delaying IPv4 by 250ms. Only the last connection error is recorded here. But this could mean that the most meaningful error is not recorded.
Here is an example of when this can be detrimental. Start a mongod with TLS, only listening on IPv6, with an invalid TLS certificate.
> cat test.conf
net:
ipv6: true
bindIp: ::1
tls:
mode: requireTLS
certificateKeyFile: invalid-cert.pem
> mongod -f test.conf --dbpath ./data
Run mongoc-ping using a domain name that resolves to both IPv4 and IPv6 address. I did this by modifying /etc/hosts to have this record:
::1 ipv4_and_ipv6 127.0.0.1 ipv4_and_ipv6
Then, attempt to connect using that domain name:
> ./cmake-build/src/libmongoc/mongoc-ping "mongodb://ipv4_and_ipv6:27017/?tls=true" Ping failure: No suitable servers found (`serverSelectionTryOnce` set): [connection closed calling ismaster on 'ipv4_and_ipv6:27017']
The error indicates a failure to connect not a TLS failure. E.g. connecting directly with the IPv6 address, you'll get a more indicative error:
Ping failure: No suitable servers found (`serverSelectionTryOnce` set): [TLS handshake failed (Certificate trust failure: Host name mismatch) calling ismaster on 'ipv6_only:27017']
The issue is, that since the IPv4 address is tried after the IPv6 address fails to connect over TLS, it overwrites the error.
Possible solutions:
1. combine all connection errors against a server (this might make it very lengthy, and more likely to fill up all of the bson_error_t's 504 character max.
2. store the error of the stream that got the furthest (i.e. if stream A gets as far as the TLS handshake, but stream B never even makes connection, then stream A's error should be the one reported).