How much of iptables work inside containers?

It seems that some support for iptables exist inside (non-privileged) containers.
For example, I have installed software in a container that installs a ufw firewall, and ufw prevents connections to ports from other containers.

But I’ve also read in this forum, that fail2ban does not work inside containers, so you have to set it up on the host: Fail2ban for Wordpress on containers

So, how much of iptables works inside a container? Why does ufw work, but fail2ban doesn’t work?

Well there are two aspects here:

  1. Does iptables work inside containers - the answer is mostly yes, although if you need any custom modules loaded then they will need to be preloaded on the host as containers can’t load kernel modules. Also, if you find yourself wanting to match rules against UIDs you’ll likely need to shift them in the rules to use the container’s shifted UID range.
  2. Is fail2ban able to recognise the remote IP address in order to add the correct iptables rule? Technically this is nothing to do with iptables, and all to do with the method that you are using to get remote connections into your container.

If you are using a reverse proxy such as nginx, haproxy or LXD’s own proxy device type, the by default the container won’t see the remote clients IP, and so fail2ban won’t be able to block it.

However there are usually ways around this, such as:

  1. Use LXD’s proxy device in nat=true mode, and assign a static IP to your container using lxc config device override <instance> <nic name> ipv4.address=n.n.n.n.n, this will then maintain the source IP address into the container as it won’t be going through a separate reverse proxy process.
  2. Use LXD’s proxy device in proxy_protocol=true mode, this will still use the more flexible proxy process, but will use the so-called “proxy protocol” to allow passing info about the remote IP address to the target application. However in order for this to work your target application needs to be able to understand the proxy protocol and write the remote IP it receives into its log for fail2ban.
  3. Don’t use a proxy at all, and just expose the container directly onto the external network using a NIC type like macvlan, routed or a separate unmanaged bridge. But this will depend on your network topology and whether you have any spare IPs to use for your containers.

Thank you. This clears things up mostly.

There is yet another way to get remote connections into the container, without multiple external ip addresses: Using iptables DNAT rules on the host. In this case, the container sees the real external source ip in the incoming connection. Would fail2ban work inside the container then?

Yes it would.

This is identical to the way I suggested using a LXD proxy device with nat=true. It just gets LXD to maintain the firewall rules for you without having to manually do it.

In this mode it sets up the DNAT rules for you. But because it uses the host’s iptables DNAT rules to forward traffic to the container, we need to ensure that the container’s IP doesn’t change, and that is why you need to then specify a static DHCP allocation using the command I mentioned above.