fixing docker issue with open ports and firewalls, with ufw instead of iptables

2021-02-14

If you have ever dealt with Docker and opening ports at the host level1, you might have (hopefully) realized that firewalls do not filter these ports used by Docker. Consequentially, if you use neat solutions such as Fail2Ban in the host to ban somebody abusing one of your docker containers, the ban kicks in but is effectively void.

This issue is well known, and it happens because Docker sets up its own iptables rules to achieve network isolation and port forwarding. These rules interfere with the usual ways we use our firewalls. Now, if you are an iptables guru, you know how to setup your own filtering so that it is compatible with the DOCKER-USER chain. If you, like me, see iptables like black magic and prefer a human readable firewall like ufw, you’re hit by the same issue. The ufw is just a frontend for iptables.

I discovered two neat tricks this week. The first one: you can use ufw as a banaction for fail2ban instead of iptables directly.

This is how I set it up globally in /etc/fail2ban/jail.local so that I do not have to specify it for all jails.

# cat /etc/fail2ban/jail.local | grep banaction
banaction = ufw
banaction_allports = ufw

So that when fail2ban issues some bans:

# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 3
|  |- Total failed:     1641
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 2
   |- Total banned:     33
   `- Banned IP list:   171.227.213.238 81.161.63.103

The ban is handled by ufw and you can see it pretty easily:

# ufw status
Status: active

To                         Action      From
--                         ------      ----
Anywhere                   REJECT      81.161.63.103             
Anywhere                   REJECT      171.227.213.238
[...]

How to have ufw actually ban bad actors with Docker containers? This post by p1ngouin shows the solution. It is a pretty easy one, and they even offer an Ansible solution to automatize its deployment. Just remember to use your network interface name instead of $INTERFACE!.


  1. For example, a containerized SMPT server using the host ports 25, 465, and 587. 


I do not use a commenting system anymore, but I would be glad to read your feedback. Feel free to contact me.