Block subnet except single ip not working

hello,

i want to block a whole subnet within network acls except one single ip address.

But i can’t access the single ip address when the reject rule ist active.

my acl settings in the lxc network:

config:
...
  security.acls.default.ingress.action: reject
  security.acls.default.egress.action: reject
  security.acls: test-acl
...

my network acl setting:

name: test-acl
descriptione: ""
egress:
- action: allow
  destination: 172.17.0.22
  state: enabled
- action: reject
  destination: 172.17.0.0/24
  state: enabled
ingress: []
config: {}
used_by:
- /1.0/networks/lxdbr0-test

any idea?
my lxd-version: 5.5

Please can you show lxc network show <network> and lxc config show <instance> as well as the command you are running that isn’t working (so I can get an idea of direction and context).

hello,

here all configs and commands i used

# lxc network show lxdbr0-acl

config:
  ipv4.address: 10.228.15.1/24
  ipv4.nat: "true"
  ipv6.address: fd42:8572:a718:e314::1/64
  ipv6.nat: "true"
  security.acls: test-acl
  security.acls.default.egress.action: allow
  security.acls.default.ingress.action: allow
description: ""
name: lxdbr0-acl
type: bridge
used_by:
- /1.0/instances/ct-acl
- /1.0/profiles/profile-acl
managed: true
status: Created
locations:
- none
# lxc config show ct-acl
architecture: x86_64
config:
  image.architecture: amd64
  image.description: ubuntu 22.04 LTS amd64 (release) (20220902)
  image.label: release
  image.os: ubuntu
  image.release: jammy
  image.serial: "20220902"
  image.type: squashfs
  image.version: "22.04"
  volatile.base_image: 95f82d22bea6a0d20dc3c06a59929b768abd0c7243d5298c3973f1808688d117
  volatile.cloud-init.instance-id: a438dcb8-06db-4c62-866a-8a77d135b239
  volatile.eth0.host_name: veth58fb7177
  volatile.eth0.hwaddr: 00:16:3e:93:4c:bf
  volatile.eth0.name: eth0
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.power: RUNNING
  volatile.uuid: 4336cc6b-0134-4b69-938a-8d9e690d009a
devices: {}
ephemeral: false
profiles:
- profile-acl
stateful: false
description: ""

my commands:

# network and acls
lxc network create lxdbr0-acl
lxc network acl create test-acl
lxc network acl rule add test-acl egress destination=172.17.0.22/32 action=allow
lxc network acl rule add test-acl egress destination=172.17.0.0/24 action=reject
lxc network set lxdbr0-acl security.acls.default.egress.action=allow security.acls.default.ingress.action=allow security.acls=test-acl

# ct
lxc launch ubuntu:22.04 ct-acl

# profile
lxc profile copy default profile-acl
lxc profile device remove profile-acl eth0
lxc profile device add profile-acl eth0 name=eth0 network=lxdbr0-acl type=nic
lxc profile add ct-acl profile-acl
lxc profile remove ct-acl default

i cannot ping the ip 172.17.0.22 from inside container:

# lxc exec ct-acl -- ping 172.17.0.22 -c 1
PING 172.17.0.22 (172.17.0.22) 56(84) bytes of data.
From 10.228.15.1 icmp_seq=1 Destination Port Unreachable

--- 172.17.0.22 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

removing the deny rule then it works

lxc network acl rule remove test-acl egress destination=172.17.0.0/24 action=reject
# lxc exec ct-acl -- ping 172.17.0.22 -c 1
PING 172.17.0.22 (172.17.0.22) 56(84) bytes of data.
64 bytes from 172.17.0.22: icmp_seq=1 ttl=61 time=11.8 ms

--- 172.17.0.22 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 11.809/11.809/11.809/0.000 ms

i can do it with iptables

iptables -I FORWARD -i lxdbr0-acl -d 172.17.0.0/24 -j REJECT
iptables -I FORWARD -i lxdbr0-acl -d 172.17.0.22/32 -j ACCEPT

but it would be better to manage with network acls

could it be a lxd bug in creating the iptables-rules?

my network acl rule:

# lxc network acl show test-acl
name: test-acl
description: ""
egress:
- action: allow
  destination: 172.17.0.22/32
  state: enabled
- action: reject
  destination: 172.17.0.0/24
  state: enabled
ingress: []
config: {}
used_by:
- /1.0/networks/lxdbr0-acl

iptables says:

# sudo iptables-save | grep 172.17
-A lxd_acl_lxdbr0-acl -d 172.17.0.0/24 -i lxdbr0-acl -j REJECT --reject-with icmp-port-unreachable
-A lxd_acl_lxdbr0-acl -d 172.17.0.22/32 -i lxdbr0-acl -j ACCEPT

lxc writes the REJECT rule in front of the ACCEPT rule.
so the ACCEPT rule never wins!

I don’t think its a bug, according to:

More generally what is the use-case you’re trying to achieve here?

thanks for your reply

ok, i don’t understand the purpose of this sorting

i want to isolate some containers from other networks but need some exceptions for single ip addresses.

maybe i’m on the completely wrong way to do that with network acls?

In that case you should set security.acls.default.[egress|ingress].action to reject or block and then you can remove the reject rule and instead add allow rules for the traffic you want to allow.

Its designed on the principle of Access Control Lists, i.e that everything is denied by default and you just allow what you want.

This allows multiple ACL lists to be merged together without needing to consider the ordering result of that.