There is nothing to do for the WireGuard interfaces. Qubes OS allows forwarding from a vif interface (client qubes) to the default route interface.
The new rules are there to prevent forwarding to happen on eth0. What’s good with them is that they are using a default table in nftables that is exposed by Qubes OS, so if for some reasons Qubes OS modify the rules in the running VPN qube, it should never alter those rules.
But I know how software suck, so it’s important to add rules in the VPN qube firewall (which are deployed on the netvm of that VPN qube)
Okay this is my install script for wg-quick.After running this and qubes-vpn-firewall-ip-and-ports.sh (in app and dom0) and adding the config files, you only have to add qubes-firewall in qvm-service and you are finished
Code
#!/bin/sh
if [ "$(id -u)" -ne 0 ]; then
echo "This script must be run as root." >&2
exit 1
fi
cat <<'EOF' > /rw/config/rc.local
#!/bin/sh
wg_conf_location="/home/user/wireguard"
mkdir -p /etc/wireguard
if [ -d "$wg_conf_location" ]; then
chmod -R 0600 "$wg_conf_location" && chmod 0700 "$wg_conf_location"/ && chown -R root:root "$wg_conf_location"
cp "$(find "$wg_conf_location" -type f -print0 | shuf -z -n 1 | tr -d '\0')" "/etc/wireguard/current.conf" && \
systemctl start wg-quick@current.service
fi
EOF
chmod 755 /rw/config/rc.local
cat <<'EOF' > /rw/config/qubes-firewall-user-script
#!/bin/sh
nft add rule qubes custom-forward oifname eth0 counter drop
nft add rule ip6 qubes custom-forward oifname eth0 counter drop
EOF
echo "Remember to activate qubes-firewall in the qvm-service tab"
cat <<'EOF' > /usr/local/bin/qubes-vpn-firewall-ip-and-ports.sh
#!/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-proxyvm ]; 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 [[ ! -f "$LIST_LOCATION" ]]; then
echo "list does not exist in specified location"
exit 1
fi
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=tcp
((counter++))
qvm-firewall "$HOSTNAME_TARGET" add --before "$counter" drop proto=udp
((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
EOF
chmod 755 /usr/local/bin/qubes-vpn-firewall-ip-and-ports.sh
echo "Remember to add the ip and port to the qvm-firewall rules in dom0..."
Major improvement would be translating these rules to nftables and adding them to the configs. Would be an additional killswitch. WireGuard Kill Switch - IVPN Help
PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT && ip6tables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT && ip6tables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
This is attempted translate with iptables-translate:
PostUp = nft insert rule ip filter OUTPUT oifname != "%i" mark != $(wg show %i fwmark) fib daddr type != local counter reject && nft insert rule ip6 filter OUTPUT oifname != "%i" mark != $(wg show %i fwmark) fib daddr type != local counter reject
PreDown= nft delete rule ip filter OUTPUT oifname != "%i" mark != $(wg show %i fwmark) fib daddr type != local counter reject && nft delete rule ip6 filter OUTPUT oifname != "%i" mark != $(wg show %i fwmark) fib daddr type != local counter reject
Haha tried to do with LLM not sure if the result if garbage:
PostUP = nft add rule inet filter output oifname "%i" mark != $(wg show %i fwmark) ipaddr != 127.0.0.1 drop && nft add rule inet filter output oifname "%i" mark != $(wg show %i fwmark) ip6 daddr != ::1 drop
PreDown = nft delete rule inet filter output oifname "%i" mark != $(wg show %i fwmark) ipaddr != 127.0.0.1 drop && nft delete rule inet filter output oifname "%i" mark != $(wg show %i fwmark) ip6 daddr != ::1 drop
Hi all,
I read a lot, but it seems guides are for adding a VPN for all traffic, while I need only to configure a VPN to access my house private network when I am outside, since when at home I do not it to be active.
It seems natural to me to add it to sys-net qubes, using NetworkManager, but since I am very new to Qubes OS, I am not sure which is the best practice in this case, any advice?
If you do not route all traffic, then you need to figure if you want to block all traffic that will not go through the VPN (so, not going to house network) or if you want to pass traffic.
If you want to block the traffic, this does not change much from the guide, in fact, it’s just a difference in the peer configuration in WireGuard configuration file that will list all subnets to route through the VPN.
If you do not want to block the traffic, it’s a lot easier:
I am in the second scenario, I do not need to block other traffic, but be able to access public internet + my private network, when I am not at home.
I think I have already tried what you suggest:
Created a sys-wg0 qube as describe in the guide, it is aphv based on fedora-41-xfce that uses sys-firewall as NetVM
I the created a qube Home that uses sys-wg0 as NetVM
When I open Firefox in Home then I am able to access hosts via the VPN, but when at home, I lost the possibility to reach other hosts on my local network, that are not exposed via the VPN.
Let’s says that the Wireguard VPN uses the subnet 10.1.0.0/24, while my home private network is using 10.2.0.0/24, then using the sys-wg0 as NetVM, I can access public internet and hosts on 10.1.0.0/24 but no more hosts on 10.2.0.0/24.
But why? If I am at home sys-net is connected to 10.2.0.0/24, and sys-wg0 uses sys-firewall as NetVM, addresses that are not routed to the VPN, so everything different from 10.1.0.0/24, should not go to the default gateway and so use sys-net?
So after some more debugging, it turns out that I can reach the host on the local network by IP but not by DNS, so I need to understand how to add my local router to the list of DNS servers