No Internet Connection inside Whonix-Workstation KVM with NordVPN with Kill-Switch on Host

Hello,

after successfully using Whonix on my M1 Mac via UTM without a VPN on my Host, I tried connecting my host to a VPN (I’m using NordVPN over OpenVPN), which is causing some unexpected problems:

  • With a VPN on my host, the Whonix Gateway’s internet seems to work without any issues (I did curl requests from the console and they all worked)
  • Even though the Gateway’s connection works, the Whonix Workstation cannot establish any internet connection while using a VPN on the host, even after several restarts of both the Gateway & Workstation and the Host

Running systemcheck on my Workstation shows

Tor Connection Result:
Tor’s Control Port could not be reached. Attempt 1 of 5. Could be temporary due to a Tor restart. Trying again…
[…]
(tor_circuit_established_check_exit_code: 255)
(tor_bootstrap_timeout_type: )
(tor_bootstrap_status: )
(check_socks_port_open_test: 56)

Any displayed troubleshooting steps do not help, as systemcheck runs without any issues on my Gateway.

Tor works fine via VPN on my host and I didn’t change any networking settings in UTM, just built Whonix for Silicon Macs as described in the docs and imported the output to UTM directly.

I would appreciate any troubleshooting ideas as I have no idea where the issue could originate from.

Looks weird, Because the WS taking the connection from GW, If GW working then WS will work as well. (i hope you are not trying to route the WS directly to the VPN, Because WS meant to connect only to GW).

Yeah I know, very weird. The VPN is running on my host and all curl requests I tested inside the GW worked.

But if I run a VPN on the host, I assume Whonix doesn’t even “know” about the VPN. That makes me think it has to be an issue on the host, but it’s weird that it works on the GW which on the other hand makes me think it’s something with Whonix.

I unfortunately have no idea how to troubleshoot this at all.

Update: The issue was related to NordVPN’s advanced Kill-Switch, which according to their Desktop app “might interfere with other network applications on your machine”. The same goes for ProtonVPN and many other VPN clients.

For now, I just deactivated the advanced Kill-Switch on the NordVPN client and everything works fine with a basic Kill-Switch still in place.

2 Likes

Thanks for the report! Moved to KVM forums.
Yeah, it makes sense. Since KVM network interfaces are visible on the host operating system, firewalls such as presumably what the NordVPN kill switch is doing can disrupt Whonix KVM.

I doubt this is fixable? @HulaHoop

@maxeth: You’d have to use a VPN kill switch (also called fail-closed mechanism) that is compatible with Whonix KVM. There is vpn-firewall but untested with Whonix KVM, I think. Also as per Avoid Non-Freedom Software I suggest to avoid the presumably non-freedom software NordVPN client and use a Freedom Software VPN client such as OpenVPN.

1 Like

There’s no legitimate excuse by any company to ever claim that it that it can’t support libre clients like OpenVPN.

I think that we support VPN → Tor on the GW to hide it from ISP (though this feature could be dropped in the future if it already isn’t deprecated).

Main issue being, a useful host firewall (without intention / can be Freedom Software) such as:

can break Whonix KVM.

related:

Fixable?

NordVPN seems to support OpenVPN too.
OpenVPN configuration files | NordVPN

In some countries Tor and the TorProject website are blocked by the government, as well as commercial VPN services, and bridges like obfs4/SnowFlake may be very unreliable and slow. In such cases self-hosted VPNs are highly needed to have an ability to use Tor. For example, after installing Whonix-Gateway I have to start OpenVPN client on the host to connect the Gateway to Tor, install Shadowsocks client on it(it is much faster than VPN) and then use it as a proxy in torrc. Yeah, a self-hosted VPS as a Tor bridge might be not a very good solution for privacy, but it might be the only way to normally use Tor for some users. Please, do not drop support for VPN → Tor on the GW.

Sounds dangerous to me. When the kill switch kills the connection, then adversaries can correlate the connection drop from your Mac to VPN with the connection that exits the VPN and is going to TOR entry and TOR exits, so you are de-anonymized every time your VPN connection drops without being a result of lost internet connection.

Without a VPN, that correlation can only be done if your internet connection drops.

Not that simple and the false positive rates would be so high as to render this type of traffic analysis useless.

KVM potential solution: Using hubport to avoid KVM network interfaces being visible on the host operating system

QEMU bug report:

1 Like

It’s possible to use unix domain socket files.

Relevant quotes from Proof-of-concept - Whonix on QEMU on Windows

start-whonix-gateway.bat:

-nic user,model=virtio-net-pci -netdev stream,addr.type=unix,addr.path=.\gateway.sock,server=on,id=whonixint -device virtio-net-pci,netdev=whonixint

start-whonix-workstation.bat:

-netdev stream,addr.type=unix,addr.path=.\gateway.sock,server=off,id=whonixint -device virtio-net-pci,netdev=whonixint

But that’s QEMU and needs to be translated to libvirt XML.
libvirt-dist/usr/share/libvirt-dist/xml at master · Kicksecure/libvirt-dist · GitHub

There is a related but not exact feature request:

Meanwhile it might be possible to use qemu:commandline in libvirt XML.

  <qemu:commandline>
    <qemu:arg value='-netdev'/>
    ...
  </qemu:commandline>
2 Likes

This is the libvirt feature request for this missing feature:

As a stopgap I highly recommend to work twoards:

That would probably be much more secure, fix host corridor and host VPN issues.

2 Likes

Claude code.

Whonix-Gateway:

  <!-- Whonix-Internal: isolated, point-to-point link between Gateway and one
       Workstation over an AF_UNIX socket. The Gateway owns the socket
       (server=on). A Workstation connects to it (server=off). Loopback-only
       file, no host routing and no internet on this link, so the Whonix
       isolation guarantee is preserved. Path uses the default "user" account
       runtime dir (uid 1000). Remove a stale socket file before restarting the
       Gateway. Only one Workstation can be attached at a time. -->
  <qemu:commandline>
    <qemu:arg value='-netdev'/>
    <qemu:arg value='stream,id=whonixinternal,server=on,addr.type=unix,addr.path=/run/user/1000/whonix-internal.sock'/>
    <qemu:arg value='-device'/>
    <qemu:arg value='virtio-net-pci,netdev=whonixinternal,mac=52:54:00:00:00:0a'/>
  </qemu:commandline>

Whonix-Workstation:

  <!-- Whonix-Internal: connect to the Gateway's AF_UNIX socket (server=off).
       reconnect-ms makes start order with the Gateway irrelevant; the
       Workstation retries until the Gateway's socket is available. The socket
       path is shared with Whonix-Custom-Workstation: only one Workstation can
       be attached to the Gateway at a time. -->
  <qemu:commandline>
    <qemu:arg value='-netdev'/>
    <qemu:arg value='stream,id=whonixinternal,server=off,reconnect-ms=1000,addr.type=unix,addr.path=/run/user/1000/whonix-internal.sock'/>
    <qemu:arg value='-device'/>
    <qemu:arg value='virtio-net-pci,netdev=whonixinternal,mac=52:54:00:00:00:0b'/>
  </qemu:commandline>

Whonix-Custom-Workstation:

  <!-- Whonix-Internal: connect to the Gateway's AF_UNIX socket (server=off).
       reconnect-ms makes start order with the Gateway irrelevant; the
       Workstation retries until the Gateway's socket is available. The socket
       path is shared with Whonix-Workstation: only one Workstation can be
       attached to the Gateway at a time. -->
  <qemu:commandline>
    <qemu:arg value='-netdev'/>
    <qemu:arg value='stream,id=whonixinternal,server=off,reconnect-ms=1000,addr.type=unix,addr.path=/run/user/1000/whonix-internal.sock'/>
    <qemu:arg value='-device'/>
    <qemu:arg value='virtio-net-pci,netdev=whonixinternal,mac=52:54:00:00:00:0b'/>
  </qemu:commandline>

Progress.

Untested! But looks promising.

Major changes:

  • rootless
  • using unix domain socket files
  • Images must now be placed in folder /home/user/.local/share/libvirt/images to avoid rootless usage.
  • Whonix-External.xml and Whonix-Internal.xml deleted because no longer required.
  • New host dependency: sudo apt install passt

Advantages:

Disadvantages:

  • Hardcoded paths:
    • Path to /home/user is literal and hardcoded. Users using a different Linux account name than “user” will need to adjust their XML file. As far as I know, libvirt does not support ~, "$HOME` or similar.
      • TODO: Please post and upstream feature request.
    • Path to unix doman socket files are stored in folder /run/user/1000 is similarly hardcoded. /run/user does not refer to account “user”. That’s just a constant independent of Linux user account names. And 1000 is a id --user, which will be different on user systems unfortunately.
      • TODO: See if there is a better path for the unix domain socket files.
  • XML files using <qemu:commandline>.
    • (Feature requests exist. Linked above.)

Branch:
GitHub - Kicksecure/libvirt-dist at rootless-kvm-session · GitHub

XML files in branch rootless-kvm-session:
libvirt-dist/usr/share/libvirt-dist/xml at rootless-kvm-session · Kicksecure/libvirt-dist · GitHub

Pull request:
port to rootless and unix domain sockets by adrelanos · Pull Request #119 · Kicksecure/libvirt-dist · GitHub

Diff (file changes):
port to rootless and unix domain sockets by adrelanos · Pull Request #119 · Kicksecure/libvirt-dist · GitHub

Observations:

Notes:

  • The source code changes have been assisted by Claude Code.
  • This forum post has been fully hand-written by myself.

TODO: @HulaHoop:

  • Please test, extend, fix, commit on top of my branch, edit wiki, etc.