mongodb / mongo-php-library

The Official MongoDB PHP library
https://mongodb.com/docs/php-library/current/
Apache License 2.0
1.59k stars 260 forks source link

TLS connection with mongo cluster failed (while single host works) #947

Closed HalleyUK closed 2 years ago

HalleyUK commented 2 years ago

Bug Report

Hi, I need to connect to Mongo from PHP7.3. I used this library it works perfectly without TLS. When I use TLS, it works if I just specify the mongo host with single host name such as 'host' => 'dev2-ent-mongodb1' (with replicaSet and CAfile etc). But it throw this error when I specify the host as a cluster such as: 'host' => 'dev2-ent-mongodb1,dev2-ent-mongodb2,dev2-ent-mongodb3' The error log: No suitable servers found: serverselectiontimeoutms timed out: [TLS handshake failed: certificate verify failed (64): IP address mismatch calling hello on '10.107.1.202:27017'] [TLS handshake failed: certificate verify failed (64): IP address mismatch calling hello on '10.107.1.68:27017'] [TLS handshake failed: certificate verify failed (64): IP address mismatch calling hello on '10.107.1.135:27017']

With the host set as a cluster and the flag "tlsAllowInvalidHostnames" => true, it works as well. But with Mongo Studio 3T, it works perfectly without this flag set. So it looks like a problem in this library.

Environment

PHP7.3 (with Phalcon 3.4.5)/Ubuntu20

Test Script

Expected and Actual Behavior

working in Apache and Cron job.

Debug Log

No suitable servers found: serverselectiontimeoutms timed out: [TLS handshake failed: certificate verify failed (64): IP address mismatch calling hello on '10.107.1.202:27017'] [TLS handshake failed: certificate verify failed (64): IP address mismatch calling hello on '10.107.1.68:27017'] [TLS handshake failed: certificate verify failed (64): IP address mismatch calling hello on '10.107.1.135:27017']

jmikola commented 2 years ago

When I use TLS, it works if I just specify the mongo host with single host name such as 'host' => 'dev2-ent-mongodb1' (with replicaSet and CAfile etc). But it throw this error when I specify the host as a cluster such as: 'host' => 'dev2-ent-mongodb1,dev2-ent-mongodb2,dev2-ent-mongodb3'.

Neither the PHP driver nor library take a host option, so it seems like you're using another library on top of the driver. To get to the root of this issue, please share two scripts using just the driver and library that reproduces successful connection for a single host and error for multiple hosts.

For example:

So please prepare two scripts (each with the appropriate connection options) and share their output when executing them through a CLI environment. I expect we'll see no output if selectServer() or command() succeeds and an uncaught exception otherwise. Once we have that, we can look at what the driver is doing directly.


The PHP driver's TLS is handled by whatever library is linked by libmongoc (and detected during compilation). This will most likely be OpenSSL, but the particular version of OpenSSL used may still differ from other applications (e.g. Mongo Studio 3T) if you happen to have multiple versions on your system. We can confirm exactly what libmongoc uses by running ldd /path/to/mongodb.so (where /path/to/mongodb.so is the compiled PHP extension). For instance, on my system:

$ ldd ~/phpc/modules/mongodb.so
    linux-vdso.so.1 (0x00007ffc2fd63000)
    libsnappy.so.1 => /usr/lib/x86_64-linux-gnu/libsnappy.so.1 (0x00007efc2b98c000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007efc2b970000)
    libzstd.so.1 => /usr/lib/x86_64-linux-gnu/libzstd.so.1 (0x00007efc2b8c7000)
    libsasl2.so.2 => /usr/lib/x86_64-linux-gnu/libsasl2.so.2 (0x00007efc2b8aa000)
    libssl.so.1.1 => /usr/lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007efc2b817000)
    libcrypto.so.1.1 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007efc2b541000)
    libicuuc.so.66 => /usr/lib/x86_64-linux-gnu/libicuuc.so.66 (0x00007efc2b359000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007efc2b336000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007efc2b144000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007efc2af62000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007efc2af47000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007efc2af41000)
    libicudata.so.66 => /usr/lib/x86_64-linux-gnu/libicudata.so.66 (0x00007efc2947e000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007efc2932f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007efc2bbf0000)

The "IP address mismatch" error suggests that the certificate is actually being properly checked by OpenSSL and the root issue is likely an incorrect certificate configuration. You should also be able to verify the certificate directly using the openssl verify command and the -verify_ip <ip> and -verify_hostname <hostname> options. That would help you debug the certificate issue independent of the PHP driver (and MongoDB).

jmikola commented 2 years ago

Note: I restored the original bug report contents since this may be relevant to other users that come across the same error message down the line.