diff --git a/README.md b/README.md index fd089bb..dc5c27b 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/salt/sys-wireguard/README.md b/salt/sys-wireguard/README.md index 9d8419d..88a115c 100644 --- a/salt/sys-wireguard/README.md +++ b/salt/sys-wireguard/README.md @@ -32,16 +32,17 @@ qubesctl --skip-dom0 --targets=sys-wireguard state.apply sys-wireguard.configure ``` -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) diff --git a/salt/sys-wireguard/configure.sls b/salt/sys-wireguard/configure.sls index 678a5db..1cfb43a 100644 --- a/salt/sys-wireguard/configure.sls +++ b/salt/sys-wireguard/configure.sls @@ -5,13 +5,8 @@ SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. 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' diff --git a/salt/sys-wireguard/create.sls b/salt/sys-wireguard/create.sls index d6a43cc..8c23836 100644 --- a/salt/sys-wireguard/create.sls +++ b/salt/sys-wireguard/create.sls @@ -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 diff --git a/salt/sys-wireguard/files/admin/qubes-setup-sys-wireguard.desktop b/salt/sys-wireguard/files/admin/qubes-setup-sys-wireguard.desktop deleted file mode 100644 index 1bb565d..0000000 --- a/salt/sys-wireguard/files/admin/qubes-setup-sys-wireguard.desktop +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-FileCopyrightText: 2022 unman -# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. -# -# 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 diff --git a/salt/sys-wireguard/files/admin/qvm-wireguard b/salt/sys-wireguard/files/admin/qvm-wireguard new file mode 100755 index 0000000..29167f6 --- /dev/null +++ b/salt/sys-wireguard/files/admin/qvm-wireguard @@ -0,0 +1,46 @@ +#!/bin/sh + +# SPDX-FileCopyrightText: 2022 unman +# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. +# +# 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 diff --git a/salt/sys-wireguard/files/admin/setup-sys-wireguard b/salt/sys-wireguard/files/admin/setup-sys-wireguard deleted file mode 100755 index e32c435..0000000 --- a/salt/sys-wireguard/files/admin/setup-sys-wireguard +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh - -# SPDX-FileCopyrightText: 2022 unman -# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. -# -# 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 diff --git a/salt/sys-wireguard/files/server/network-hooks.d/50-sys-wireguard b/salt/sys-wireguard/files/server/network-hooks.d/50-sys-wireguard new file mode 100755 index 0000000..ddad58a --- /dev/null +++ b/salt/sys-wireguard/files/server/network-hooks.d/50-sys-wireguard @@ -0,0 +1,11 @@ +#!/bin/sh + +# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. +# +# 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 diff --git a/salt/sys-wireguard/files/server/qubes-firewall.d/50-sys-wireguard-pre b/salt/sys-wireguard/files/server/qubes-firewall.d/50-sys-wireguard-pre deleted file mode 100755 index 6177190..0000000 --- a/salt/sys-wireguard/files/server/qubes-firewall.d/50-sys-wireguard-pre +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. -# -# 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/ diff --git a/salt/sys-wireguard/files/server/qubes-firewall.d/50-sys-wireguard-var b/salt/sys-wireguard/files/server/qubes-firewall.d/50-sys-wireguard-var new file mode 100755 index 0000000..398bdd2 --- /dev/null +++ b/salt/sys-wireguard/files/server/qubes-firewall.d/50-sys-wireguard-var @@ -0,0 +1,48 @@ +#!/bin/sh + +# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. +# +# 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 diff --git a/salt/sys-wireguard/files/server/qubes-firewall.d/55-sys-wireguard-tunnel b/salt/sys-wireguard/files/server/qubes-firewall.d/55-sys-wireguard-tunnel new file mode 100755 index 0000000..caf54dc --- /dev/null +++ b/salt/sys-wireguard/files/server/qubes-firewall.d/55-sys-wireguard-tunnel @@ -0,0 +1,43 @@ +#!/usr/sbin/nft -f +# vim: ft=nftables + +# SPDX-FileCopyrightText: 2022 unman +# SPDX-FileCopyrightText: 2023 1cho1ce +# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. +# +# 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 diff --git a/salt/sys-wireguard/files/server/qubes-firewall.d/60-sys-wireguard-filter b/salt/sys-wireguard/files/server/qubes-firewall.d/60-sys-wireguard-filter deleted file mode 100755 index 7b3c422..0000000 --- a/salt/sys-wireguard/files/server/qubes-firewall.d/60-sys-wireguard-filter +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/sbin/nft -f - -# SPDX-FileCopyrightText: 2022 unman -# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. -# -# 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 diff --git a/salt/sys-wireguard/files/server/qubes-firewall.d/60-sys-wireguard-nat b/salt/sys-wireguard/files/server/qubes-firewall.d/60-sys-wireguard-nat new file mode 100755 index 0000000..b2d345d --- /dev/null +++ b/salt/sys-wireguard/files/server/qubes-firewall.d/60-sys-wireguard-nat @@ -0,0 +1,25 @@ +#!/usr/sbin/nft -f +# vim: ft=nftables + +# SPDX-FileCopyrightText: 2022 unman +# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. +# +# 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" diff --git a/salt/sys-wireguard/files/server/rc.local.d/50-sys-wireguard.rc b/salt/sys-wireguard/files/server/rc.local.d/50-sys-wireguard.rc index 1274df1..bf54c16 100755 --- a/salt/sys-wireguard/files/server/rc.local.d/50-sys-wireguard.rc +++ b/salt/sys-wireguard/files/server/rc.local.d/50-sys-wireguard.rc @@ -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 diff --git a/salt/sys-wireguard/files/server/vpn/dns-hijack.nft b/salt/sys-wireguard/files/server/vpn/dns-hijack.nft deleted file mode 100755 index 5484a76..0000000 --- a/salt/sys-wireguard/files/server/vpn/dns-hijack.nft +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/sbin/nft -f -# vim: ft=nftables - -# SPDX-FileCopyrightText: 2022 unman -# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. -# -# 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 diff --git a/salt/sys-wireguard/files/server/vpn/tunnel.nft b/salt/sys-wireguard/files/server/vpn/tunnel.nft deleted file mode 100755 index eac98b4..0000000 --- a/salt/sys-wireguard/files/server/vpn/tunnel.nft +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/sbin/nft -f -# vim: ft=nftables - -# SPDX-FileCopyrightText: 2022 unman -# SPDX-FileCopyrightText: 2023 1cho1ce -# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. -# -# 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 diff --git a/salt/sys-wireguard/files/server/wg-conf.sh b/salt/sys-wireguard/files/server/wg-conf.sh deleted file mode 100755 index 7b6f47e..0000000 --- a/salt/sys-wireguard/files/server/wg-conf.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -# SPDX-FileCopyrightText: 2022 unman -# SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. -# -# 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" diff --git a/salt/sys-wireguard/install.sls b/salt/sys-wireguard/install.sls index e3e81ba..104e4e4 100644 --- a/salt/sys-wireguard/install.sls +++ b/salt/sys-wireguard/install.sls @@ -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 -%}