Install, start and enable:
apt install firewalld
systemctl start firewalld
systemctl enable firewalld
Make sure the file /etc/docker/daemon.json
does not contain this line. If it does, delete/comment it. If the file is missing, it is OK, you can skip the step:
{
//...rest content
"iptables": true // <-- delete this
}
Add rules for the host:
firewall-cmd --permanent --zone=public --add-port=22/tcp
firewall-cmd --permanent --zone=public --add-port=80/tcp
firewall-cmd --permanent --zone=public --add-port=8080/tcp
firewall-cmd --permanent --zone=public --add-port=8083/tcp
firewall-cmd --permanent --zone=public --add-port=443/tcp
firewall-cmd --permanent --zone=public --add-port=8443/tcp
Add chain for docker:
firewall-cmd --permanent --direct --remove-rules ipv4 filter DOCKER-USER
firewall-cmd --permanent --direct --add-chain ipv4 filter DOCKER-USER
Allow internal docker communication (Run docker network inspect <your_network>
to obtain network submask):
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -j RETURN -s 172.18.0.0/16 -m comment --comment "allow internal docker communication"
Accept dns requests:
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN -m comment --comment "accept dns requests"
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -p udp -m udp --dport 53 --sport 1024:65535 -j RETURN -m comment --comment "accept dns requests"
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -p tcp -m tcp --dport 53 -j ACCEPT -m comment --comment "accept dns requests"
Accept http(s) traffic:
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -p tcp -m multiport --dports 80,443,8080,8083,8443 -s 0.0.0.0/0 -j ACCEPT -m comment --comment "accept http(s) traffic"
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -p tcp -m multiport --sports 80,443,8080,8083,8443 -s 0.0.0.0/0 -j ACCEPT -m comment --comment "accept https(s) traffic"
Accept smtp traffic from docker containers. SMTP typically uses port 25 for unencrypted communication, port 587 for TLS/STARTTLS, and port 465 for SMTPS (SMTP over SSL):
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -p tcp -m multiport --dports 25,465,587 -j ACCEPT -m comment --comment "accept smtp traffic from docker containers"
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -p tcp -m multiport --sports 25,465,587 -j ACCEPT -m comment --comment "accept smtp traffic responses"
Accept our remote postgres:
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -p tcp -s 5.XXX.XXX.149 --sport 5432 -j ACCEPT -m comment --comment "our remote postgres"
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -p tcp -d 5.XXX.XXX.149 --dport 5432 -j ACCEPT -m comment --comment "our remote postgres"
Enable logging (access via dmesg
command or check /var/log/syslog
):
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
Reject all other out traffic:
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -j REJECT -m comment --comment "reject all other out traffic"
Restart:
firewall-cmd --reload
systemctl stop docker && systemctl stop firewalld
systemctl start firewalld && systemctl start docker
Save this file as check_connection.py
changing the IP to your own:
# coding=utf-8
import socket
def _connect(target, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.setdefaulttimeout(1)
result = s.connect_ex((target, port))
if result == 0:
print("You can connect to the port: {}".format(port))
else:
print("You CANNOT connect to the port: {}".format(port))
s.close()
ip = '82.196.4.187' # specify another server of yours for checking
_connect(ip, 80)
_connect(ip, 443)
_connect(ip, 22)
Run this file INSIDE docker container:
python check_connection.py
# or python3 check_connection.py
Expected results:
$ docker exec -it hello-world-app-1 bash
app@56a9eca011ff:~$ python3 check_connection.py
You can connect to the port: 80
You can connect to the port: 443
You CANNOT connect to the port: 22
Exit container and run the script from the host console, expected result:
root@hello:/var/www/app $ python3 check_connection.py
You can connect to the port: 80
You can connect to the port: 443
You can connect to the port: 22