Search code examples
mongodbamazon-ec2meanjsbitnami

Why does MongoDB port 27017 need to be opened in AWS EC2 Security Group?


(I've searched SO, AWS support and more widely without success.)

I've just successfully deployed a MEANjs application to a Bitnami MEAN instance on EC2, following Ahmed Haque's excellent tutorial on scotch.io. As part of the tutorial/deployment I altered the AWS Security Group to include port 27017 for MongoDB traffic. The CIDR notation for the port 27017 was 0.0.0.0/0 - which AFAIK means 'allow access from any IP address'.

Question: Why does MongoDB port 27017 need to be opened in AWS EC2 Security Group for a 'production' type environment? Surely this is directly exposing the DB to the Internet. The only thing that should be talking to Mongo is the "/server/api" code, which is running on the same instance - and so shouldn't need the port opening.

If I change the Security Group rule for port 27017 by closing off 27017, changing the source to: localhost, the internal IP address, the public IP address, or hack a CIDR to be equivalent to any of those - then the web app hangs (static content returns but no responses to db backed api calls). Changing the SG rule back to 0.0.0.0/0 almost immediately 'fixes' the hang.

All is otherwise sweet with my install. I've closed port 3000 (the node app) in the Security Group and am using Apache to proxy port 80 traffic to port 3000. Set up like this, port 3000 does not need to be open in the Security Group; to me this implies that on-instance traffic doesn't need ports to be externally exposed - so how come that's not true of the Mongo port?

I cant see anything in the '/client' code which is talking direct to Mongo.

What am I missing?

Thanks in advance - John


Solution

  • OK, after further investigation and overnight/red wine reflection I think I have an answer for those learners like me following the above tutorial (or similar). Following the Agile principle that 'done' means 'working code in a production environment' I was trying to understand the last 5 meters as a developer trying to get code working in a representative production environment (which wouldn't have unnecessary ports open) - this answer is written from that perspective. (Builds welcome from wiser readers.)

    What's Happening

    The step in the tutorial which (a) changed the Mongo bind IP address from 127.0.0.1 to 0.0.0.0, and (b) specifies a connection URL which uses the external IP address of the same instance, appears to have two effects:

    1. It makes the MongoDB on the instance you're configuring potentially available to other instances (0.0.0.0 tells Mongo to "listen on all available network interfaces".)
    2. It means that the IP traffic from your MEAN app /server component on the same instance will talk to Mongo as though it was coming from off-instance (even though it's on the same instance). Hence the Security Group needs to make port 27017 open to allow this traffic to flow. (This is the nub of the issue in terms of MEANjs stack component interaction.)

    Fix

    • On a single instance MEANjs server, if you change the Mongo bind IP address back to 127.0.0.1 and the Mongo connection url to be 127.0.0.1:27017 then you can close off port 27017 in the EC2 Security Group and the app still works.

    • To share one MongoDB across more than one MEANjs app server (without wanting to stray into serverfault territory):

      • Change the Mongo bind IP address to 0.0.0.0,
      • Use the private IP address of the Mongo server in other app/instance connection strings
      • Add a EC2 Security Group CIDR rule of private IP address/24, or private IP address/16 to allow access across instances in the specified internal IP address range.

    The above is developer 'hack', not a recommendation for good practice.