3

I've set up self-signed certs and SSL on my mongo database, according to several articles, the mongodb.org manual, some dba.stackexchange.com questions, and various tutorials.

So, I run an instance of mongodb with the following command (or the config file):

mongod --sslMode requireSSL --sslPEMKeyFile ./selfsignsec/mongodb.pem --sslCAFile ./selfsignsec/ca.pem 

And it looks like everything is fine:

[datetime].129-0700 I CONTROL  [initandlisten] MongoDB starting : pid=42188 port=27017 dbpath=/data/db
...
[datetime].129-0700 I CONTROL  [initandlisten] OpenSSL version: OpenSSL 1.0.2 22 Jan 2015
...
[datetime].129-0700 I CONTROL  [initandlisten] options: { net: { ssl: { CAFile: "./selfsignsec/dbclient.pem", PEMKeyFile: "./selfsignsec/mongodb.pem", mode: "requireSSL" } } }
...
[datetime].178-0700 I NETWORK  [initandlisten] waiting for connections on port 27017 ssl

Then, I've connected to that instance with a client certificate using this code:

...

var https = require('https'),
    fs = require('fs'); 
...

app.use(methodOverride('X-HTTP-Method-Override')); //ability to use put, etc.
...

// For the moment, allow just about everything for CORS origin, methods, and headers
...

// http://docs.mongodb.org/manual/core/authentication/
var config = {
                mongo: {
                    host: "localhost",
                    port: 27017,
                    db: "test",
                    ssl: true
                   }
                };

var dbstring = "mongodb://" + config.mongo.host + ":" + config.mongo.port +
"/" + config.mongo.db;

var dboptions = {
    server: {
            ssl: true,
            sslCert: fs.readFileSync('./selfsignsec/my-client.crt.pem'),
            sslKey: fs.readFileSync('./selfsignsec/my-client.key.pem')
        }
    };

mongoose.connect(dbstring, dboptions);
mongoose.connection.once('open', function() {

    app.models = require('./models/index');
    var routes = require('./routes');

    _.each(routes, function(controller, route) {
        // declaring controllers & pass in the app & route
        app.use(route, controller(app, route));
    }); 

    console.log('Secure Express server listening on port 27017...');
    app.listen(27017);

});

And the server log looks good:

[datetime].166-0700 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:57591 #1 (1 connection now open)
...

But, in the browser, when I go to https://localhost:27017/somecollection, the GET fails. I don't get a connection (ERR_CONNECTION_CLOSED).

When I just use http, I get the json collection back!

Another time, I used an admin username & password, and got:

[datetime].347-0700 I ACCESS   [conn43] Successfully authenticated as principal adminrole on test

But the browser requests & responses were the same: no response on https and full collection on http request.

If ssl is set on mongod and mongo client, how come http is returning results?

TL;DR:

BTW, if I don't pass any ssl values in the client code, I do get what I expected from the server:

AssertionException handling request, closing client connection: 17189 The server is configured to only allow SSL connections

And if I pass in a bad cert, I do get expected:

no SSL certificate provided by peer; connection rejected
end connection 127.0.0.1:55829 (0 connections now open)

Result of incognito requests were the same as above.

Result of netstat -a | grep 27017:

tcp46      0      0  *.27017                *.*                    LISTEN     
tcp4       0      0  localhost.27017        localhost.56297        ESTABLISHED
tcp4       0      0  localhost.56297        localhost.27017        ESTABLISHED
tcp4       0      0  localhost.27017        localhost.56296        ESTABLISHED
tcp4       0      0  localhost.56296        localhost.27017        ESTABLISHED
tcp4       0      0  localhost.27017        localhost.56295        ESTABLISHED
tcp4       0      0  localhost.56295        localhost.27017        ESTABLISHED
tcp4       0      0  localhost.27017        localhost.56294        ESTABLISHED
tcp4       0      0  localhost.56294        localhost.27017        ESTABLISHED
tcp4       0      0  localhost.27017        localhost.56293        ESTABLISHED
tcp4       0      0  localhost.56293        localhost.27017        ESTABLISHED
tcp4       0      0  *.27017                *.*                    LISTEN     
704e9db9a444912b stream      0      0 704e9db9b79bb6c3                0                0                0 /tmp/mongodb-27017.sock

Result of openssl s_client -connect localhost:27017 -tls1 -servername localhost | openssl x509 -text -noout:

depth=1 C = US, ST = CA, L = SanFran, O = Local Signing Authority, CN = localhost
verify error:num=19:self signed certificate in certificate chain
read:errno=0
Certificate:
Data:
    Version: 1 (0x0)
    Serial Number: 13550121380367150794 (0xbc0bb39a9435aeca)
Signature Algorithm: sha256WithRSAEncryption
    Issuer: C=US, ST=CA, L=SanFran, O=Local Signing Authority, CN=localhost
    Validity
        Not Before: May 21 19:42:47 2015 GMT
        Not After : Oct  2 19:42:47 2016 GMT
    Subject: C=US, ST=CA, L=SanFran, O=Local Signing Authority, CN=127.0.0.1
    Subject Public Key Info:
        Public Key Algorithm: rsaEncryption
            Public-Key: (2048 bit)
            Modulus:
                00:ba:0e:a4:0d:23:6c:a7:01:a9:e7:92:0e:9e:15:
                1c:83:5d:91:32:7a:fb:6e:6f:da:ad:70:24:ef:a0:
                4d:83:24:a1:f0:d0:6a:40:81:12:aa:f9:40:6d:53:
                b3:d6:c1:24:b4:c9:07:a2:e9:5a:80:7a:51:30:71:
                9c:e2:ee:fc:ce:d7:b1:2c:e2:91:40:94:9d:43:50:
                08:33:67:cb:58:66:0d:c7:13:cc:45:20:e7:ef:70:
                c4:8a:26:64:b5:af:4e:f8:c4:70:d8:7e:17:21:40:
                4f:12:5b:35:71:b0:51:87:6f:12:4e:06:99:12:ac:
                0e:4e:8e:7d:9c:6e:41:6f:d8:ca:93:77:9a:ee:60:
                7e:9d:86:c1:6d:df:7c:a6:3a:71:cd:73:d8:8e:d1:
                d8:61:f9:48:e5:02:44:10:31:94:58:1a:d2:75:a7:
                14:83:b5:ad:b9:2e:ae:7a:65:af:8d:5d:31:65:fd:
                c5:1f:e1:4f:f2:fb:80:df:08:25:64:5b:a6:c2:9d:
                aa:10:8b:25:2e:fc:75:65:82:ea:4f:5c:18:68:21:
                2b:0e:00:b8:57:e9:fb:14:67:18:14:ae:e0:c5:e6:
                d9:5d:a1:df:6e:9d:27:0b:72:bd:33:e2:e8:a6:b3:
                e8:a1:94:cc:ec:78:15:1b:37:b2:23:57:7c:d6:65:
                c8:71
            Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
     56:f6:ca:05:be:4a:ab:8d:94:8b:4e:7a:51:e2:8c:ed:d3:0e:
     16:ac:68:61:eb:5b:d0:c3:e5:96:f2:50:12:f3:a8:10:14:c8:
     9f:63:cc:f3:d3:b9:c2:71:8b:ac:7a:9c:9e:61:8d:09:26:4c:
     6f:0d:30:2d:87:e2:e8:aa:77:f0:33:25:51:cb:67:d9:99:a5:
     3c:cf:3a:3d:27:63:cd:3e:42:50:da:d6:68:a0:0a:c4:78:ad:
     aa:a5:b1:93:8f:01:d0:70:72:5e:c0:19:5a:43:94:ba:65:35:
     aa:0d:8b:da:b5:16:50:f5:bc:8f:cf:80:c9:f9:53:67:eb:68:
     a2:0b:60:11:a0:c0:04:ef:47:5c:8b:e6:28:09:37:b9:43:bb:
     0f:8f:1d:28:2a:d7:aa:46:6e:7d:32:64:44:70:74:c0:84:bd:
     3e:82:87:85:68:51:c1:ba:44:d1:b3:29:bd:78:d8:80:63:59:
     40:a5:dd:97:a1:a5:35:7c:5d:cb:11:1d:39:63:08:15:f5:00:
     7c:6f:85:a8:df:9b:26:aa:66:a4:8a:81:f9:7a:ea:65:f5:03:
     89:0b:ef:49:67:60:79:c5:82:39:eb:b3:88:9e:7b:b9:f9:6e:
     c1:2c:30:19:23:d5:c8:3a:4e:c6:2a:33:c0:5a:5f:74:04:90:
     91:07:b3:f2
theship
  • 75
  • 1
  • 13

1 Answers1

0

You have two problems. First is the self-signed server certificate; and second is the DNS names in the CN. You have a third related problem that will go away once you fix the first two problems.

For the first problem, self-signed certificate, see How do you sign Certificate Signing Request with your Certification Authority?. Browser have actively moved against self-signed certificates.

For the second problem, DNS names in the CN, see How to create a self-signed certificate with openssl?. This is another browser requirement. DNS names must be put in the Subject Alternate Name (SAN), and not the Common Name (CN).


But, in the browser, when I go to https://localhost:27017/somecollection, the GET fails.

A related problem is the Subject's CN is CN=127.0.0.1. 127.0.0.1 is not localhost, so the browser thinks its a different origin. Even other user agents (non-browsers) will fail for this one. Non-browsers include cURL and GNU's Wget.

This problem will go away once you place all the DNS names in the SAN. The DNS names include 127.0.0.1, localhost, john-dev-machine, and john-dev-machine.example.com.


You can see if the server is actually serving over HTTPS with:

echo -e "GET /somecollection HTTP/1.1\r\nHost:localhost\r\n\r\n" | \
  openssl s_client -connect localhost:27017 -tls1 -servername localhost -ign_eof

You should see raw HTML returned. You can then press CTRL+C to exit.

OpenSSL does not perform the host name checks (the programmer must do it manually) or enforce DNS name policy (in the CN or SAN). So it will work if the server is serving pages on that port over HTTPS.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • Thanks much, jww! I will clear all this up. Also, Stephen pointed out on the mongodb-user google group that I was confusing the SSL configuration between my application & MongoDB with configuring SSL between the browser and my app. This is the (app <=> MongoDB) part. When I do create the browser-to-app connection, via https.createServer() , I shouldn't listen on the same port as the MongDB server! – theship May 22 '15 at 17:39