Qubes OS 4.2 nftables / nft firewall guide

Indeed!
But if you’re 100% sure that you’re running bash, it can be abbreviated to “&> file”

Yes…

This is impossible :smile:
You’re probably doing the redirection(s) in a wrong way.
If you read carefully my post (and @renehoj 's), you’ll see that.
(“Pedantic Note”)

Thanks guys, now the correct answer was: do chain add (does not fail if already exists), flush chain (OK if empty) then add all rules.
Perhaps the pedantic response should have been never discard stderr as the error may not be the one you are expecting, and then information is lost.
One still has to use list and grep if one needs a handle in nft.
Note that while 2 copies of bash say exactly the same version, they may behave differently because they come from different code bases. :wink:

1 Like

I am not using 4.2 but I use nftables on my GNU/Linux systems. Here is the setup from those systems which has worked well for me on (in case it may give you some useful ideas). Note that this is a setup for a personal workstation, not about a router. Unlike traditional setups, it also adds filtering to the outgoing packets too, thus not allowing any local software to connect in uncontrolled ways. I guess for a router output rules should be translated to forward rules.

#!/usr/sbin/nft -f

# https://wiki.codeemo.com/secure/nftables.html
# https://blog.samuel.domains/blog/security/nftables-hardening-rules-and-good-practices

flush ruleset

table netdev filter {
        chain ingress { 
                type filter hook ingress device eth0 priority -500;

                # IP FRAGMENTS
                ip frag-off & 0x1fff != 0 counter drop

                # IP BOGONS
                # From <https://www.team-cymru.com/bogon-reference.html>.
                ip saddr { \
                                0.0.0.0/8, \
                                10.0.0.0/8, \
                                100.64.0.0/10, \
                                127.0.0.0/8, \
                                169.254.0.0/16, \
                                172.16.0.0/12, \
                                192.0.0.0/24, \
                                192.0.2.0/24, \
                                192.168.0.0/16, \
                                198.18.0.0/15, \
                                198.51.100.0/24, \
                                203.0.113.0/24, \
                                224.0.0.0/3 \
                        } \
                        counter drop

                # TCP XMAS
                tcp flags & (fin|psh|urg) == fin|psh|urg counter drop

                # TCP NULL
                tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 counter drop

                # TCP MSS
                tcp flags syn \
                        tcp option maxseg size 1-535 \
                        counter drop
        }
}

table inet filter {
        chain input {
                type filter hook input priority 0; policy drop;
                # Allow traffic from established and related packets, drop invalid
                ct state vmap { established : accept, related : accept }
                ct state { invalid } counter drop
                # accept localhost traffic
                iif lo ip saddr 127.0.0.1 ip daddr 127.0.0.1 accept
#               tcp flags & (fin|syn|rst|ack) != syn ct state { new } drop
                # log all remaining packets
                log prefix "[nftables] in.dropped: "
        }
        chain forward {
                type filter hook forward priority 0; policy drop;
        }
        chain output {
                type filter hook output priority 0; policy drop;
                ct state { related, established } accept
                # accept localhost traffic
                oif lo ip saddr 127.0.0.1 ip daddr 127.0.0.1 accept
                # ssh, http, https, imap, smtp, pop, tor, tor browser
                tcp dport { 22, 80, 443, 465, 993, 995, 8080, 9001 } accept
                # chronyd, tcptraceroute
                udp dport { 123, 443 } accept
                icmp type { echo-request } accept
                # log all remaining packets
                log prefix "[nftables] out.dropped: "
        }
}

table inet mangle {
        chain prerouting {
                type filter hook prerouting priority -150;

                # CT INVALID
                ct state invalid counter drop

                # TCP SYN (CT NEW)
                tcp flags & (fin|syn|rst|ack) != syn \
                        ct state new \
                        counter drop
        }
}
1 Like

How do you use this? You are not supposed to write the firewall rules in the VPN qube, and modifying its netVm with nftables isn’t straightforward

How do you use this?

As noted, I don’t use it in Qubes OS but on bare metal GNU/Linux.

You are not supposed to write the firewall rules in the VPN qube, and modifying its netVm with nftables isn’t straightforward

What VPN qube? Isn’t the thread about having an nftables guide for QOS 4.2?

I mixed up topics sorry

for anyone unfamiliar with nftables syntax (I.E almost everyone :), but are familar with iptables syntax, there is iptables-translate.
If you give your iptables parameters to iptables-translate it will give you back some proposed nftables commands.
The targets may not be the same, so the commands might not work, but it’s quite a easy way to learn nftables syntax, so it might be worth mentioning.

(I know iptables-translate is part of the iptables package in debian. It probably is the same in other distributions as well)

1 Like

I have noticed that iptables-translate does not optimize the result and sometimes it is better to write shorter and simpler (as well as less repetitive) nftables rules manually.

1 Like

I agree. If you know nftables use nftables. If your lost, and don’t know the nftables equivilant to -A, it can be way faster to find it out by doing:
iptables-translate -A INPUT -s 1.1.1.1/24 -j ACCEPT
and getting:
nft add rule ip filter INPUT ip saddr 1.1.1.0/24 counter accept

rather then trying to look it up in a man page, or doing a google search on it, cause you already know exactly what the one side means.

1 Like

Agreed. Thanks for opening this topic, @Solene.

Btw, do you know why R4.2 used to work but the new update that made VPNs dysfunctional was viewed as an improvement? Were there leaks or security flaws? Online auditors and cli status showed my VPN configuration to be working with the values it was designed to. Is there something hidden in this iptables complexity you could elucidate?

And does anyone know what these “start” IPs refer to in the output highlighted here? What are -t -nat --flush PR-QBS all about? No simple path for Rise Up now, is there?

As a matter of fact, don’t forget that in R4.2, selinux is enabled by default, adding some more security but at the same time, making even a simple script startup from /rw/ more complex.

in R4.2, selinux is enabled by default

Is there any more detailed info (documentation) about it?

Whatever Mullvad VPN has done is compatible with the new configuration. If someone could figure out all that they did to make their GUI and integrations with Qubes other VPNs might be easier to make work.

So each VPN offering “framework” has a lot of specifics that need to be tailored to ip/nf tables now that whatever that was automating and streamlining the particulars it has been removed?

That means that if I want to make a remailer qube, yggdrasil, veilid, nym, freenet, etc I should definitely start by mastering iptables, right? Ambitious goal. But such a proposed muti-networking-modality computer would be an attractive acquisition…

They have been using nftables in their Linux application for quite some time, so it works on Qubes 4.2.

You need to learn the syntax of nftables and how it works. iptables is considered deprecated and is already replaced by nftables under the hood in some distributions.

iptables is considered deprecated and is already replaced by nftables under the hood in some distributions.

My information may be somewhat outdated but some months ago I have read that Android uses only iptables and most non-x86 architectures don’t support nftables at all. Of course, nftables is better and the way forward. Just sharing.

Of course!
4.2.0 Resease Notes
And, linked in the Release Notes:
SELinux support in Fedora qubes
(scroll towards the end, the thread starts in 2018)
On Feb 26 2023, marmarek (chapeau!) confirms that selinux is enabled by default in Fedora-based templates: Build Fedora templates with SELinux enabled from the start #7988

2 Likes

Ok. Read up on nftables. Still dont know how to, for starters, take an installation guide specific to Debian stable or bookworm and add something with nftables to make it work like it did before when R4.2 has iptables. nftables just organizes iptables more and corrects a few other security issues.

If you have trouble with nftables, you can still use iptables-translate to get any iptables rule into nftables syntax. The only thing to keep in mind is that Qubes has created its own table called “qubes”, so if you are using nft, you will need to refer to it in your command.
You have some examples in this PR:

I don’t know how it is in 4.2, but in 4.1, whenever I add an IPv6 address to the allow list, it does not show up in nft list ruleset. I wonder if this is a bug.

Can anyone using 4.2 check this?