Isolating AppVM Network Traffic in Qubes OS using Network Namespaces

Hello,

I’m trying to implement a feature in Qubes OS that would allow each AppVM to use a separate VPN tunnel, potentially with different providers and regions, simultaneously. To achieve this, I’m exploring the use of temporary network namespaces for each AppVM.

The idea is to create a new network namespace for each AppVM, and then establish a VPN tunnel within that namespace. This would allow each AppVM to have its own isolated network connection, with its own VPN configuration, without affecting the other AppVMs.

To make this work, I need to be able to:

  • Create a new network namespace for each AppVM
  • Move the AppVM’s vif from sys-firewall to the new namespace
  • Establish a VPN tunnel within the namespace
  • Route traffic from the AppVM through the VPN tunnel
  • Allow multiple AppVMs to have their own separate VPN tunnels, with different providers and regions, simultaneously

However, I’m experiencing a problem when I try to attach the AppVM’s vif from sys-firewall to the namespace. Whenever I do this, the AppVM is no longer able to route traffic properly, and nothing becomes pingable. It seems like the routing table is not being updated correctly, or the traffic is not being forwarded as expected.

I’ve tried using veth pairs to connect the network namespaces to sys-firewall, but I’m having trouble getting the traffic to be forwarded correctly. I’ve also tried enabling IP forwarding and setting up routes, but it’s not working as expected.

Can anyone provide guidance on how to achieve this in Qubes OS, or point me in the direction of any relevant documentation or examples? I’d appreciate any help or advice on how to make this work.

Below are the commands I set in the sys-firewall to make this work:

ip netns add test
ip link add veth0 type veth peer name veth1
ip link set veth1 netns test
ip link set <appvm_vif> netns test
ip netns exec test ip link set <appvm_vif> up
ip netns exec test ip link set veth1 up
ip link set veth0 up

After running these commands, the AppVM is no longer able to ping anything, and the routing table seems to be incorrect. Can anyone help me figure out what I’m doing wrong, or provide a working example of how to isolate an AppVM’s network traffic in Qubes OS?"

All this in a single netvm?

Yes, the idea would be to use sys-firewall for this, since it holds all the vifs for all the AppVms, so it is easier to use a single sys vm for this.

Why don’t you use create a separate sys-vpn for each VPN configuration you want to use, and then assign each of them to the right AppVM as network VM. You shouldn’t need to use namespaces nor touch sys-firewall at all for that. Or am I misunderstanding what you want to accomplish?

Simply put, creating a separate sys-vpn for each VPN configuration is not a scalable solution due to the significant resource allocation required to support each individual tunnel, resulting in a large footprint. You can always kill a fly with a cannon, but that would be suboptimal.
In contrast, leveraging network namespaces provides a more efficient and scalable approach, enabling dynamic management of multiple isolated network connections while minimizing resource utilization and overhead.

1 Like

It seems that no one has a clear answer to this question?

There is similar feature implemented already. It isn’t for VPN, but for extra NAT. Take a look at qubes-core-agent-linux/network/vif-qubes-nat.sh at main · QubesOS/qubes-core-agent-linux · GitHub and its usage in vif-route-qubes script.
This specific feature can be enabled by setting net.fake-ip feature on the AppVM (see qvm-features man page).

1 Like