MongoDB Replica set with external addresses - mongodb

Here is my problem. Mongodb works perfectly on my debian 8 server, but I want to do a replica set with external addresses... Here is my problem :
- I have two VPS on a different network
- I followed a tutorial on internet but I have an error message "either all host names in a replica set configuration must be localhost"
Here is a part of my mongodb config :
net:
port: 27017
bindIp: 51.X.X.1, 167.X.X.4
I didn't bind any localhost address. What could I do ? Do I have do do something special to make it works ?
Best Regards

The error message suggests your replica set config includes a localhost address, which was likely added by the default config in rs.initiate() if you didn't explicitly specify localhost anywhere.
You can check the output of rs.conf() to review the current replicate set configuration. Since you want to specify a public hostname I would include your desired config for rs.initiate() rather than relying on the defaults when you initiate the replica set. I'd also recommend following the tutorials in the MongoDB documentation for your server version, as third party tutorials may be outdated or miss important details.
If you want to correct your existing configuration, you could copy the the current replica set config as reported by rs.conf(), edit the hostname or IP address, and then pass the updated configuration document to rs.reconfig().
NOTE: before binding to external IPs, please review the MongoDB Security Checklist and ensure you have configured appropriate security measures like access control, authentication, network encryption (TLS/SSL), and firewall rules. Ideally you would have a VPN/VPC for private communication between your replica set members rather than directly using public networks.

Related

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
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:
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".)
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.

AWS RDS Postgresql Pgadmin - Server doesn't listen

I followed the aws tutorial found here.
Everything went smoothly up until connecting to the postgresql instance via pgadmin.
I entered the appropriate user/pw info and copy/pasted the address of the db appropriately.
The port is indeed 5432 on my aws dashboard.
I am receiving the following error message:
Server doesn't listen
The server doesn't accept connections: the connection library reports
could not connect to server: Operation timed out Is the server running on host "my_database_name.some_stuff.us-west-2.rds.amazonaws.com" (52.10.228.18) and accepting TCP/IP connections on port 5432?
If you encounter this message, please check if the server you're trying to contact is actually running PostgreSQL on the given port. Test if you have network connectivity from your client to the server host using ping or equivalent tools. Is your network / VPN / SSH tunnel / firewall configured correctly?
For security reasons, PostgreSQL does not listen on all available IP addresses on the server machine initially. In order to access the server over the network, you need to enable listening on the address first.
For PostgreSQL servers starting with version 8.0, this is controlled using the "listen_addresses" parameter in the postgresql.conf file. Here, you can enter a list of IP addresses the server should listen on, or simply use '*' to listen on all available IP addresses. For earlier servers (Version 7.3 or 7.4), you'll need to set the "tcpip_socket" parameter to 'true'.
You can use the postgresql.conf editor that is built into pgAdmin III to edit the postgresql.conf configuration file. After changing this file, you need to restart the server process to make the setting effective.
If you double-checked your configuration but still get this error message, it's still unlikely that you encounter a fatal PostgreSQL misbehaviour. You probably have some low level network connectivity problems (e.g. firewall configuration). Please check this thoroughly before reporting a bug to the PostgreSQL community.
Step 1
You are getting the same dialog I was seeing above. Crap!
Step 2
Go to your RDS instances
Step 3
Go to your security groups
Step 4
If your account was like mine you see this text:
Your account does not support the EC2-Classic Platform in this region.
DB Security Groups are only needed when the EC2-Classic Platform is supported.
Instead, use VPC Security Groups to control access to your DB Instances.
Go to the EC2 Console to view and manage your VPC Security Groups.
For more information, see AWS Documentation on Supported Platforms and Using RDS in VPC.
Step 5 Go back and check your RDS security group name (RDS->instances right click your instance). You will see something like Security GroupsList of VPC Security Groups associated with this DB Instance.
You will see something like:
default (sg-********) ( active )
Step 6 In your VPC security groups find your sg-******** that matches your database. Right click that. Edit inbound/outbound rules to add postgresql.
Try to connect again.
This solved my problem.
If this does not solve your problem I am very sorry, but I hope this documentation brings me some debugging karma.
go to AWS services in security group click on the security group id . from the "actions" button click on "edit inbound roles" and then change the "source" to "my ip"

What does the --bindip configuration option in mongodb do?

Here is the mongodb documentation https://docs.mongodb.com/manual/reference/configuration-options/ it specifies that
The IP address that mongos or mongod binds to in order to listen for
connections from applications. You may attach mongos or mongod to any
interface. When attaching mongos or mongod to a publicly accessible
interface, ensure that you have implemented proper authentication and
firewall restrictions to protect the integrity of your database.
To bind to multiple IP addresses, enter a list of comma separated
values.
and that
127.0.0.1. is the default configuration
I'm clueless when it comes to networking so I wanted to know if someone could explain to me what this means in a more comprehensive way. Also, what would it mean if I were to change this? Why would I want to bind multiple IPs? and finally if anyone has a clue, why is 127.0.0.1 the default option?
Edit:
(You can skip this edit part)
Some of the motivation behind this question lies in getting these warnings while trying to run mongodb on docker:
2016-05-22T05:36:12.478+0000 I CONTROL [initandlisten] ** WARNING: Insecure configuration, access control is not enabled and no --bind_ip has been specified.
2016-05-22T05:36:12.478+0000 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted,
2016-05-22T05:36:12.478+0000 I CONTROL [initandlisten] ** and the server listens on all available network interfaces.
and also some issues where I'd get this error
2016-05-20T01:04:18.012+0000 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2016-05-20T01:04:18.018+0000 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) ok
(more on that here if you are curious https://dba.stackexchange.com/questions/139075/replica-set-in-mongodb-using-docker-primary-has-error-and-stops-being-primary-w/139145#139145 but this issue is not the topic of this post!)
On bindIp
127.0.0.1 by convention is the IP address of localhost and is bound to the loopback interface, which is only accessible from the same machine.
Using this address as default is best practice, since doing so makes it impossible to accidentally expose a service to the public. You have to make the conscious choice to change the bind IP to make your service publicly available. Which you should only do after you made sure that you took proper security measures.
Note This is very simplified, skipping advanced topics
Typically, a machine has the loopback interface and one or more "real" network interfaces.
Say you have one network interface which is "internal" (only accessible by your application servers, since you put them into the same network) and you have one network interface which is "external" (reachable via the public internet for maintenance purposes). Now, if you would bind your MongoDB instance to all interfaces (you would use the IP address 0.0.0.0 to do that), your MongoDB instance would be accessible from the public internet – hardly a desired situation. Attackers could try to brute force your passwords and may eventually get access to your MongoDB instance. Better to prevent any access from the public internet at all.
What you would rather want to have that your MongoDB instance is accessible for your application servers and from the machine it runs on. So you would bind MongoDB to both the loopback interface's IP (127.0.0.1) and the IP of the private network, which in general would be one of
the range from 10.0.0.0 to 10.255.255.255
the range from 172.16.0.0 to 172.31.255.255
the range from 192.168.0.0 to 192.168.255.255
Let us take our example and say both the application servers and the MongoDB instance are in a private network in the range 192.168.X.X and you have given the MongoDB instance the IP address 192.168.0.1. So you would want to have your MongoDB instance be accessible via 192.168.0.1 so that the application servers can talk to it and via 127.0.0.1 to use the administration tools from the machine MongoDB runs on effortlessly.
So with the YAML configuration syntax, you would pass multiple IPs
NOTE do not add space between commas on multiple IPs
# WARNING!!! WARNING!!! WARNING!!!
# DO NOT DO THIS UNLESS YOU HAVE CLIENT AUTHENTICATION ENABLED
# (or you really, really, really know what you are doing)
net:
bindIp: 127.0.0.1,192.168.0.1
On the warnings
In short, this is MongoDBs way of saying:
Mate, you have two problems: you have not configured security yet and your MongoDB instance is only accessible from the local machine. The former is not as severe because of the latter. But you really should configure security before you bind the MongoDB instance to other IPs than "localhost"!
There is sort of an implied "Unless you really know what you are doing!", because iirc, the warning vanishes if you either activate client authentication or change the bindIp.
In my case i change bindIp to 0.0.0.0 in /etc/mongod.conf
sudo nano /etc/mongod.conf
# network interfaces
net:
port: 27017
bindIp: 0.0.0.0

MongoDB - Prevent unauthorized user from opening console

Trying to set up authorization in my development cluster, I couldn't prevent users from opening a console to my mongods.
I have enabled authorization in the config file:
secutiry:
authorization: enabled
And have created an admin user with the userAdminAnyDatabase role.
Yet, when connecting unauthorized to this server from another machine, I can enter the console.
I do get permission error when trying to issue commands, but I would like to know if there's any way of preventing the console from opening - getting the permission error earlier.
If you only need to access your MongoDB deployment from applications running on the same server you can use the bind_ip configuration option to control the network interface(s) that MongoDB processes listen to. By default this should already be set to '127.0.0.1' (localhost) in packaged versions of MongoDB 2.6+.
If you want to have the server listening to a more public network interface (eg. local LAN) and want to prevent remote connections entirely, you can limit source IP access via your firewall configuration.
The Network Security Tutorials in the MongoDB manual include examples that should be useful as a starting point:
Configure Linux iptables Firewall for MongoDB
Configure Windows netsh Firewall for MongoDB
If users/applications might authenticate from those remote IPs, you can't prevent them from opening a console connection (with no permissions). This is similar to how other services (sshd, apache, etc) work with authentication: step 1 is to establish a connection and step 2 authenticates.
For more information on MongoDB best practices, please refer to the Security section in the manual.

Clarification on MongoDB bind_ip Flag

I was reading around the MongoDb documentation and I noticed a bind_ip flag you can set for your mongod instance.
From what I gathered after reading, it appears as though you can use this in your configuration file to make MongoDB only respond from connections from the specific IP address(es).
Digging around on the internet to get more information it would appear as though it doesn't do what I expect it to (check last comment). It may be old/ inaccurate though, it is a few years old.
So am I right? Does the bind_ip limit what external IP's can connect to the DB?
bind_ip does not put a limit on external IP addresses. It will bind your mongod instance to a specific network interface on the machine it is running on.
So for example if you had a server in which there were 2 network cards, one which interfaced with a private internal network and a second which interfaced with a public, less secure network. You could bind mongod to the private card/interface so that it would only accept connections across your private network.