I am trying to learn how to implement replication in mongodb.
I have gone through the mongodb docs on the same topic and I understand most of it. However I do not really understand everything about ip binding
According to the docs the bindip is
The hostnames and/or IP addresses and/or full Unix domain socket paths
on which mongos or mongod should listen for client connections.
According to the same docs net.port is:
The TCP port on which the MongoDB instance listens for client
connections.
I can see the differences from the two definitions and I understand net.port well enough. But I do not understand what net.bindIp really is and how it works. So here are my questions
What is the difference between socket paths and TCP ports in regard to mongodb listening for client connections?
The docs say that when net.bindIpAll is set to true: "the mongos or mongod instance binds to all IPv4 addresses (i.e. 0.0.0.0)." Where do this "IPv4 addresses" come from? Why are they many? What is the advantage of binding to all of them?
Why not just use port to access my mongodb instance why do I need bind an ip address?
in MongoDB the configuration item net.bindIp allows the administrator to specify which network adapter the MongoDB process should listen for traffic on (by IP Address). For a multi-homed system (multiple network cards) traffic can be managed by specifying the IP Address related to a specific network card for both performance and security. If the IP address 0.0.0.0 is specified then all network adapters will be used. To bind to all adapters using IPv6 then specify ::,0.0.0.0 instead. See https://docs.mongodb.com/manual/core/security-mongodb-configuration/ for details.
The advice I have always received is to NEVER use a hostname or DNS name, but instead ALWAYS use an IP Address.
Related
Obviously I could listen on a particular IP address, but is it possible to listen on a particular hostname? Specifically, if example1.com and example2.com both point to my server with IP address (say) 12.34.56.78, is it possible to proxy connections to example1.com:5432 to my postgres db, but have connections to example2.com:5432 be rejected?
I have a feeling the hostname is not passed in the initial connection, so it would be impossible to do what can be done with HTTP(S) (e.g. Nginx server block, Caddy, etc.).
No, that is not possible. The database server never sees the host name the client used. Domain Name Service (DNS) resolution of a host name to an IP address has to happen before the server can be contacted.
You will have to use two different IP addresses, for example by defining a second, virtual IP address for the server. You don't need to have a second network card.
(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.
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 has bind ip but it is not so practical due to when new server add, it need shutdown db and add the new server ip into bind ip list and restart db. This is unacceptable because all other servers need to relaunch either.
In almost all deployment, servers machine and db machine are in same LAN. So can mongodb be configured as only accept ranges of ip of [172.16.0.0 - 172.31.255.255], [192.168.0.0 - 192.168.255.255], [10.0.0.0 - 10.255.255.255]?
These 3 ranges ip is LAN ip
The bind_ip configuration value only determines which IP address(es) your MongoDB server is listening to. It does not control access from remote IPs -- that is the job of a firewall.
The address ranges you have listed as requiring remote access are all private IP address space which means these networks are not directly reachable/routable outside your LAN. Assuming you can route traffic between your private networks you should not need to bind to multiple IP addresses.
Given you are allowing access from a broad range of IP addresses, you should also read the Security section of the MongoDB manual (in particular, the Security Checklist and tutorial on enabling Access Control).
bindIp can accept multiple comma separated values. See the "Security considerations" section Here
Other than that you might want to consider configuring your firewall, maybe iptables if it runs on Linux machine.
Hope this helps
I just started to read some binding documentation for Apache HTTP Server. And the very first line "By default, it listens to all addresses on the machine.", I found this statement very confusing. What does it mean to be "listening on all addresses"? Definitely they are not going to open all 64000 ports to listen. What are they trying to convey from this?
In this context, address would refer to IP addresses, not ports. It doesn't listen on all ports, it binds (by default) and listens on all IP addresses on the host machine.