-
-
Save Joeviocoe/6c4dc0c283f6d6c5b1a3f5af8793292b to your computer and use it in GitHub Desktop.
Qubes-os port forwarding to allow external connections
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# Inspired by https://gist.github.com/daktak/f887352d564b54f9e529404cc0eb60d5 | |
# Inspired by https://gist.github.com/jpouellet/d8cd0eb8589a5b9bf0c53a28fc530369 | |
ip() { qvm-prefs -g -- "$1" ip; } | |
netvm() { qvm-prefs -g -- "$1" netvm; } | |
forward() { | |
local from_domain=$1 | |
local to_domain=$2 | |
local port=$3 | |
local type=$4 | |
local from_ip=$(ip "$from_domain") | |
local to_ip=$(ip "$to_domain") | |
local iface=$(qvm-run -p -u root "$from_domain" "ifconfig \ | |
| grep cast -B 1 --no-group-separator | grep -vE '^(vif|lo)' | grep -oE '^[^: ]+' | head -1") | |
local from_ip=$(qvm-run -p -u root "$from_domain" "hostname -I | cut -d ' ' -f 1") | |
if [ X"$from_ip" = XNone ] ; then local from_ip= ; fi | |
if [[ $3 = "clear" && $4 = "all" ]] | |
then | |
echo "$from_domain: Clearing Port Forwarding from $1 iptables" >&2 | |
qvm-run -p -u root "$from_domain" "iptables-save | grep -v 'PortFwd $1' | iptables-restore" | |
local nft_cmd="nft list table ip qubes-firewall -a | tr -d '\"' | grep 'iifname $iface accept # handle' | awk '{print \$NF}'" | |
local nft_handle=$(qvm-run -p -u root "$from_domain" "$nft_cmd") | |
if [[ $nft_handle =~ ^[0-9]+$ ]] ; then qvm-run -p -u root "$from_domain" "nft delete rule ip qubes-firewall forward handle $nft_handle" ; fi | |
else | |
echo "$from_domain: Forwarding on $iface port $port to $to_domain | |
($from_ip -> $to_ip)" >&2 | |
qvm-run -p -u root "$from_domain" "iptables-save | grep -v 'PortFwd $1>$2:$4$3' | iptables-restore" | |
qvm-run -p -u root "$from_domain" "iptables -t nat -A PREROUTING -i $iface -p $type ${from_ip:+-d} $from_ip --dport $port -j DNAT --to-destination $to_ip \ | |
-m comment --comment 'PortFwd $1>$2:$4$3'" | |
qvm-run -p -u root "$from_domain" "iptables -I FORWARD 2 -i $iface -p $type ${to_ip:+-d} $to_ip --dport $port -m conntrack --ctstate NEW -j ACCEPT \ | |
-m comment --comment 'PortFwd $1>$2:$4$3'" | |
qvm-run -p -u root "$from_domain" "nft add rule ip qubes-firewall forward meta iifname $iface accept" | |
fi | |
} | |
input() { | |
local domain=$1 | |
local port=$2 | |
local type=$3 | |
if [[ $2 = "clear" && $3 = "all" ]] | |
then | |
echo "$domain: Clearing Port Forwarding from $1 iptables" >&2 | |
qvm-run -p -u root "$domain" "iptables-save | grep -v 'PortFwd $1' | iptables-restore" | |
else | |
echo "$domain: Allowing input to port $port" >&2 | |
qvm-run -p -u root "$domain" "iptables-save | grep -v 'PortFwd $1:$3$2' | iptables-restore" | |
qvm-run -p -u root "$domain" "iptables -I INPUT 5 -p $type --dport $port -m conntrack --ctstate NEW -j ACCEPT \ | |
-m comment --comment 'PortFwd $1:$3$2'" | |
fi | |
} | |
recurse_netvms() { | |
local this_dom=$1 | |
local port=$2 | |
local type=$3 | |
local outer_dom=$(netvm "$this_dom") | |
if [[ -n "$outer_dom" && "$outer_dom" != "None" ]]; then | |
forward "$outer_dom" "$this_dom" "$port" "$type" | |
recurse_netvms "$outer_dom" "$port" "$type" | |
fi | |
} | |
usage() { | |
echo "Usage: ${0##*/} <vm> <port> <proto> | <vm> clear all" >&2 | |
exit 1 | |
} | |
[ $# -eq 3 ] || usage | |
input "$1" "$2" "$3" | |
recurse_netvms "$1" "$2" "$3" |
In case someone wants to test, I improved a little bit the current version (https://gist.github.com/fepitre/941d7161ae1150d90e15f778027e3248), notably by adding option for persistence. I'll do some review again (and from others I hope) and we will probably refactor it a little bit again for putting it in @QubesOS-contrib
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Why this double fw thing tho?
nf and ip tables