fix: sys-wireguard compatible with Qubes 4.2

This commit is contained in:
Ben Grande 2024-01-08 20:07:20 +01:00
parent 42a93093dd
commit c306047f1e
18 changed files with 207 additions and 228 deletions

View File

@ -9,8 +9,7 @@ and will be introduced in the meantime. You've been warned.
The following projects are unfinished (not a complete list):
- sys-wireguard: unfinished firewall port to nft, waiting for R4.2
- sys-syncthing: broken firewall script functionality with disposable netvm
- sys-syncthing: broken firewall script due to nftables and disposable netvm
Other projects might also have drastic changes, the above are simply not ready
at all.

View File

@ -32,16 +32,17 @@ qubesctl --skip-dom0 --targets=sys-wireguard state.apply sys-wireguard.configure
```
<!-- pkg:end:post-install -->
To add the VPN configuration and configure the qubes firewall:
```sh
/srv/salt/qusal/sys-wireguard/files/admin/setup-sys-wireguard.sh
```
## Usage
Use the VPN qube `sys-wireguard` to enforce incoming and outgoing connections
from clients connected to the VPN with a fail safe mechanism.
To start using the VPN:
1. Copy the Wireguard configuration you downloaded to `sys-wireguard` and
place it in `/home/user/wireguard.conf`.
2. Run from Dom0 to apply Qubes Firewall rules: `qvm-wireguard`
## Credits
- [Unman](https://github.com/unman/shaker/tree/main/mullvad)

View File

@ -5,13 +5,8 @@ SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
"{{ slsdotpath }}-config-vpn":
file.directory:
- name: /rw/config/vpn
- user: root
- group: root
- mode: '0755'
- makedirs: True
include:
- dev.home-cleanup
"{{ slsdotpath }}-rc.local":
file.managed:
@ -22,38 +17,22 @@ SPDX-License-Identifier: AGPL-3.0-or-later
- mode: '0755'
- makedirs: True
"{{ slsdotpath }}-wg-conf.sh":
file.managed:
- name: /home/user/wg-conf.sh
- source: salt://{{ slsdotpath }}/files/server/wg-conf.sh
- mode: '0755'
- user: user
- group: user
- makedirs: True
"{{ slsdotpath }}-firewall-filter":
file.managed:
- name: /rw/config/qubes-firewall.d/60-sys-wireguard-filter
- source: salt://{{ slsdotpath }}/files/server/qubes-firewall.d/60-sys-wireguard-filter
- mode: '0755'
"{{ slsdotpath }}-qubes-firewall":
file.recurse:
- name: /rw/config/qubes-firewall.d/
- source: salt://{{ slsdotpath }}/files/server/qubes-firewall.d/
- dir_mode: '0755'
- file_mode: '0755'
- user: root
- group: root
- makedirs: True
"{{ slsdotpath }}-firewall-flush":
file.managed:
- name: /rw/config/network-hooks.d/flush.sh
- source: salt://{{ slsdotpath }}/files/server/flush.sh
- mode: '0755'
"{{ slsdotpath }}-network-hooks":
file.recurse:
- name: /rw/config/network-hooks.d/
- source: salt://{{ slsdotpath }}/files/server/network-hooks.d/
- file_mode: '0755'
- dir_mode: '0755'
- user: root
- group: root
- makedirs: True
"{{ slsdotpath }}-firewall-flush-rules":
file.managed:
- name: /rw/config/network-hooks.d/flush
- source: salt://{{ slsdotpath }}/files/server/flush
- user: root
- group: root
- makedirs: True
- mode: '0755'

View File

@ -35,3 +35,12 @@ features:
- service.tinyproxy
{%- endload %}
{{ load(defaults) }}
"{{ slsdotpath }}-qvm-wireguard":
file.managed:
- name: /usr/local/bin/qvm-wireguard
- source: salt://{{ slsdotpath }}/files/admin/qvm-wireguard
- user: root
- group: root
- mode: '0755'
- makedirs: True

View File

@ -1,14 +0,0 @@
# SPDX-FileCopyrightText: 2022 unman <unman@thirdeyesecurity.org>
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
[Desktop Entry]
Type=Application
Exec=/usr/bin/setup-sys-wireguard
Icon=qubes-manager
Terminal=false
Name=Setup sys-wireguard
GenericName=Setup sys-wireguard
StartupNotify=false
Categories=Settings;X-XFCE-SettingsDialog

View File

@ -0,0 +1,46 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2022 unman <unman@thirdeyesecurity.org>
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
test "$(id -u)" = "0" || exec sudo "$0" "$@"
qube="${1:-"sys-wireguard"}"
if ! qvm-check -q "$qube" >/dev/null 2>&1; then
echo "Qube '$qube' doesn't exist" >&2
exit 1
fi
qvm-run "$qube" -- test -f /home/user/wireguard.conf || {
echo "File /home/user/wireguard.conf was not found" >&2
exit 1
}
## TOFU
# shellcheck disable=SC2016
endpoint="$(qvm-run -p "$qube" -- awk '/Endpoint/{print $3}' /home/user/wireguard.conf)"
ip="$(echo "$endpoint" | cut -d ":" -f 1)"
port="$(echo "$endpoint" | cut -d ":" -f 2)"
if test -z "$ip" || test -z "$port";then
echo "Endpoint (IP:Port) not found in /home/user/wireguard.conf" >&2
exit 1
fi
if qvm-check -q --running "$qube" >/dev/null 2>&1; then
qvm-pause --verbose "$qube"
fi
echo "Firewalling $qube"
qvm-firewall --verbose "$qube" reset
qvm-firewall --verbose "$qube" del --rule-no 0
qvm-firewall --verbose "$qube" add accept dsthost="$ip" dstports="$port" proto=udp
qvm-firewall --verbose "$qube" add accept dsthost="$ip" dstports="$port" proto=tcp
qvm-firewall --verbose "$qube" add drop
if qvm-check -q --paused "$qube" >/dev/null 2>&1; then
qvm-unpause --verbose "$qube"
fi

View File

@ -1,47 +0,0 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2022 unman <unman@thirdeyesecurity.org>
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
qube="sys-wireguard"
if qvm-check -q "$qube" >/dev/null 2>&1; then
echo "Qubes doesn't exist: $qube" >&2
exit 1
fi
qvm-run -p "$qube" '/home/user/set-wg-conf.sh'
if ! qvm-run -p "$qube" 'test -f /home/user/wireguard.conf'; then
qvm-run -u root "$qube" /home/user/install-sys-wireguard
qvm-run -p "$qube" 'test -f /home/user/wireguard.conf' || exit
fi
## TOFU
# shellcheck disable=SC2016
endpoint="$(qvm-run -p "$qube" -- awk '/Endpoint/{print $3}' /home/user/wireguard.conf)"
ip="$(echo "$endpoint" | cut -d ":" -f 1)"
port="$(echo "$endpoint" | cut -d ":" -f 2)"
if test -z "$ip" || test -z "$port";then
echo "Endpoint (server ip:port) not found in /home/user/wireguard.conf" >&2
exit 1
fi
if qvm-check -q --running "$qube" >/dev/null 2>&1; then
qvm-pause "$qube"
fi
qvm-firewall "$qube" reset
qvm-firewall "$qube" del --rule-no 0
qvm-firewall "$qube" add accept proto=tcp dstports=53
qvm-firewall "$qube" add accept proto=udp dstports=53
qvm-firewall "$qube" add accept dsthost="$ip" proto=udp dstports="$port"
qvm-firewall "$qube" add drop
if qvm-check -q --paused "$qube" >/dev/null 2>&1; then
qvm-unpause "$qube"
fi

View File

@ -0,0 +1,11 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
ln -sf /run/resolvconf/resolv.conf /etc/resolv.conf
/rw/config/qubes-firewall.d/50-sys-wireguard-var
nft -f /rw/config/qubes-firewall.d/60-sys-wireguard-nat

View File

@ -1,12 +0,0 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
echo "define qube_ip = $(qubesdb-read /qubes-ip)" \
| tee /rw/config/vpn/qube-ip.nft >/dev/null
nft -f /rw/config/vpn/dns-hijack.nft
## TODO: read https://www.wireguard.com/netns/

View File

@ -0,0 +1,48 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
wg_conf="/home/user/wireguard.conf"
nft_conf="/var/run/wireguard/dnat.nft"
mkdir -p /var/run/wireguard/
rm -f "${nft_conf}"
touch "${nft_conf}"
set_nft(){
echo "${*}" | tee -a "${nft_conf}" >/dev/null
}
set_nft_dnat(){
ipv="${1}" # empty(4), 6
proto="${2}" # tcp, udp
dns_host="${3}"
set_nft "insert rule ip${ipv} qubes custom-dnat iifgroup 2 ${proto} dport 53 dnat to ${dns_host}"
}
dns="$(grep -s "^\s*DNS\s*=\s*\S\+" "${wg_conf}" | sed "s/.*=//;s/ //g")"
dns_primary="$(echo "${dns}" | cut -d "," -f 1)"
dns_secondary="$(echo "${dns}" | cut -d "," -f 2)"
dns_primary_ipv=""
if echo "${dns_primary}" | grep -qF ":"; then
dns_primary_ipv=6
fi
dns_secondary_ipv=""
if echo "${dns_secondary}" | grep -qF ":"; then
dns_secondary_ipv=6
fi
if test -n "${dns}"; then
set_nft_dnat "${dns_primary_ipv}" udp "${dns_primary}"
set_nft_dnat "${dns_primary_ipv}" tcp "${dns_primary}"
if echo "${dns}" | grep -qF ","; then
set_nft_dnat "${dns_secondary_ipv}" udp "${dns_secondary}"
set_nft_dnat "${dns_secondary_ipv}" tcp "${dns_secondary}"
fi
fi

View File

@ -0,0 +1,43 @@
#!/usr/sbin/nft -f
# vim: ft=nftables
# SPDX-FileCopyrightText: 2022 unman <unman@thirdeyesecurity.org>
# SPDX-FileCopyrightText: 2023 1cho1ce <https://github.com/1cho1ce>
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: GPL-3.0-or-later
add chain ip qubes output { type filter hook output priority 0; policy accept; }
add chain ip6 qubes output { type filter hook output priority 0; policy accept; }
## Stop leaks between downstream (vif+) and upstream (eth0)
#chain ip qubes forward { policy drop; }
#chain ip qubes input { policy drop; }
#chain ip qubes output { policy drop; }
#chain ip6 qubes forward { policy drop; }
#chain ip6 qubes input { policy drop; }
#chain ip6 qubes output { policy drop; }
insert rule ip qubes custom-forward oifgroup 1 drop
insert rule ip qubes custom-forward iifgroup 1 drop
insert rule ip6 qubes custom-forward oifgroup 1 drop
insert rule ip6 qubes custom-forward iifgroup 1 drop
## Accept forward traffic between dowstream vif+ (group 2) and VPN (group 9)
#insert rule ip qubes custom-forward iifgroup 2 oifgroup 9 accept
#insert rule ip qubes custom-forward iifgroup 9 oifgroup 2 accept
#insert rule ip6 qubes custom-forward iifgroup 2 oifgroup 9 accept
#insert rule ip6 qubes custom-forward iifgroup 9 oifgroup 2 accept
## Drop ICMP
insert rule ip qubes custom-input meta l4proto icmp drop
insert rule ip6 qubes custom-input meta l4proto icmp drop
insert rule ip qubes output oifgroup 1 meta l4proto icmp drop
insert rule ip6 qubes output oifgroup 1 meta l4proto icmp drop
## Allow traffic from the "qvpn" group to the uplink interface (eth0);
## Our VPN client will run with group "qvpn".
#insert rule ip qubes output oifname "lo" accept
#insert rule ip qubes output oifgroup 1 skgid "qvpn" accept
#insert rule ip6 qubes output oifname "lo" accept
#insert rule ip6 qubes output oifgroup 1 skgid "qvpn" accept

View File

@ -1,10 +0,0 @@
#!/usr/sbin/nft -f
# SPDX-FileCopyrightText: 2022 unman <unman@thirdeyesecurity.org>
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
insert rule filter forward tcp flags syn tcp option maxseg size set rt mtu
insert rule filter forward oifname eth0 drop
insert rule filter forward iifname eth0 drop

View File

@ -0,0 +1,25 @@
#!/usr/sbin/nft -f
# vim: ft=nftables
# SPDX-FileCopyrightText: 2022 unman <unman@thirdeyesecurity.org>
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
flush chain ip qubes custom-forward
flush chain ip6 qubes custom-forward
insert rule ip qubes custom-forward oifgroup 1 drop
insert rule ip qubes custom-forward iifgroup 1 drop
insert rule ip6 qubes custom-forward oifgroup 1 drop
insert rule ip6 qubes custom-forward iifgroup 1 drop
add chain ip6 qubes dnat-dns { type nat hook prerouting priority dstnat; policy accept; }
add chain ip qubes custom-dnat { type nat hook prerouting priority dstnat; policy accept; }
add chain ip6 qubes custom-dnat { type nat hook prerouting priority dstnat; policy accept; }
flush chain ip qubes dnat-dns
flush chain ip6 qubes dnat-dns
flush chain ip qubes custom-dnat
flush chain ip6 qubes custom-dnat
include "/var/run/wireguard/dnat.nft"

View File

@ -4,4 +4,4 @@
#
# SPDX-License-Identifier: AGPL-3.0-or-later
wg-quick up /rw/config/vpn/wireguard.conf
wg-quick up /home/user/wireguard.conf

View File

@ -1,24 +0,0 @@
#!/usr/sbin/nft -f
# vim: ft=nftables
# SPDX-FileCopyrightText: 2022 unman <unman@thirdeyesecurity.org>
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
include /rw/config/vpn/qube-ip.nft
define vpn_dns_primary = 10.8.0.1
define vpn_dns_secondary = 10.14.0.1
chain ip qubes forward '{ policy drop; }'
insert rule ip qubes custom-forward oifgroup 1 drop
insert rule ip qubes custom-forward iifgroup 1 drop
flush chain ip qubes dnat-dns
flush chain ip6 qubes dnat-dns
add rule ip qubes dnat-dns iifgroup 2 ip daddr $qube_ip tcp dport 53 counter dnat to $vpn_dns_primary
add rule ip qubes dnat-dns iifgroup 2 ip daddr $qube_ip tcp dport 53 counter dnat to $vpn_dns_primary
add rule ip qubes dnat-dns iifgroup 2 ip daddr $qube_ip udp dport 53 counter dnat to $vpn_dns_secondary
add rule ip qubes dnat-dns iifgroup 2 ip daddr $qube_ip udp dport 53 counter dnat to $vpn_dns_secondary

View File

@ -1,41 +0,0 @@
#!/usr/sbin/nft -f
# vim: ft=nftables
# SPDX-FileCopyrightText: 2022 unman <unman@thirdeyesecurity.org>
# SPDX-FileCopyrightText: 2023 1cho1ce <https://github.com/1cho1ce>
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: GPL-3.0-or-later
## TODO: source this ruleset
## Stop leaks
chain ip qubes forward '{ policy drop; }'
chain ip qubes input '{ policy drop; }'
chain ip qubes output '{ policy drop; }'
chain ip6 qubes forward '{ policy drop; }'
chain ip6 qubes input '{ policy drop; }'
chain ip6 qubes output '{ policy drop; }'
insert rule ip qubes custom-forward oifgroup 1 drop
insert rule ip qubes custom-forward iifgroup 1 drop
insert rule ip6 qubes custom-forward oifgroup 1 drop
insert rule ip6 qubes custom-forward iifgroup 1 drop
## Accept forward traffic between dowstream vif+ (group 2) and VPN (group9)
insert rule ip qubes custom-forward iifgroup 2 oifgroup 9 accept
insert rule ip qubes custom-forward iifgroup 9 oifgroup 2 accept
insert rule ip6 qubes custom-forward iifgroup 2 oifgroup 9 accept
insert rule ip6 qubes custom-forward iifgroup 9 oifgroup 2 accept
## Drop ICMP
insert rule ip qubes custom-input meta l4proto icmp drop
insert rule ip qubes output oifgroup 1 meta l4proto icmp drop
insert rule ip6 qubes custom-input meta l4proto icmp drop
insert rule ip6 qubes output oifgroup 1 meta l4proto icmp drop
## Allow traffic from the `qvpn` group to the uplink interface (eth0);
## Our VPN client will run with group `qvpn`.
insert rule ip qubes output oifname "lo" accept
insert rule ip qubes output oifgroup 1 skgid qvpn accept
insert rule ip6 qubes output oifname "lo" accept
insert rule ip6 qubes output oifgroup 1 skgid "qvpn" accept

View File

@ -1,33 +0,0 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2022 unman <unman@thirdeyesecurity.org>
# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
target_file="/home/user/wireguard.conf"
if ! zenity --question \
--text="Please select the wireguard configuration file you want to use" \
--ok-label="OK" --cancel-label="No"
then
zenity --error --text="You need a config file\nCheck with Mullvad VPN"
exit 1
fi
client_file="$(zenity --file-selection)"
if test -z "${client_file}"; then
zenity --error --text="No file selected"
exit 1
fi
if ! grep -q '^PrivateKey' "$client_file" ; then
zenity --error --text="That doesn't look like a client config file"
exit 1
fi
test "$client_file" != "$target_file" && cp "$client_file" "$target_file"
zenity --info --text="Restart this qube. The VPN service will autostart"

View File

@ -7,10 +7,12 @@ SPDX-License-Identifier: AGPL-3.0-or-later
{% if grains['nodename'] != 'dom0' -%}
{#
"{{ slsdotpath }}-qvpn-group":
group.present:
- name: qvpn
- system: True
#}
"{{ slsdotpath }}-updated":
pkg.uptodate:
@ -25,12 +27,9 @@ SPDX-License-Identifier: AGPL-3.0-or-later
- qubes-core-agent-networking
- ca-certificates
- iproute2
- libnotify-bin
- mate-notification-daemon
- resolvconf
- unzip
- wireguard
- unzip
- curl
- zenity
{% endif -%}