For a production server, I would like to limit access to certain services to specific allowed hosts on the public internet.
I am using ufw to configure iptables on the lxd host.
I have nat proxy devices configured in lxd to forward external connections to container instances. ip4.firewall is not set.
I have observed that deny rules for connections to ports on the external interface that lxd is listening on have no effect on the lxd proxy devices. Only rules applied to lxdbr0 have any effect at all. It’s as though the external physical interface doesn’t even exist.
Consider a container with the following devices configured:
eth0:
ipv4.address: <container_ip>
ipv6.address: <container_ip6>
nictype: bridged
parent: lxdbr0
type: nic
ssh:
connect: tcp:<container_ip>:22
listen: tcp:<external_ip>:2201
nat: "true"
type: proxy
With these firewall rules, I can log into containers from the host at <allowed_host>:
$ sudo ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 22/tcp on lxdbr0 ALLOW FWD <allowed_host> (out)
[ 2] 22 ALLOW IN Anywhere
[ 3] Anywhere on lxdbr0 ALLOW IN Anywhere
[ 4] Anywhere ALLOW FWD Anywhere on lxdbr0
[ 5] 22 (v6) ALLOW IN Anywhere (v6)
[ 6] Anywhere (v6) on lxdbr0 ALLOW IN Anywhere (v6)
[ 7] Anywhere (v6) ALLOW FWD Anywhere (v6) on lxdbr0
If I add a deny rule, as below, where eth0 has <external_ip>
:
$ sudo ufw prepend deny in on eth0 from <allowed_ip> to any port 2201 proto tcp
[sudo] password for user:
Rule inserted
user@lxdhost 2024-01-03 16:53:15 ~ $ sudo ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 2201/tcp on eth0 DENY IN <allowed_host>
[ 2] 22/tcp on lxdbr0 ALLOW FWD <allowed_host> (out)
[ 3] 22 ALLOW IN Anywhere
[ 4] Anywhere on lxdbr0 ALLOW IN Anywhere
[ 5] Anywhere ALLOW FWD Anywhere on lxdbr0
[ 6] 22 (v6) ALLOW IN Anywhere (v6)
[ 7] Anywhere (v6) on lxdbr0 ALLOW IN Anywhere (v6)
[ 8] Anywhere (v6) ALLOW FWD Anywhere (v6) on lxdbr0
it has no effect on connections to the container on the lxdbr0 network from <allowed_host>. (It does not matter if I deny traffic in or out, the non-effect is the same.)
Only manipulating lxdbr0 has any effect.
This is not what I expect. LXD is listening on the external interface! If I am blocking ports on the external interface, LXD should not even be able to receive connections on those blocked ports.
How do you explain what I am observing? My guess is that lxd network is handling the packet before the firewall sees it.
(One other thing that may be relevant: I noticed that I cannot see the listeners for every lxd device in ss -tlpn
output, only listeners for interfaces configured very early, perhaps via lxd? The listener above is not one of the ones that is visible in ss -tlpn
. The installation was originally the 4.0.x snap, and was upgraded to the 5.0 stable snap.)