Wireguard VPN setup

there are some specific changes for the minimal template, like installing and enabling network manager, or how to run a command as root :slight_smile:

Ahhh ok. I had that already taken into account when setting up the template. Probably the reason why it is been working with your guide so smoothly.
I wrote up some bash scripts for setting up minimal templates even from dom0. It is not as sophisticated as salt but it is doing its job and might be a little easier to understand for Qubes beginners like me:

I have pretty much the same problem here. I tried to set up a sys-vpn via ivpn on a StandaloneVm fedora-41-xfce,also tried via Template then AppVm. In both the app version and the wireguard set up I have a connection and can ping servers as 9.9.9.9 .
But when tryin to browse it doesnt work. I can also acces the sys-vpn as a net qube from a different qube same symptoms. I tried without, with the DNS hardening with 9.9.9.9 as DNS, and with the DNS provided by my VPN Provider.

I dont know what else to try
Thanks in advance

Having issues with sys-vpn AppVM connectivity using wireguard setup in Network Manager. Trying to ping the ip address of an external ip will fail, either with no response or “Destination Host Unreachable ping: sendmsg: Destination address required”.

Using cmd systemd-resolve google.com gives “google.com: resolve call failed: All attempts to contact name servers failed”

Now comes the strange part. Sometimes I can simply switch to a another vpn server in Network Manager and connectivity is restored. Other times, say 20%, this does not work. Restarting the sys-vpn qube usually doesn’t work, but rarely it will.

‘resolvectl status’ shows the Wireguard tunnel as the default route with the correct DNS ip.

Is anyone else experiencing this?

Looks like it’s not a DNS problem as you can’t ping an IP.

Check the status of the VPN using sudo wg and see if there are data in rx and tx lines. (wireguard-tools package is needed, not sure it’s installed by default)

After installing wireguard-tools ‘sudo wg’ shows no rx or tx lines

Then had to switch vpn twice to get connectivity. Now it show the rx and tx info.

Did you notice a huge difference in the command output except the tx/Rx lines? If they are not present, this mean there is the wireguard tunnel started which would be weird, but this would explain your issue.

Went back and had a closer look. The peer endpoint is missing from the output. Why would this happen?

Is it correctly defined in network manager? I don’t know how this is possible to be honest.

I can see the Endpoint as “domain name:port” in the wg config files I imported into network manager.

In the network manager settings the endpoint isn’t shown.

At least you certainly found why the VPN were not all working. But if you used nmcli import, I wonder what went wrong with these files :thinking:

Ok so I created a new wg config using the ip address of the endpoint and not as a domain as in the original configs. Now there are no connection issues and the tunnel comes up correctly.

So it seems using the endpoint’s domain name in the config files causes the problem. Still doesn’t explain how disconnecting and reconnecting the vpn in network manager allows it to connect using the domain name configs though.

Seems the DNS lookup of the endpoint fails during network manager wg startup for some reason.

Anyway thanks for your help troubleshooting Solene

The domain name may resolve to a different address in the future, but using a DNS name in the endpoint can also create troubles if you do not allow DNS traffic before the VPN is connected :sweat_smile:

From the sys-vpn firewall DNS traffic is allowed. Perhaps it’s blocked somewhere else.

My experience: When I added the vpn configuration to sys-vpn with nmcli everything worked well, but on a sys-vpn reboot, the vpn was not working until I cycled the vpn connection, either via the gui or nmcli down/up.

I eventually figured out that Qubes is adding the uplink connection to net vm after NetworkManager has already started the vpn. You can confirm this by checking the timestamp of /rw/config/NM-system-connections/qubes-uplink-eth0: it’s recreated at every boot after rc.local has run, so even rc.local scripting wasn’t fixing it.

My solution was to disable the vpn from auto connecting through the gui and manually enabling it after sys-vpn starts up. This also allowed me to have several VPNs to pick from without a default one starting.

The firewall rules on sys-vpn in the Qube Manager prevent the downstream vm from accessing the network through it, other than DNS (which by default was running through Qubes) which I handled in their systemd-resolved configurations.

/rw/config/resolve.conf

[Resolve]
DNS=<MY VPN's DNS>
Domains=~.

/rw/config/rc.local

ln -s /rw/config/resolved.conf /etc/systemd/resolved.conf
systemctl --no-block restart systemd-resolved.service`

No problem here on all my VPN qubes, whether running debian or fedora. Are you using a domain name as the endpoint address?

I did nothing except importing the config in network manager and letting it in automatic. Make sure you don’t have multiple VPNs enabled at the same time.

Is this Good Enough for quic to work reliabily, without issues, in practice? It’s not sufficient for wireguard-in-wireguard, right? You must explicitly set a lower mtu on the “inner” wireguard vm interface?

I think those are problematic with the clamp approach, in theory. But I religiously set mtu explicitly when behind tunnels, because I’ve been burned. so I’m not certain.

I do use clamp, though. It’s a clever hack. I just don’t rely on it for my use-case

EDIT: Forgot to explicitly state “… because they’re UDP”, for any who read this that are not familiar with mss

I have written a script that can extract the ip and port and create firewall rules in dom0 automatcily for thousands of config file at the same time. Appears to work great but some feedback would be nice

You have to run it once in the vpn qube and then in dom0. In the vpn qube you have to provide a directory with wireguard config files also it must be a proxyvm

Code
#!/bin/bash
# dom0 get the file qvm-run --pass-io vpn-test 'cat /home/user/ip_and_port.txt' > $HOME/ip_and_port.txt

LIST_LOCATION="$HOME/ip_and_port.txt"

usage() {
  echo "Usage: $0 [--hostname TARGETVM] [--directory DIR] [--list-location FILE]"
  exit 1
}

while [[ "$#" -gt 0 ]]; do
  case "$1" in
  --hostname)
    shift
    HOSTNAME_TARGET="$1"
    ;;
  --directory)
    shift
    DIRECTORY="$1"
    ;;
  --list-location)
    shift
    LIST_LOCATION="$1"
    ;;
  *)
    echo "Unknown parameter: $1"
    usage
    ;;
  esac
  shift
done

if [ -f /run/qubes/this-is-netvm ]; then
  if [[ -z "$DIRECTORY" ]]; then
    echo "Error: --directory is not set."
    exit 1
  fi
  if [[ -z "$HOSTNAME_TARGET" ]]; then
    HOSTNAME_TARGET=$(hostname)
  fi
  echo "$HOSTNAME_TARGET" >"$LIST_LOCATION"

  find "$DIRECTORY" -type f -name "*.conf" | while read -r conf_file; do
    grep 'Endpoint' "$conf_file" | while read -r line; do
      ip=$(echo "$line" | cut -d'=' -f2 | awk '{print $1}' | cut -d':' -f1)
      port=$(echo "$line" | cut -d'=' -f2 | awk '{print $1}' | cut -d':' -f2)
      echo -e "$ip\t$port" >>"$LIST_LOCATION"
    done
  done

else
  read -p "Your are in dom0 and want to Proceed? (y/n): " ans && [[ "$ans" =~ ^[Yy]$ ]] || {
    echo "Canceled"
    exit 1
  }

  if [[ -z "$HOSTNAME_TARGET" ]]; then
    HOSTNAME_TARGET="$(head -n 1 <"$LIST_LOCATION")"
  fi
  qvm-firewall "$HOSTNAME_TARGET" reset
  counter=0

  while IFS=$'\t' read -r ip port; do
    qvm-firewall "$HOSTNAME_TARGET" add --before "$counter" accept proto=udp dstports="$port" dsthost="$ip/32"
    ((counter++))
  done < <(tail -n +2 "$LIST_LOCATION")

  qvm-firewall "$HOSTNAME_TARGET" add --before "$counter" drop specialtarget=dns
  ((counter++))
  qvm-firewall "$HOSTNAME_TARGET" add --before "$counter" drop proto=icmp
  ((counter++))
  qvm-firewall "$HOSTNAME_TARGET" add --before "$counter" drop
  ((counter++))
  qvm-firewall "$HOSTNAME_TARGET" del --rule-no "$counter"
  qvm-firewall "$HOSTNAME_TARGET" list
fi
1 Like

Hi, thanks so much for this useful guide! What do you think to update it to use with Fedora MINIMAL version to improve security? maybe some notes aside? e.g i see that you also need to install NetworkManager (not installed by default on minimal) other than “enable” the service as you wrote in the guide. thank you

It should work - it definitely works with debian-12-minimal… You have to add some Qubes packages, mainly:

  • qubes-core-agent-networking
  • qubes-core-agent-network-manager
  • wireguard
  • wireguard-tools
2 Likes