UFW Does Not Control CTs Or VMs, Only Host


All CTs/VMs have static IPs (via override) and I have several port fwds working (they are all nat=true due to my use cases).

lxc network show lxdbr0
  ipv4.address: x.x.x.x/24
  ipv4.firewall: "true"
  ipv4.nat: "true"
  ipv6.address: none

UFW is using the default setup: deny (incoming), allow (outgoing), deny (routed). LXD is using the standard lxdbr0. This is Ubuntu Focal, and nftables has never been/is not installed.

If I remove a rule from UFW (remove an explicit ALLOW, so it should DENY) to my surprise I can still reach the listener inside each CT/VM. For listeners on the host, UFW is respected.

What is going on?


I think to help further we would need to see the output of sudo iptables-save before/after the rule change you mention, as well as an example command you are running to test that the port is still open (curl perhaps?).

Additionally please show output of lxc info | grep firewall:


Thank you Thomas. The firewall: xtables but the reason for this was:

an (intentionally created) proxy device placed the rule in iptables, and removing the rule from UFW did not affect iptables either because iptables respects the wishes of the LXD daemon over UFW OR the LXD daemon recreates the rule either periodically or upon restart.

i was naively expecting this behavior: no matter what the proxy device says, if UFW doesn’t have an allow rule, the connection is not allowed from the WAN. But given that UFW is only a frontend, it makes sense that IPtables does what it is told independent of UFW. The question then becomes what happened: did the LXD daemon re insert the rule at some point OR did iptables not obey UFW when the rule was removed from UFW?

What rule are you referring to?

-A PREROUTING -d pu.bl.ic.ip/32 -p tcp -m tcp --dport 8080 -m comment --comment "" -j DNAT --to-destination

-A OUTPUT -d pu.bl.ic.ip/32 -p tcp -m tcp --dport 8080 -m comment --comment "" -j DNAT --to-destination

-A POSTROUTING -s -d -p tcp -m tcp --dport 8080 -m comment --comment "" -j MASQUERADE

Which were properly created by a proxy intented to NAT (true NAT) 8080 in a WAN-Host-VM fashion.

The FORWARD chain should still be able to block packets incoming to that DNAT port forward, as these rules in the PREROUTING chain just setup the DNAT forward, but the packets still go through the FORWARD chain too after their destination IP has been rewritten and can be dropped there if needed.

hmm, I just changed the proxy device on the host to use "listen": "tcp:" instead. 8080 is no longer reachable from the outside, as needed.

PS: in case you are curious, I need the proxy device in place so that I can tell a service in a docker container inside the VM to connect to a service listening in the VM on 8080: I told the docker service to use