Problems connecting to mongod from a different machine, using X509

I have a mongod daemon running on one machine.

I can confirm it, by running these two commands:

$ ps -ef | grep mongod
ubuntu      4908       1  5 07:44 ?        00:00:03 mongod --tlsMode requireTLS --tlsCertificateKeyFile Server2.cert --tlsCAFile RootCA.pem --auth --dbpath /mnt/mongoDB-One/DB_X509 --logpath /mnt/mongoDB-One/DB_X509/mongod.log --fork --bind_ip 192.168.1.2
ubuntu      4951    3223  0 07:45 pts/0    00:00:00 grep --color=auto mongod
$ 
$ sudo netstat -tulpn | grep mongod
tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      4612/mongod         
$ 

While being on the same machine I can launch mongo shell, using one of these two commands:

$ mongo --tls --host localhost --tlsCertificateKeyFile Client.cert --tlsCAFile RootCA.pem
$ mongo --tls --host 127.0.0.1 --tlsCertificateKeyFile Client.cert --tlsCAFile RootCA.pem

But from a different machine, the following is not working:

$ mongo --tls --host 192.168.1.2 --tlsCertificateKeyFile Client.cert --tlsCAFile RootCA.pem --authenticationDatabase '$external' --authenticationMechanism MONGODB-X509
MongoDB shell version v4.2.0
connecting to: mongodb://192.168.1.2:27017/?authMechanism=MONGODB-X509&authSource=%24external&compressors=disabled&gssapiServiceName=mongodb
2021-01-21T16:26:42.690+0900 E  QUERY    [js] Error: couldn't connect to server 192.168.1.2:27017, connection attempt failed: SocketException: Error connecting to 192.168.1.2:27017 :: caused by :: Connection refused :
connect@src/mongo/shell/mongo.js:341:17
@(connect):3:6
2021-01-21T16:26:42.693+0900 F  -        [main] exception: connect failed
2021-01-21T16:26:42.693+0900 E  -        [main] exiting with code 1
$ 

Why could that be?

Some more information which may be useful:

The server certificate has been created using these 2 commands.

$ openssl req -new -newkey rsa:4096 -nodes -keyout Server.key.pem -out Server.req.pem -subj /C=US/ST=CA/O=ServerCA/CN=localhost
$ openssl x509 -req -days 365 -in Server.req.pem -CA IntermedCA.pem -CAkey IntermedCA.key.pem -set_serial 01 -out Server.pem -extfile X509_v3.ext

With X509_v3.ext being :

$ cat X509_v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.1 = 127.0.0.1
IP.2 = 192.168.1.2
$

Hi @Michel_Bouchet

The mongo server is only listening on 127.0.0.1 that is the loopback ip address only accessible on that host.

By default mongod only binds to localhost for security reasons.

Here is what you need:
https://docs.mongodb.com/manual/core/security-mongodb-configuration/#ip-binding

OK. Though I was not aware of this security limitation, what you write is also my understanding but it still does not work.

I launch mongod with this command:

$ mongod --tlsMode requireTLS --tlsCertificateKeyFile Server.cert --tlsCAFile RootCA.pem --auth --dbpath /mnt/mongoDB-One/DB_X509 --logpath /mnt/mongoDB-One/DB_X509/mongod.log --fork --bind_ip 127.0.0.1,192.168.1.2

and I can confirm:

$ ps -ef | grep mongod
ubuntu      2868       1  1 01:45 ?        00:00:10 mongod --tlsMode requireTLS --tlsCertificateKeyFile Server.cert --tlsCAFile RootCA.pem --auth --dbpath /mnt/mongoDB-One/DB_X509 --logpath /mnt/mongoDB-One/DB_X509/mongod.log --fork --bind_ip 127.0.0.1,192.168.1.2
ubuntu      3031    2608  0 01:54 pts/0    00:00:00 grep --color=auto mongod
$ 

Then I can fire up mongo shell locally using any of the following:

$ mongo --tls --host localhost --tlsCertificateKeyFile Client.cert --tlsCAFile RootCA.pem
$ mongo --tls --host 127.0.0.1 --tlsCertificateKeyFile Client.cert --tlsCAFile RootCA.pem
$ mongo --tls --host 192.168.1.2 --tlsCertificateKeyFile Client.cert --tlsCAFile RootCA.pem
$ mongo --tls --host localhost --tlsCertificateKeyFile Client.cert --tlsCAFile RootCA.pem --authenticationDatabase '$external' --authenticationMechanism MONGODB-X509
$ mongo --tls --host 127.0.0.1 --tlsCertificateKeyFile Client.cert --tlsCAFile RootCA.pem --authenticationDatabase '$external' --authenticationMechanism MONGODB-X509
$ mongo --tls --host 192.168.1.2 --tlsCertificateKeyFile Client.cert --tlsCAFile RootCA.pem --authenticationDatabase '$external' --authenticationMechanism MONGODB-X509

But I expect the last command to also work from a different computer and it doesn’t. Can you see why?

This is how it goes:

$ mongo --tls --host 192.168.1.2 --tlsCertificateKeyFile Client.cert --tlsCAFile RootCA.pem  --authenticationDatabase '$external' --authenticationMechanism MONGODB-X509
MongoDB shell version v4.2.0
connecting to: mongodb://192.168.1.2:27017/?authMechanism=MONGODB-X509&authSource=%24external&compressors=disabled&gssapiServiceName=mongodb
2021-01-22T11:12:02.292+0900 E  NETWORK  [js] SSL peer certificate validation failed: Certificate trust failure: Invalid Extended Key Usage for policy; connection rejected
2021-01-22T11:12:02.293+0900 E  QUERY    [js] Error: couldn't connect to server 192.168.1.2:27017, connection attempt failed: SSLHandshakeFailed: SSL peer certificate validation failed: Certificate trust failure: Invalid Extended Key Usage for policy; connection rejected :
connect@src/mongo/shell/mongo.js:341:17
@(connect):3:6
2021-01-22T11:12:02.296+0900 F  -        [main] exception: connect failed
2021-01-22T11:12:02.296+0900 E  -        [main] exiting with code 1
$

I’m not sure why this would work on the mongod host but not remotely, maybe the tls implementation? What host OS is on the remote client.

The remote client is a MacBook Air running macOS Catalina Version 10.15.7.

As per mongodb documentation to use x.509

  • Client certificates must contain the following fields

keyUsage = digitalSignature extendedKeyUsage = clientAuth
Could this be the issue? As error says something about EKU

1 Like

Are you able to share the X509 extension section from.

openssl x509 -in Server.cert -noout -text

This is it:

$ openssl x509 -in Server.cert -noout -text
Certificate:
  Data:
    Version: 3 (0x2)
    Serial Number: 1 (0x1)
    Signature Algorithm: sha256WithRSAEncryption
    Issuer: C = US, ST = DC, O = IntermedCA, CN = echo
    Validity
      Not Before: Jan 22 03:21:07 2021 GMT
      Not After : Jan 22 03:21:07 2022 GMT
    Subject: C = US, ST = CA, O = ServerCA, CN = echo
    Subject Public Key Info:
      Public Key Algorithm: rsaEncryption
        RSA Public-Key: (4096 bit)
        Modulus:
            00:f5:b8:9e:a3:6c:91:0c:b6:43:af:51:c1:13:e4:
            .............
        Exponent: 65537 (0x10001)
    X509v3 extensions:
      X509v3 Authority Key Identifier: 
        keyid:82:E7:CC:17:6E:A3:9A:53:AC:5B:E1:82:08:ED:52:D3:FC:EA:F1:24
        DirName:/C=US/ST=NY/O=RootCA
        serial:01

      X509v3 Basic Constraints: 
        CA:FALSE
      X509v3 Key Usage: 
        Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment
      X509v3 Subject Alternative Name: 
        DNS:localhost, IP Address:127.0.0.1, IP Address:192.168.1.2
  Signature Algorithm: sha256WithRSAEncryption
     81:b3:2b:ac:f3:46:fc:85:28:ab:4e:16:17:d8:f1:25:da:71:
     .............
$

I noticed this issue is not appearing on other clients. And adding keyUsage and extendedKeyUsage as mentioned by Ramachandra_Tummala doesn’t seem to make any difference, as much as I’ve tried.

In doing what @Ramachandra_Tummala suggested the the other Extended Key usage is missing:
extendedKeyUsage = serverAuth, clientAuth

There is a good set of examples in the security appendix, hopefully that can help.

I think the only thing I would change is in the Appendix B, Section B, Step 4:
cat mongodb-test-server1.crt mongodb-test-server1.key > test-server1.pem
to
cat mongodb-test-server1.crt mongodb-test-ia.crt mongodb-test-server1.key > test-server1.pem

What platforms are the other clients on?

The other clients are on Ubuntu and Debian.

Yes, it finally works. This time I added:

extendedKeyUsage = serverAuth,clientAuth

both to the server and to the client certificates.

And I can connect also from my Mac running macOS Catalina.

Thanks again for the precious tips!

1 Like

Trying out and testing a bit more seems to show that, only having this on the server certificate is enough:

extendedKeyUsage = serverAuth

1 Like

Hi @Michel_Bouchet

Glad you got there!