Skip to content

Instantly share code, notes, and snippets.

@liejuntao001
Last active May 10, 2020 09:30
Show Gist options
  • Save liejuntao001/266f2c5a5e85be70201eee9bcbd2b4a4 to your computer and use it in GitHub Desktop.
Save liejuntao001/266f2c5a5e85be70201eee9bcbd2b4a4 to your computer and use it in GitHub Desktop.
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:FILTERS - [0:0]
:DOCKER-USER - [0:0]
-F INPUT
-F DOCKER-USER
-F FILTERS
# BASIC Allow
-A INPUT -i lo -j ACCEPT
# Chain to FILTERS
-A INPUT -j FILTERS
-A DOCKER-USER -i eth0 -j FILTERS
# COMMON FIREWALL RULES
# ALLOW something
-A FILTERS -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# DENY something
-A FILTERS -p icmp --icmp-type echo-request -j REJECT
###################################################################
### special cases for servers
### please modify by the server
### end special cases
############################################################
# FINAL REJECT
# Optional logging
-A FILTERS -m limit --limit 5/min -j LOG --log-prefix "iptables_INPUT_denied: " --log-level 7
-A FILTERS -j REJECT
COMMIT
@jakommo
Copy link

jakommo commented May 9, 2020

Thanks for the quick reply. So just by binding it to the private ip, I don't see a different behaviour.

Didn't fully get your last sentence about the public ip. This machine only has one interface wlp3s0 with private ip 192.168.1.5.

I did play with it a little more, but when I remove allow 80,44 in line 22 and use something like:

-A FILTERS -s 192.168.1.20/32 -p tcp -m multiport --dports 8080 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Then 192.168.1.20 still can not connect to the nginx running on 8080. What makes it work is using the port inside the container like:

-A FILTERS -s 192.168.1.20/32 -p tcp -m multiport --dports 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Then I can curl from 192.168.1.20 to http://192.168.1.5:8080 and it works.
However, this allows connections to any container that is using port 80 internally. I.e. if I start another container like sudo docker run --rm --name nginx2 -p 192.168.1.5:8181:80 nginx
Then I can curl from 192.168.1.20 to http://192.168.1.5:8181 and it works.

What I want to achieve is that only certain hosts on the 192.168.1.0 net can reach certain services on this machine provided by docker.

How would you go about only allowing 192.168.1.20 access to the nginx running like sudo docker run --rm --name some-nginx -p 192.168.1.5:8080:80 nginx, without also allowing it access to another nginx that is running with 8181->80?

@liejuntao001
Copy link
Author

You have a different use case.
Mine is for hosts with 2 interfaces. One is the public IP address serving 80/443, another is private IP serving other internal services. The rules in this example block the unexpected access from the private IP interface.

The official document could help your use case.
https://docs.docker.com/network/iptables/

You could instead allow connections from a source subnet. The following rule only allows access from the subnet 192.168.1.0/24:
$ iptables -I DOCKER-USER -i ext_if ! -s 192.168.1.0/24 -j DROP

As you have this line
-A DOCKER-USER -i wlp3s0 -j FILTERS
above rule is like
-A FILTERS -i wlp3s0 ! -s 192.168.1.0/24 -j DROP

@liejuntao001
Copy link
Author

After some study I found this line will allow access to container port 80 when jumped from DOCKER-USER to FILTERS

-A DOCKER-USER -i wlp3s0 -j FILTERS
-A FILTERS -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Here the "80, 443" are not the port on the host side of the binding, but container side
e.g. 8080:80, 8080, the left side, host side port, and 80, the right side, container side.

If you modify the rule as
-A FILTERS -p tcp -m multiport --dports 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
then 8080 port is not accessible from external.

@jakommo
Copy link

jakommo commented May 10, 2020

Thanks for looking into this, really appreciate the help. I think I will stick with my current setup and using double rules in INPUT+DOCKER-USER for the per host per service mapping.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment