0

Recently I created a server with MongoDB preinstalled on a DigitalOcean droplet following these tutorials

It was my first time doing this. Today I received this email from DigitalOcean:

A recent network security scan suggests your Droplet droplet-name is running a MongoDB instance and that it may be unintentionally exposing data, or misconfigured to allow unauthorized access. MongoDB listens for traffic from everywhere on port 27107 and you can validate this report by attempting to connect to your MongoDB instance on via a simple telnet command: telnet xxx.xxx.xx.xx 27107 If the connection is successful you will receive output like the following, which will confirm that your service is visible to the public Internet

Trying xxx.xxx.xx.xx...
Connected to xxx.xxx.xx.xx.

Remediation of this issue will take just a few minutes and is relatively straightforward. You will need to open mongodb instance and run below command adding IP you want to connect from: sudo mongod --bind_ip localhost, ip-or-Associated-Hostname-you-connect-from

After connecting to my server, I tried sudo mongod --bind_ip localhost and sudo mongod --bind_ip xxx.xxx.xx.xx commands (xxx.xxx.xx.xx is my server IP, the one I have to put on ssh user@xxx.xxx.xx.xx command to connect to my server), but they didn't work, they threw me

I CONTROL  [main] Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'
I CONTROL  [initandlisten] MongoDB starting : pid=16339 port=27017 dbpath=/data/db 64-bit host=host-name
I CONTROL  [initandlisten] db version v4.0.3       
I CONTROL  [initandlisten] git version: xxxxxxxxxxxxxxxxxxxxx
I CONTROL  [initandlisten] OpenSSL version: OpenSSL 1.1.1  11 Sep 2018
I CONTROL  [initandlisten] allocator: tcmalloc     
I CONTROL  [initandlisten] modules: none
I CONTROL  [initandlisten] build environment:      
I CONTROL  [initandlisten]     distmod: ubuntu1804 
I CONTROL  [initandlisten]     distarch: x86_64    
I CONTROL  [initandlisten]     target_arch: x86_64 
I CONTROL  [initandlisten] options: { net: { bindIp: "localhost" } }
E STORAGE  [initandlisten] Failed to set up listener: SocketException: Address already in use
I CONTROL  [initandlisten] now exiting
I CONTROL  [initandlisten] shutting down with code:48

So I remembered my mongod.conf was:

net:
  port: 27017
  bindIp: 0.0.0.0

security:
  authorization: enabled

I changed the 0.0.0.0 to localhost,xxx.xxx.xx.xx, and now when I try to connect with telnet xxx.xxx.xx.xx 27107 (I didn't try this command before to check if the connection was successful, my bad) I receive

Connecting To xxx.xxx.xx.xx...Could not open connection to the host, on port 27107: Connect failed

My service is not visible to the public internet I guess (if I set again bindIp: 0.0.0.0 I get the same output)

But I noticed DigitalOcean email telnet command says 27107 and all my settings (and DigitalOcean docs) are based on port 27017. Is the email port wrong? If I put telnet xxx.xxx.xx.xx 27017 the output is Trying xxx.xxx.xx.xx... and then the console is totally cleaned (even the prompt), and the title bar is changed to Telnet xxx.xxx.xx.xx. If I press a key nothing happens, but after pressing any key many times the console backs as it was at the beginning. I don't know if the connection is successful or not.

If I check ufw status as root, the output is

To                         Action      From
--                         ------      ----
22/tcp                     LIMIT       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
27017                      ALLOW       Anywhere
OpenSSH                    ALLOW       Anywhere
22/tcp (v6)                LIMIT       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)
27017 (v6)                 ALLOW       Anywhere (v6)
OpenSSH (v6)               ALLOW       Anywhere (v6)

I think this is not good. If I try to connect to mongo on a Nodejs app running on my machine using mongoose with mongodb://xxx.xxx.xx.xx:27017 the connection is successful, but when I try to create a new document, it throws MongoServerError: command insert requires authentication which looks good but I'm not sure.

What am I doing wrong? I want to allow connections to Mongo only from my pc and my Nodejs app, deployed on DigitalOcean via App Platform (App Platform app doesn't have static IP address)

Thanks in advance

Fernando
  • 15
  • 6

1 Answers1

1

The advise from DigitalOcean is not very smart. There is no reason to run mongod as root. By running sudo mongod ... you ignore the settings in mongod.conf, which could be bad. From the log messages, it looks like you tried to start mongod while mongod service was already running. You can run mongod (with using the same port and/or dbPath) only once.

Now, regarding to your actual problem:

When you set net.bindIp: localhost (or --bind_ip localhost) then the mongod service is exposed only to the local machine, i.e. you cannot connect to the MongoDB from any external machine. This setting is typically used while maintenance work or when your MongoDB is accessed only from locally installed application - which seems to be your case.

When you set net.bindIpAll: true or net.bindIp: 0.0.0.0 (or according command line options), then the mongod service is exposed to external network, i.e. you can connect from external machine to your MongoDB - provided the access is permitted by firewall settings.

Setting net.bindIp: xxx.xxx.xx.xx is more or less the same and actually only useful if your computer has multiple network interfaces. And of course, it works only if the machine has a static IP-Address.

You enabled authentication, which is good. However, then must also connect with username/password *), either in connection string or with db.auth().

Note, you can (almost) always connect to a MongoDB without username/password. However, unless you are authenticated you can execute only harmless commands like db.help(), db.version(), db.listCommands(), etc. For other commands you get error command ... requires authentication as you saw it.

*) MongoDB also provides authentication via x.509 certificate, LDAP or Kerberos.

Update:

I missed your statement "I want to allow connections to Mongo only from my pc and my Nodejs app, deployed on DigitalOcean via App Platform"

In this case, you must expose the MongoDB to external, i.e. net.bindIpAll: true. When the MongoDB is visible public, then of course you must enable authentication. Which means you must connect with username/password. You should also use TLS/SSL secured connections.

Regarding firewall settings, it could be difficult. I guess, your PC does not have a static IP-Address. Thus the only option is 27017 ALLOW Anywhere. Maybe you know the range on IP-Addresses your PC can have. Then you can open the firewall only for this particular range.

Wernfried Domscheit
  • 54,457
  • 9
  • 76
  • 110
  • Thanks for your answer. So are my settings good? I have doubts about ufw settings (`27017 ALLOW Anywhere`). I also noticed DigitalOcean email telnet command says `27107` and all the MongoDB documentation on DigitalOcean says `27017`. Is it wrong? – Fernando Feb 26 '23 at 17:32
  • If I put telnet xxx.xxx.xx.xx 27017 looks like the connection is successfull, there's no output, but the console is cleaned. – Fernando Feb 26 '23 at 17:44
  • I suggest https://stackoverflow.com/questions/37839365/simple-http-tcp-health-check-for-mongodb/63790795#63790795 – Wernfried Domscheit Feb 26 '23 at 19:54
  • If you set `net.bindIp: localhost` then firewall setting `27017 ALLOW Anywhere` has no effect, because mongod service is exposed only to the local machine. But in general you should open only the ports which are actually needed, thus it's better to remove this rule. – Wernfried Domscheit Feb 26 '23 at 20:01
  • Default port for MongoDB is `27017`. Port 27107 seems to be a typo. Of course, in the end it is defined by your `net.port` setting. – Wernfried Domscheit Feb 26 '23 at 20:04
  • I used that curl and received the output `It looks like you are trying to access MongoDB over HTTP on the native driver port.`. But I'm still not sure if my MongoDB is secure, because of the telnet response (I updated the question to give a little more details about it, the update is just before the `ufw status`) – Fernando Feb 26 '23 at 20:14
  • Also I should remove both 27017 rules on ufw? Thanks – Fernando Feb 26 '23 at 20:21
  • Please see up update – Wernfried Domscheit Feb 27 '23 at 06:53
  • Thanks. I've looked into `mongod.conf` and `net.bindIp` is `0.0.0.0`, and I'm pretty sure the last time I've checked it was `localhost,xxx.xxx.xx.xx`, it's weird. Also my Nodejs app deployed on DigitalOcean was connected to mongo (using user and password URI) when the setting was `localhost,xxx.xxx.xx.xx` and everything was working. If I understood correctly, it shouldn't have worked, right? Sorry for so many questions – Fernando Feb 27 '23 at 16:56
  • When I understand your question correct, then everything was working fine. You only got a security alert from DigitalOcean. If you run your MongoDB with `authorization: enabled`, then everything is fine. As written, in order to increase security you may also use TLS/SSL certificates for connection or even better also for [authentication](https://www.mongodb.com/docs/manual/tutorial/configure-x509-client-authentication/). – Wernfried Domscheit Feb 27 '23 at 17:20
  • Yes, when I received the email everything was working fine, the `bindIp` was `0.0.0.0`, that was the reason of the alert I guess. And when I updated it to `localhost,xxx.xxx.xx.xx` everything kept working fine. The telnet response is what keeps me concerned. I will add TLS/SSL. Thanks so much. – Fernando Feb 28 '23 at 02:24