0

TL;DR: how do I configure firewall rules to be persistent? I am not using UFW, I believe I am using iptables-nft.

First, I have

There's some known firewall issues with Docker and LXD coexisting, but I want to use both and AFAIK both should be achievable, and this did work on my previous host (which was Ubuntu 18).

Out of the box Docker networking worked, LXD did not, and iptables commands showed this kind of firewall configuration:

sudo iptables -L
# Warning: iptables-legacy tables present, use iptables-legacy to see them
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
Chain FORWARD (policy DROP)
target     prot opt source               destination         
DOCKER-USER  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
Chain DOCKER (1 references)
target     prot opt source               destination         
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination         
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            
Chain DOCKER-USER (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere 

and

sudo iptables-legacy -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination  

The "Warning: iptables-legacy tables present" was a bit concerning, but I was not able to figure out if it is a problem I need to fix. I had not done any firewall customization myself at this point.

I got LXD fixed by adding these rules (last one to make it less open)

sudo iptables -I DOCKER-USER -o lxdbr0 -j ACCEPT
sudo iptables -I DOCKER-USER -i lxdbr0 -j ACCEPT
sudo iptables -I DOCKER-USER -i ext_if ! -s 192.168.1.0/24 -j DROP

But now I don't know how to make these permanent.

There is /etc/nftables.conf but it only has this blank configuration

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0;
    }
    chain forward {
        type filter hook forward priority 0;
    }
    chain output {
        type filter hook output priority 0;
    }
}

and when I execute nft list ruleset, there's a lot of Docker and LXD related configuration that obviously does not come from nftables.conf, and I don't know if it's supposed to be dynamic and configured by something else than me manually editing nftables.conf file.

So now I have created a script setup-lxd-networking.sh that does those iptables -I commands that I run by hand, but that's not very nice.

sudo nft list ruleset
...
table ip filter {
    chain DOCKER {
    }

    chain DOCKER-ISOLATION-STAGE-1 {
        iifname "docker0" oifname != "docker0" counter packets 18 bytes 1393 jump DOCKER-ISOLATION-STAGE-2
        counter packets 181 bytes 18684 return
    }

    chain DOCKER-ISOLATION-STAGE-2 {
        oifname "docker0" counter packets 0 bytes 0 drop
        counter packets 18 bytes 1393 return
    }

    chain FORWARD {
        type filter hook forward priority filter; policy drop;
        counter packets 209 bytes 35269 jump DOCKER-USER
        counter packets 181 bytes 18684 jump DOCKER-ISOLATION-STAGE-1
        oifname "docker0" ct state related,established counter packets 14 bytes 8351 accept
        oifname "docker0" counter packets 0 bytes 0 jump DOCKER
        iifname "docker0" oifname != "docker0" counter packets 18 bytes 1393 accept
        iifname "docker0" oifname "docker0" counter packets 0 bytes 0 accept
    }

    chain DOCKER-USER {
        iifname "ext_if" ip saddr != 192.168.1.0/24 counter packets 0 bytes 0 drop
        iifname "lxdbr0" counter packets 15 bytes 866 accept
        oifname "lxdbr0" counter packets 13 bytes 15719 accept
        counter packets 181 bytes 18684 return
    }
}
table inet lxd {
    chain pstrt.lxdbr0 {
        type nat hook postrouting priority srcnat; policy accept;
        ip saddr 10.5.62.0/24 ip daddr != 10.5.62.0/24 masquerade
        ip6 saddr fd42:dbed:893c:1f91::/64 ip6 daddr != fd42:dbed:893c:1f91::/64 masquerade
    }

    chain fwd.lxdbr0 {
        type filter hook forward priority filter; policy accept;
        ip version 4 oifname "lxdbr0" accept
        ip version 4 iifname "lxdbr0" accept
        ip6 version 6 oifname "lxdbr0" accept
        ip6 version 6 iifname "lxdbr0" accept
    }

    chain in.lxdbr0 {
        type filter hook input priority filter; policy accept;
        iifname "lxdbr0" tcp dport 53 accept
        iifname "lxdbr0" udp dport 53 accept
        iifname "lxdbr0" icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
        iifname "lxdbr0" udp dport 67 accept
        iifname "lxdbr0" icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, nd-router-solicit, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } accept
        iifname "lxdbr0" udp dport 547 accept
    }

    chain out.lxdbr0 {
        type filter hook output priority filter; policy accept;
        oifname "lxdbr0" tcp sport 53 accept
        oifname "lxdbr0" udp sport 53 accept
        oifname "lxdbr0" icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
        oifname "lxdbr0" udp sport 67 accept
        oifname "lxdbr0" icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } accept
        oifname "lxdbr0" udp sport 547 accept
    }
}
Janne Mattila
  • 101
  • 1
  • 4

1 Answers1

0

I had the same problem. As discussed on the LXD forums here the solution I found was to remove docker installed via apt and replace with docker from a snap.

# apt purge docker.io
# apt autoremove
# snap install docker
# reboot

The reason is that lxd wants to use nftables and apt docker also wants to use nftables, but it doesn't play nice with lxd. You cannot seem to force lxd to use iptables-legacy. But snap docker seems to use iptables-legacy, so they avoid each other.

Kimb0
  • 1