Docker on AWS ElasticBeanstalk: "host.docker.internal: host-gateway": Connection refused. Iptables issue? - linux

So I have a multicontainer project running on AWS ElasticBeanstalk (latest Docker platform).
The containers share the same bridge network since they need to be able to communicate with each other (ports 3000, 8080, 9090, 9100). But one of those containers needs to be able to communicate with the host too (ports 55113, 56113).
This is normally possible by just adding extra_hosts: "host.docker.internal:host-gateway" to that container and then using host.docker.internal instead of localhost inside the container, i.e. host.docker.internal:55113. I've successfully used it before on a Debian.
But this is not working on AWS ElasticBeanstalk, the connection is refused.
Am I doing something wrong? Is there any workaround?
AWS ElasticBeanstalk Platform:
Docker running on 64bit Amazon Linux 2/3.4.2
Host's Docker & Docker-Compose versions:
$ sudo docker --version
Docker version 20.10.4, build d3cb89e
$ sudo docker-compose --version
docker-compose version 1.29.2, build unknown
Project's docker-compose.yml: (showing only the relevant parts)
version: "3.9"
services:
prometheus:
image: prom/prometheus:v2.28.1
container_name: prometheus
ports:
- 9090:9090
extra_hosts:
- host.docker.internal:host-gateway # <-------- EXTRA HOST
networks:
default:
name: monitoring
Container debug:
$ sudo docker exec -it prometheus cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.1 host.docker.internal # <-------- the mapping is present
172.25.0.4 f01ffc6b2a8a
$ sudo docker exec -it prometheus wget host.docker.internal
Connecting to host.docker.internal (172.17.0.1:80)
wget: can't connect to remote host (172.17.0.1): Connection refused
$ sudo docker exec -it prometheus wget host.docker.internal:55113 # <-------- the port I want to reach
Connecting to host.docker.internal:55113 (172.17.0.1:55113)
wget: can't connect to remote host (172.17.0.1): Connection refused
Host's iptables (configured by AWS and/or Docker, I didn't edit it):
$ sudo iptables -S
-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o br-a8a58f19c627 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-a8a58f19c627 -j DOCKER
-A FORWARD -i br-a8a58f19c627 ! -o br-a8a58f19c627 -j ACCEPT
-A FORWARD -i br-a8a58f19c627 -o br-a8a58f19c627 -j ACCEPT
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.25.0.2/32 ! -i br-a8a58f19c627 -o br-a8a58f19c627 -p tcp -m tcp --dport 8080 -j ACCEPT
-A DOCKER -d 172.25.0.3/32 ! -i br-a8a58f19c627 -o br-a8a58f19c627 -p tcp -m tcp --dport 9100 -j ACCEPT
-A DOCKER -d 172.25.0.4/32 ! -i br-a8a58f19c627 -o br-a8a58f19c627 -p tcp -m tcp --dport 9090 -j ACCEPT
-A DOCKER -d 172.25.0.5/32 ! -i br-a8a58f19c627 -o br-a8a58f19c627 -p tcp -m tcp --dport 3000 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i br-a8a58f19c627 ! -o br-a8a58f19c627 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o br-a8a58f19c627 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
Host's open ports:
$ netstat -tuplen
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 0.0.0.0:9090 0.0.0.0:* LISTEN 0 200315 -
tcp 0 0 127.0.0.1:55113 0.0.0.0:* LISTEN 1000 119886 -
tcp 0 0 0.0.0.0:9100 0.0.0.0:* LISTEN 0 200280 -
tcp 0 0 127.0.0.1:22221 0.0.0.0:* LISTEN 1001 197452 -
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 0 14121 -
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 0 201081 -
tcp 0 0 127.0.0.1:56113 0.0.0.0:* LISTEN 1000 119890 -
tcp 0 0 127.0.0.1:38581 0.0.0.0:* LISTEN 0 20325 -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 18585 -
tcp 0 0 0.0.0.0:3000 0.0.0.0:* LISTEN 0 201164 -
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 0 16235 -
tcp6 0 0 ::1:55113 :::* LISTEN 1000 119885 -
tcp6 0 0 :::111 :::* LISTEN 0 14124 -
tcp6 0 0 ::1:56113 :::* LISTEN 1000 119889 -
tcp6 0 0 :::22 :::* LISTEN 0 18594 -
udp 0 0 0.0.0.0:68 0.0.0.0:* 0 15762 -
udp 0 0 0.0.0.0:111 0.0.0.0:* 0 14119 -
udp 0 0 127.0.0.1:323 0.0.0.0:* 0 14990 -
udp 0 0 0.0.0.0:979 0.0.0.0:* 0 14120 -
udp6 0 0 fe80::ed:19ff:fe84::546 :::* 0 16539 -
udp6 0 0 :::111 :::* 0 14122 -
udp6 0 0 ::1:323 :::* 0 14991 -
udp6 0 0 :::979 :::* 0 14123 -

I'm new in the field.
Your logs shows that your port is listening on localhost (127.0.0.1:56113) instead of all IPs (eg 0.0.0.0:8080).
In my case the port forward rule on the host machine has to be modified to -L0.0.0.0:<lport>:<ip>:<rport> .

Related

container port not reachable when iptables is enabled

Am using a port map for my container and opened the necessary port in iptables for the same. When the iptables is enabled, the application is not connectable from another server. Have tried to add a rule in the DOCKER chain, but not helped. Any suggestion?
Docker-compose file:
version: "3"
services:
testing-app:
image: "${DOCKER_REGISTRY_URI}/testing-app-${ENV}:${COMMIT_ID}"
container_name: test
ports:
- 8087:80
restart: always
Iptables rules:
-A INPUT -p tcp -m tcp --dport 8087 -m conntrack --ctstate NEW -m comment --comment "ANSIBLE_FIREWALL_COMMENT - Allow tcp for 8087" -j ACCEPT
-A INPUT -p udp -m udp --dport 8087 -m conntrack --ctstate NEW -m comment --comment "ANSIBLE_FIREWALL_COMMENT - Allow udp port for 8087" -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -m conntrack --ctstate NEW -m comment --comment "ANSIBLE_FIREWALL_COMMENT - Allow tcp for 80" -j ACCEPT
-A INPUT -p udp -m udp --dport 80 -m conntrack --ctstate NEW -m comment --comment "ANSIBLE_FIREWALL_COMMENT - Allow udp port for 80" -j ACCEPT
Iptables list:
iptables -t nat -L -n -v
Chain PREROUTING (policy ACCEPT 738 packets, 177K bytes)
pkts bytes target prot opt in out source destination
348 20880 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 243 packets, 14580 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 2804 packets, 170K bytes)
pkts bytes target prot opt in out source destination
2407 144K DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 2804 packets, 170K bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * !br-40940e3fd969 172.18.0.0/16 0.0.0.0/0
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.18.0.2 172.18.0.2 tcp dpt:80
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- br-40940e3fd969 * 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
105 6300 DNAT tcp -- !br-40940e3fd969 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8087 to:172.18.0.2:80
Netstat:
netstat -plant | grep 8087
tcp6 0 0 :::8087 :::* LISTEN 5665/docker-proxy
[root#idev-staging-micro-2 ~]#
service
ps -Af | grep proxy
root 5665 24269 0 May05 ? 00:00:02 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8087 -container-ip 172.18.0.2 -container-port 80
root 24106 23979 0 16:47 pts/1 00:00:00 grep --color=auto proxy
sysctl:
sysctl -a | grep net.ipv4.conf.all.route_localnet
net.ipv4.conf.all.route_localnet = 0

Can't open port 25

I have a weird issue.
I am running a mail server behind a proxy. On the proxy all mail related ports are forwarded to the mail server:
peter#proxy:~$ sudo iptables -S
[sudo] password for peter:
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -p tcp -m tcp --dport 3389 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 110 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 143 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 465 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 587 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 993 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 995 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
-A FORWARD -i ens192 -o ens160 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i ens160 -o ens192 -j ACCEPT
-A FORWARD -d 10.10.0.15/32 -p tcp -m tcp --dport 3389 -j ACCEPT
-A FORWARD -d 10.10.0.5/32 -p tcp -m tcp --dport 110 -j ACCEPT
-A FORWARD -d 10.10.0.5/32 -p tcp -m tcp --dport 143 -j ACCEPT
-A FORWARD -d 10.10.0.5/32 -p tcp -m tcp --dport 587 -j ACCEPT
-A FORWARD -d 10.10.0.5/32 -p tcp -m tcp --dport 465 -j ACCEPT
-A FORWARD -d 10.10.0.5/32 -p tcp -m tcp --dport 993 -j ACCEPT
-A FORWARD -d 10.10.0.5/32 -p tcp -m tcp --dport 995 -j ACCEPT
-A FORWARD -d 10.10.0.5/32 -p tcp -m tcp --dport 25 -j ACCEPT
As you can see all the mailing related ports are forwarded to the mail server (10.10.0.5). I can telnet from outside into all the ports, except 25. From the proxy I can also telnet into the mail server on port 25. So the port is blocked on the proxy side.
Nothing else is listening on port 25:
peter#proxy:~$ sudo netstat -plutn
[sudo] password for peter:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1457/sshd
tcp6 0 0 :::443 :::* LISTEN 1512/apache2
tcp6 0 0 :::587 :::* LISTEN 1508/xinetd
tcp6 0 0 :::80 :::* LISTEN 1512/apache2
tcp6 0 0 :::465 :::* LISTEN 1508/xinetd
tcp6 0 0 :::22 :::* LISTEN 1457/sshd
This is what I get when I try telneting from the outside:
peter#ubuntu-desktop:~$ telnet mx0.xyz.com 25
Trying 5.199.xxx.yyy...
telnet: Unable to connect to remote host: Connection refused
peter#ubuntu-desktop:~$ telnet mx0.xyz.com 110
Trying 5.199.xxx.yyy...
Connected to mx0.xyz.com.
Escape character is '^]'.
+OK POP3 ready
quit
+OK
Connection closed by foreign host.
Same for the other ports.
I can send emails but I cannot receive any, the gmail server reports a Connection refused error.
[mx0.xyz.com. 5.199.xxx.yyy: FAILED_PRECONDITION: connect error (111): Connection refused]
How can I figure out what's blocking port 25 and how can I open it?

Redirect web server from port 5000 to port 80 on localhost (Fedora)

On Fedora 24, a web server (Node.js) is running (standalone, no apache/others) on port 5000. Trying to making it accessible on port 80.
http://localhost:5000 works
Tried this:
systemctl stop firewalld
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 5000
http://localhost doesn't work
Tried this
systemctl restart firewalld
firewall-cmd --add-service=http --permanent
firewall-cmd --zone=external --add-masquerade
firewall-cmd --zone=external --add-forward-port=port=80:proto=tcp:toport=5000
firewall-cmd --add-forward-port=port=80:proto=tcp:toport=5000
firewall-cmd --list-all
FedoraWorkstation (active)
target: default
icmp-block-inversion: no
interfaces: wlp3s0
sources:
services: mdns ssh dhcpv6-client samba-client https http
ports: 1025-65535/tcp 1025-65535/udp
protocols:
masquerade: yes
forward-ports: port=80:proto=tcp:toport=5000:toaddr=
source-ports:
icmp-blocks:
rich rules:
Additional info
Tried these
sysctl -w net.ipv4.ip_forward=1
iptables -A FORWARD -j ACCEPT
iptables -A FORWARD -j ACCEPT
iptables -t nat --list
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
REDIRECT tcp -- anywhere anywhere tcp dpt:http redir ports 5000
REDIRECT tcp -- anywhere anywhere tcp dpt:https redir ports 5000
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
ifconfig
enp0s25: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
wlp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ip route
default via 192.168.1.1 dev wlp3s0 proto static metric 600
192.168.1.0/24 dev wlp3s0 proto kernel scope link src 192.168.1.4 metric 600
For others it just works:
Best practices when running Node.js with port 80 (Ubuntu / Linode)
Running node as root on port 80 works. Note, there's no IPv4:
netstat -tpln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1/systemd
tcp 0 0 0.0.0.0:4433 0.0.0.0:* LISTEN 3977/deluge-gtk
tcp 0 0 0.0.0.0:51157 0.0.0.0:* LISTEN 3977/deluge-gtk
tcp 0 0 0.0.0.0:5432 0.0.0.0:* LISTEN 900/postgres
tcp 0 0 0.0.0.0:17500 0.0.0.0:* LISTEN 3203/dropbox
tcp 0 0 127.0.0.1:17600 0.0.0.0:* LISTEN 3203/dropbox
tcp 0 0 127.0.0.1:17603 0.0.0.0:* LISTEN 3203/dropbox
tcp6 0 0 :::111 :::* LISTEN 1/systemd
tcp6 0 0 :::4433 :::* LISTEN 3977/deluge-gtk
tcp6 0 0 :::51157 :::* LISTEN 3977/deluge-gtk
tcp6 0 0 :::5432 :::* LISTEN 900/postgres
tcp6 0 0 :::17500 :::* LISTEN 3203/dropbox
tcp6 0 0 :::34017 :::* LISTEN 10532/code
tcp6 0 0 :::5858 :::* LISTEN 30394/node
tcp6 0 0 :::5000 :::* LISTEN 30394/node
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --add-masquerade --permanent
firewall-cmd --add-forward-port=port=80:proto=tcp:toport=5000 --permanent
#make port forwarding work on localhost
iptables -t nat -I OUTPUT --source 127.0.0.1 --destination 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to-ports 5000
You should avoid using iptables for things like this, but on Fedora you'd need to setup the firewall appropriately. Also this question has nothing to do with Node.js
firewall-cmd --add-service=http --permanent
firewall-cmd --reload
Related: https://unix.stackexchange.com/questions/39216/cannot-connect-to-fedora-on-port-80

How do I configure Docker to work with my ens34 network interface (instead of eth0)?

does anyone know how docker decides which NIC will work with the docker0 network? I have a node with two interfaces (eth0 and ens34), however, only the requests that go through eth0 are forwarded to the container.
When my VM was provisioned and Docker was installed, I started a very silly test: I created a centos vm, installed netcat on it and committed the image. Then I started a daemon container listening on port 8080. I used:
docker -it -p 8080:8080 --name nc-server nc-server nc -vv -l 8080
So I tried to connect to the container listening on port 8080 from another node in the same network (in the same IP address as the interface ens34). It did not work.
Whereas when I sent a request from another machine to the IP address from eth0, I saw some reaction in the container (the communication worked). I was "tailing" its output with:
docker logs -ft nc-server
My conclusion with this experiment: there's some mysterious relationship between eth0 (primary NIC) and docker0, and the requests that are sent to ens34 (10.) interface are never forwarded to the veth / docker0 interfaces, only the requests that go through eth0 (9.*). Why's that?
Also, I know I can make everything work if I use --net=host, but I don't want to use that... it doesn't feel right somehow, is it a standard practice to use the HOST mode in Docker containers? Any caveats on that?
--
UPDATE:
I managed to make it work after disabling iptables:
service iptables stop
However, I still don't get what is going on. The info below should be relevant to understand what is going on:
ifconfig
[root#mydockervm2 myuser]# ifconfig | grep -A 1 flags
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
--
ens34: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.1.21.18 netmask 255.255.255.0 broadcast 10.1.21.255
--
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 9.32.145.99 netmask 255.255.255.0 broadcast 9.32.148.255
--
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
--
veth8dbab2f: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::3815:67ff:fe9b:88e9 prefixlen 64 scopeid 0x20<link>
--
virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
netstat
[root#mydockervm2 myuser]# netstat -nr
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 9.32.145.1 0.0.0.0 UG 0 0 0 eth0
9.32.145.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
10.1.21.0 0.0.0.0 255.255.255.0 U 0 0 0 ens34
169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 ens34
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0
filters
[root#mydockervm2 myuser]# iptables -t filter -vS
-P INPUT ACCEPT -c 169 106311
-P FORWARD ACCEPT -c 0 0
-P OUTPUT ACCEPT -c 110 13426
-N DOCKER
-N DOCKER-ISOLATION
-A FORWARD -c 0 0 -j DOCKER-ISOLATION
-A FORWARD -o docker0 -c 0 0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -c 0 0 -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -c 0 0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -c 0 0 -j ACCEPT
-A FORWARD -m physdev --physdev-is-bridged -c 0 0 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8080 -c 0 0 -j ACCEPT
-A DOCKER-ISOLATION -c 0 0 -j RETURN
nat
[root#mydockervm2 myuser]# iptables -t nat -vS
-P PREROUTING ACCEPT -c 28 4818
-P INPUT ACCEPT -c 28 4818
-P OUTPUT ACCEPT -c 8 572
-P POSTROUTING ACCEPT -c 8 572
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -c 2 98 -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -c 0 0 -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -c 0 0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 8080 -c 0 0 -j MASQUERADE
-A DOCKER -i docker0 -c 0 0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -c 0 0 -j DNAT --to-destination 172.17.0.2:8080
Thoughts?
First, rule out the obvious and make sure that hosts on the other networks know how to route to your machine to reach the container network. For that, check
netstat -nr
on the source host and make sure that your docker subnet is listed with your docker host as the gateway, or that the default router handling the traffic upstream knows about your host.
If traffic is getting routed but blocked, then you're getting into forwarding and iptables. For forwarding, the following should show a 1:
cat /proc/sys/net/ipv4/ip_forward
Make sure your local host shows a route for the bridges to your container networks with the same netstat command, there should be a line for the docker0 interface and your docker subnet as the destination:
netstat -nr
For iptables, check to see if there are any interface specific nat or filter rules that need to be adjusted:
iptables -t filter -vS
iptables -t nat -vS
If your forward rule defaults to DROP instead of ACCEPT, you may want to add some logging, or just change the default to accept traffic if you believe it can be trusted (e.g. the host is behind another firewall).
This all being said, advertising ports directly on the host is a fairly common practice with containers. For the private stuff, you can setup multiple containers isolated on their internal network that can talk to each other, but no other containers, and you only expose the ports that are truly open to the rest of the world on the host with the -p flag to the run (or ports option in docker-compose).

protect mongodb ports with iptables

This is my iptables config:
sudo iptables -L -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo any anywhere anywhere
859 103K ACCEPT all -- any any anywhere anywhere ctstate RELATED,ESTABLISHED
5 260 ACCEPT tcp -- any any anywhere anywhere tcp dpt:ssh
3 230 ACCEPT tcp -- any any anywhere anywhere tcp dpt:27017
4 208 ACCEPT tcp -- any any anywhere anywhere tcp dpt:28017
0 0 ACCEPT all -- any any localhost anywhere
0 0 ACCEPT all -- any any 111.111.111.111 anywhere
0 0 ACCEPT all -- any any 222.222.222.222 anywhere
64 3844 DROP all -- any any anywhere anywhere
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 764 packets, 227K bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- any any localhost anywhere
0 0 ACCEPT all -- any any 111.111.111.111 anywhere
0 0 ACCEPT all -- any any 222.222.222.222 anywhere
If I write in browser the ip if my mongodb server with port 28017, I can see a promt to enter username and password:
#ip mongodb server
000.000.000.000:28017
I want close mongodb ports to anyone except to these 2 ips:
111.111.111.111
222.222.222.222
How can I do it?
Can you try the following iptables rules
-A INPUT -m state --state NEW -p tcp --destination-port 27017 -s 111.111.111.111 -j ACCEPT
-A INPUT -m state --state NEW -p tcp --destination-port 27017 -s 222.222.222.222 -j ACCEPT
Looks like you forgot to put in the source IP flag.
I have removed of my iptables these two line:
-A INPUT -p tcp -m tcp --dport 27017 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 28017 -j ACCEPT
and now it's not possible access to mongdb ports from any ip.
Thanks
The rules I use for limiting external access to mongo are:
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- localhost anywhere tcp dpt:27017
ACCEPT tcp -- localhost anywhere tcp dpt:28017
ACCEPT tcp -- 111.111.111.111 anywhere tcp dpt:27017
ACCEPT tcp -- 222.222.222.222 anywhere tcp dpt:27017
ACCEPT tcp -- 111.111.111.111 anywhere tcp dpt:28017
ACCEPT tcp -- 222.222.222.222 anywhere tcp dpt:28017
DROP tcp -- anywhere anywhere tcp dpt:27017
DROP tcp -- anywhere anywhere tcp dpt:28017
You can add them with
sudo iptables -A INPUT -p tcp -m tcp --dport 27017 -s 127.0.0.1 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 28017 -s 127.0.0.1 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 27017 -s 111.111.111.111 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 27017 -s 222.222.222.222 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 28017 -s 111.111.111.111 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 28017 -s 222.222.222.222 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 27017 -j DROP
sudo iptables -A INPUT -p tcp -m tcp --dport 28017 -j DROP

Resources