How to give no clue when connecting Qubes to network?

Hi,

Goals:

  • I’d like to only send encrypted traffic to the network, either from sys-whonix or from my VPN VMs.
  • My ultimate goal is that the network I am connecting to does not have any clue about me (except that I use the Tor network and that I use VPN providers).
  • No clue about me means e.g. no clue that I use Qubes.

Topology:

  • sys-whonix and my VPN VMs are connected to disp-sys-firewall.
  • disp-sys-firewall is connected to disp-sys-net (which is obviously connected to the network)

Problems I see: disp-sys-firewall & disp-sys-net send unencrypted traffic to the network, like…

What I’d like to filter:

  1. IPv6 broadcasts
  2. NTP traffic
  3. DNS requests, APT updates, Others?

How I think to do it:

  1. IPv6 broadcasts
    Disable IPV6 with sysctl in the template of disp-sys-net

  2. NTP
    I tried to configure my clockVM to be my UpdateVM (which goes through my VPN VM). Unfortunately, I had time problems with this solution. (See Question 2 here below)

  3. Use qvm-firewall in dom0 for disp-sys-net, only allowing traffic to:

    • DHCP port (to get a DHCP config)
    • my Tor guard
    • the servers of my VPN providers

Questions:

  1. What problem(s) do you see with that plan? What am I missing?
  2. Do you have a solution for the NTP problem?

Thank you very much for your attention and answers!

Interesting question. I think I will implement something like that in my setup.
I believe the way you described should work. Please keep us posted on how it is going for you.

So, Qubes probably uses sys-net to synchronize the clock of all VMs, perhaps there is a way to change that to a VM that is downstream from sys-vpn. Another options is to configure sys-net to use NTS instead.

Edit: if I’m not mistaken, the DHCP protocol sends your hostname, so maybe change sys-net for a more stealthy name.

What issues did you have?

It should be as simple as setting your ClockVM to an AppVM with the clocksync service enabled. Is a minimal template in use? The right software may not be installed.

I’m not sure it works like that. qubes-firewall for a VM is enforced on the NetVM (or ProxyVM) of that VM. You’d have to make additional iptables/nft changes in sys-net via user firewall rules to block outgoing traffic from sys-net. A DNS failsafe could be to use dnsmasq in sys-net as your DNS server (127.0.0.1) that blocks all.

The only Qubes-identifying network traffic is performing updates, as those will reach out to {yum,deb}.qubes-os.org. Use an UpdateVM where Tor or a VPN is upstream and don’t worry about it.

The other is DHCP as the client host name will be ‘sys-net’. Rename sys-net to something else, or use random hostname generation if DHCP is used. Or, don’t use DHCP; there’s no need for DHCP if the network details are already known.

All other traffic is specific to the OS inside your qubes.

It sounds like you want to eliminate all traffic generated by sys-net itself, not necessarily qubes-identifying traffic. In that case I’d leave NetworkManager out, use manual network config, and use user-specified iptables rules to whitelist only the stuff you expect.

Here we go…

I tried to use those 3 commands:

sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=1

in the /rw/config/rc.local of the sys-usb-dvm template of my disp-sys-usb VM where I put a wifi USB dongle.

Didn’t work: When my usb dongle connected to a wifi network, I got an IPv6 address for the interface (ip a command) and saw IPv6 trafic on wireshark.

I created a stealh.sh script in my sys-usb-dvm template that I can run on my disp-sys-usb VM before connecting to a wifi network. First lines of stealh.sh are:

# Disable IPv6
sudo ip6tables -I OUTPUT 1 -j DROP
sudo ip6tables -I FORWARD 1 -j DROP

The FORWARD rule ensures there is no traffic that can be forwarded from downstream VMs.

Looks like it works fine this time!

Didn’t investigate more for the moment.

The clocks on (some of? all of? don’t remember exactly!) my VMs were completely off. Particularly troublesome on my mail VM and on my Signal VM…

From memory, I think that’s what I did.

Definitely not!

Exactly so! By the way, may I take this opportunity, @icequbes1, to thank you for all the good info you put in this forum in general and in this thread in particular. I found it when experiencing with my ideas.

Exactly what I did. Consequently, the next lines of stealth.sh are:

# Allow traffic through [VPN Provider Redacted]
sudo iptables -I FORWARD 3 -j ACCEPT -p udp --dport [Port of 1st VPN Server Redacted]  -d [IP of 1st VPN Server Redacted]  
sudo iptables -I FORWARD 4 -j ACCEPT -p udp --dport [Port of 2nd VPN Server Redacted]  -d [IP of 2nd VPN Server Redacted]  
etc.
sudo iptables -I FORWARD 3+n  -j DROP

I inserted rules in the FORWARD chain from number 3 on since I wanted to preserve the 2 already existing rules:

  1. state INVALID and
  2. ctstate RELATED,ESTABLISHED

NB: n is the number of VPN server of your VPN provider.

Rule “3+n” drops anything from downstream VMs that does not have a VPN server as a destination.

Finally:

sudo iptables -P OUTPUT DROP

since no trafic should originate from this machine, since it would be unencrypted.

I’m not sure to have ever fully understood the details of the templates updates in Qubes. I know the templates are updated through a VM defined on /etc/qubes-rpc/policy/qubes.UpdatesProxy and that this VM runs a qubes-updates-proxy service.

Nevertheless, when not using my stealth.sh script, I see HTTP traffic on wireshark originating from the VM connected to wifi that very looks like update traffic. Moreover, Qubes suggests me to update some of my templates only after I open an AppVM using that template.

My conclusion is that it is the dispVMs or appVMs that trigger the updates of their templates after reaching to their repositories. The templates then use the qubes-updates-proxy running on the VM defined in /etc/qubes-rpc/policy/qubes.UpdatesProxy to update themselves.

I’d love if someone could confirm this. Thanks in advance!

If this is confirmed, then using an UpdateVM where Tor or a VPN is upstream is not enough (because of the HTTP traffic originating from the VM connected to wifi triggering the update process). Or do I miss something?

That (or clone it to use it as the stealth VM) is indeed the easiest because…

… I gave a (quick) try to that script without success.

It looks like that sys-whonix needs to reach many servers when starting. It’s impossible (or demands much more energy than I’m willing to put) to whitelist all the Tor nodes. My workaround is to send sys-whonix through my VPN provider when using my stealth.sh script.

On another topic, I saw (Q Menu → sys-whonix → Tor Control Panel → Utilities tab → onion circuits ) that all my connections to the Tor network flow through 2 or 3 guards (entry points in the Tor network) and that some of them change from one day to another. Question: How is it possible to not have only one Tor guard?? Thanks is advance!!

I see we came to the same conclusion! :wink:

Some thoughts:

/rw/config/rc.local runs after the network comes up.
That’s why your IPv6 effort failed.

The right way to disable IPv6 is to use qvm-features:
qvm-features <qube> ipv6 ''

NTP is UDP based - it wont work under Tor, or some VPNs.

Updates - Yes, the qubes check for updates, and information is passed
up to dom0.
You can turn this behaviour off in the GUI, or in qvm-features by
disabling check-updates.

sys-net hostname - you can randomise the hostname or (better imo) stop
dhcp from sending the hostname at all.

As well as editing your firewall entries, I would recommend shutting
down all unwanted/unnecessary services in dom0 and sys-firewall, to
limit outgoing traffic. Why generate the traffic and then hope to block
it?

Ah yes - as @unman said it can be disabled by making sure the qubes-update-check service is disabled. I personally have the “Check for qube updates by default” option unchecked in Qubes Global Settings and forgot about it in this case.