Iptables rule to block all traffic not proxied to a container?

Hi there!

I’m setting up a few LXD hosts with several containers on each. I am using the default lxdbr0 network bridge configuration to assign a DHCP address to each container. Many of these containers have a proxy device (or multiple) to forward selected ports from the external WAN address to the container.

This all works fine while my default iptables INPUT policy is ACCEPT, but if I set this to DROP, none of the containers are accessible from the WAN interface. Obviously I could add individual ACCEPT rules for each of the proxied ports, but that makes the containers much less portable - moving a container to a different host means also having to mess with the host firewall.

Using the nat=true proxy device parameter does seem to get around the issue (although I’m not sure where/how can I see the generated rules?) however this has a similar issue to manually adding the relevant iptables rules - moving the container from one host to another requires manually updating the proxy device listen address to the new host’s IP external address.

Is there an iptables INPUT rule I can add (or some other method) to allow traffic explicitly proxied to a container to be accepted, but anything else not explicitly defined in an ACCEPT rule for the host to be dropped? This would mean, for example, that the firewall would drop all tcp/80 traffic UNLESS there was a container running on that host with a proxy device listening on tcp:0.0.0.0:80.

When the proxy device is operating in non-nat mode (nat=false or not set) then a forkproxy process is spawned on the LXD host that listens on the specified IP and port(s) and proxies connections inbound to that listener to your instance.

In this way it acts just like any other services on your host in that it is protected by the INPUT policy of your firewall.

As you’ve found, using nat=true means that the forkproxy process isn’t spawned, and instead DNAT firewall rules are added that operate in the PREROUTING and FORWARD chains of your firewall. But they do require specifying a listen address and a target address as they don’t support binding on the wildcard address.

I don’t know of any way you can specify a host-side firewall rule to allow all ports created by the forkproxy process. If there were a way to match by process name it would likely be vulnerable to being bypassed by other processes using the same name.

I suppose this is by-design really, because as the administrator of those systems, if you set the INPUT policy to by DROP and you’ve not explicitly allowed those services, then it would be remis for LXD to assume it knows better and bypass the admin’s policy.

Thanks @tomp, that’s what I assumed, but wanted to confirm.

Using nat=true mode will work, I’ll just need to adjust my tooling/processes to handle moving a container to a different host.

1 Like