The Secret Interplay Between OpenSnitch and nftables

I use NixOS and I have enabled its networking.nftables.enable = true; and networking.firewall.enable = true;. This means I get to use the default configuration of nftables on NixOS. Now, there are times when I wish to disable it. It is fairly easy to stop the firewall service: systemctl stop nftables does it. This automatically flushes the nftables ruleset and gives me freedom to do whatever I want.

Today, I wanted to run a small Debian VM, and I was in no mood to configure its networking, using QEMU’s SLiRP was the way. After creating the appropriate cloud-init files, here’s the command I ran:

qemu-system-x86_64 \
  -m 2048 \
  -smp 2 \
  -drive file=debian-12-genericcloud-amd64.qcow2,format=qcow2 \
  -netdev user,id=net0,hostfwd=tcp::2222-:22 \
  -device virtio-net,netdev=net0 \
  -nographic -drive file=cloud-init.iso,media=cdrom

But strangely, there was no Internet access inside the VM except for ICMP packets. Everything went fine when I flushed the nftables ruleset, but even after stopping nftables, no matter how many times I flushed the table via nft flush ruleset, these two tables kept coming back in a matter of seconds:

table inet mangle {
        chain output {
                type route hook output priority mangle; policy accept;
                meta l4proto != tcp ct state related,new queue flags bypass to 0
                tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0
        }
}
table inet filter {
        chain input {
                type filter hook input priority filter; policy accept;
                udp sport 53 queue flags bypass to 0
        }
}

What could it possibly be? At the first step, I learned about what queues are for in nftables. I had never seen them before. Queue statements in nftables are used to pass packets to userspace, just at that moment I knew which application it was. I use OpenSnitch to monitor which applications make what requests. OpenSnitch automatically added all these rules, no matter how many times I flushed the ruleset. As a program that needs to process packets, it makes sense for OpenSnitch to check for its rules, but it seemed frightening at first, when I didn’t know what was going on.

I was under the assumption that using eBPF, all packets are checked under OpenSnitch, but apparently only TCP packets with SYN flag, and new and related packets of other type are sent to OpenSnitch for further processing. Could a person use this to their advantage? If they have root access and can send malformed packets to initiate connections, then I guess so.

Have thoughts or questions? I'd love to hear them:

hossein.01 (Signal)
me@hossein.me

Want more articles like this one? Get notified of new posts by subscribing to the RSS feed or the email newsletter. I won't share your email or send spam, only blog posts.

Want more content now? This blog's archive has 28 ready-to-read articles. I also curate a list of cool URLs I find on the internet.

Find a mistake? This blog is open source, you can always open an issue.

Thanks for reading! ♡ All content on this blog is licensed under CC BY-SA 4.0, except where noted otherwise, or for third-party materials.