[SOLVED] What to do about LXD-generated iptables rules when the host has its own iptables rules?

Platform: LXD 3.9 running on Arch Linux.

After running lxc init and going with the default networking suggestions (save for turning off IPv6), I notice that a few iptables rules have been set up automagically:

[root@archlinux ~]# iptables -t filter -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --              tcp dpt:53 /* generated for LXD network lxdbr0 */
ACCEPT     udp  --              udp dpt:53 /* generated for LXD network lxdbr0 */
ACCEPT     udp  --              udp dpt:67 /* generated for LXD network lxdbr0 */

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --              /* generated for LXD network lxdbr0 */
ACCEPT     all  --              /* generated for LXD network lxdbr0 */

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --              tcp spt:53 /* generated for LXD network lxdbr0 */
ACCEPT     udp  --              udp spt:53 /* generated for LXD network lxdbr0 */
ACCEPT     udp  --              udp spt:67 /* generated for LXD network lxdbr0 */

[root@archlinux ~]# iptables -t nat -L -n
target     prot opt source               destination         
MASQUERADE  all  --      !       /* generated for LXD network lxdbr0 */

My question is, if I’m setting up my own iptables rules on the host (say for forwarding incoming web traffic to a container), do I just ignore the rules LXD creates (because they’ll be created again automagically on reboot no matter what) or should I incorporate them specifically into my own iptables ruleset?

I’m concerned about idempotency in this context.

Apologies if this fully documented somewhere: I have not come across this yet after many hours of reading.

Either way is fine, LXD will re-inject them whenever the network is updated or on startup.
If you don’t want LXD to do that, you can set ipv4.firewall and ipv6.firewall to false in your network’s configuration and then incorporate those rules into your own firewall script.

Thanks, Stéphane. I’m not going to mark this as solved yet, as there are still a couple of issues.

First, I’m still worried about idempotency; i.e. is the right thing always going to happen if LXD injects rules into the iptables chains, and how does LXD know if I’ve encoded these rules in my default tables myself? One server I’m planning to deploy many containers on already has a very complicated iptables setup (NAT, port forwarding here and there and everywhere, service restrictions, multiple IP addresses, etc…)

Second, I don’t understand how LXD is doing this. I looked at the systemd service file on my system, and it’s not clear how/where iptable rules are injected. This is the service file:

Description=REST API, command line tool and OpenStack integration plugin for LXC.

ExecStart=/usr/bin/lxd --group lxd
ExecStop=/usr/bin/lxd shutdown


This article suggests that there is an lxc-net service, but I can’t find any such service on my system. In this post, you suggest that it’s just a script that gets run How is LXD able to re-inject iptables rules if it’s not done through systemd?

Third, there was recently a post on this forum from someone trying to use nftables. Since people are likely to be using nftables more and more as time goes on, I’m wondering if you all have thought about how to deal with this issue.

Sorry to have so many questions, but I’m seeing LXD as a potential solution to many systems problems I’ve been dealing with, so want to understand thoroughly how it works. I read through all your excellent blog posts, but find the readthedocs documentation to be more of a reference manual than learning resource. Understood that it’s a headache to attempt to provide procedural instructions, as every distro does networking differently, including now Ubuntu (if-up vs. netplan).

The LXD daemon itself interacts with iptables/ip6tables.

If you configure a LXD managed network to disable the firewalling rules with the configuration options I mentioned before, then LXD won’t touch your firewall and it’s up to you to make sure you’re doing the right thing. If you’re not, then your containers will potentially run into networking problems, LXD doesn’t perform any check in such cases.

LXD always prepends its rules, which normally avoids an existing firewalling script from interfering with it by making sure that the rules needed for container networking will be hit before any potential drop/reject rule that’s managed outside of LXD.