[Workshop] Block traffic from sys-net and sys-firewall but allow NAT

Hi

Seems there is a real need from users, I’d like to figure a solution that would block the network traffic emitted by sys-firewall and sys-net, but let qubes below sys-firewall to have network.

The point would be to allow someone using sys-whonix or a VPN to have no leak. This can’t come with any guarantee of course, a gateway device providing the network should be used as a firewall if someone really needed to ensure there will never be any leak.

So far, I figured a simple command to block traffic from sys-firewall and sys-net, it seems to work fine so far

sudo nft add chain ip qubes output '{type filter hook output priority 0; policy drop; }'
  • this is not a permanent change (a guide will be written to make it properly)
  • not sure the rule will stay if qubes os does something with the firewall. I don’t think so as I’ve been using custom NAT rules for a year without issues, but a better proof would be useful
  • so far, it does not block ipv6
  • it breaks DNS (but if you need this, you already use a DNS by Tor or through a VPN, so this is not a problem)
2 Likes

Can you elaborate more on the use case?
Isn’t using qvm-firewall sufficient for most use cases? Also, sys-whonix uses it’s own firewall rules, and corridor can be added to the chain to allow Tor relay nodes only.

Recently, some users were disappointed to read that sys-firewall and sys-net were doing network requests on their own. Both these qubes can not really be blocked by qvm-firewall as it would just break the network, and as a firewall rule is applied on a netvm, sys-net does not have a netvm, so :woman_shrugging:

I tried to isolate sys-net from requests by setting sys-firewall net qube to none and I ran tcpdump on sys-net for outgoing requests for a while and other than ARP I didn’t see anything else trying to come out of it.

sys-firewall and sys-net are both minimal based, so a lot of things are stripped out, I’m not sure if it would be the same for the classic fedora templates.

It should check for updates once in a while, except if you manually disabled update checks for this qube. I think one of the two is also used for DNS resolving.

In any case, you can monitor easily what’s it is doing, but filtering it is a different job.

Both sys-firewall and sys-net have in fact update checking disabled. I’ve been doing this for a while because I knew it would bypass any filter or proxy services, it’s available to do quite easily in the Qubes Global Config tool in the Updates tab by adding needed qubes to the exception list.

At least on the minimal templates, I don’t see any running processes that could be sending outgoing requests. I’m not really sure about the classic ones. I’ll leave a disposable fedora-41-xfce qube on a side with tcpdump and see if it makes any calls in the next hours.

For example:

sys-net → sys-firewall → vpn → vpn-firewall → appvm?

And for sys-whonix isn’t it better to use corridor?

this does not change this change, the point is only to block any traffic generated by sys-net and sys-firewall.

sys-whonix should leak nothing in the current state

Hello. Does this need to be done inside sys-net? Can you give an example of what should be here?
{type filter hook output priority 0; policy drop; }

You would need to run it in sys-net AND sys-firewall. There is nothing more to add in the rule.

This rule explained means that all output traffic is dropped (opposite of accepted). It works because there are no other output chain in Qubes OS rule set, so the priority does not matter. It does not break traffic done by other qubes because in their case, the network is filtered in a chain forward and not output.

This is an excellent start. I wrote some time ago (last year?) that the way to separate locally generated traffic from NAT-ed traffic, at nftables level, is to use the “output” chain - which only matches locally generated traffic. (here)
Another idea is to use iproute2’s network namespaces to separate the physical devices from the (vpn) tunnels, and drop all traffic except for the tunnel traffic.
Both solutions require changing the firewall rules on the sys-XXX appVMs and can’t be implemented “the Qubes way” :tm:

I can’t get my head around this setup, why would you use a netns for a VPN and where?

I don’t understand, it’s far easier to work with a VPN and restrict the traffic using a dedicated qube to establish the VPN.

Such setup would be useful when not using Qubes OS and you want to be able to use a VPN among multiples running in parallel (or stacking VPNs :slight_smile: )

It seems to me that qubes interference with the sys-net firewall can occur at startup time, and as long as the adapter is not connected to the sys-net network, it can accept the rule blocking traffic. Of course, this will not work with a wired adapter, then this can be solved with the help of the systemd unit, which is activated before the start of the network.

The topic name says “but allow nat”, but I don’t see an explanation for this. Can you clarify?

Think of it as plumbing. sys-net is providing Internet flow, but is also using the flow for itself. You do not want to block the entire flow, otherwise qubes below will not receive it, so you just want to block sys-net from using it while allowing other qubes to join the flow.

Same for sys-firewall.

1 Like

Update: There were no outgoing requests after 10 hours, except for the update check, which I intentionally left active. Otherwise, I got a lot of IPv6 outgoing multicast requests that don’t go anywhere anyway.

Right - that’s more for stopping local traffic from a sys-vpn construct… but we can already achieve this using qvm-firewall.
Was enumerating the method as a possible way of separating traffic. Not very relevant in the Qubes context.

1 Like

You could also have multiple routes on the same network namespaces and use routing rules to use a VPN or not. It’s more practical than network namespaces in some cases.

2 Likes