Skip to content

Instantly share code, notes, and snippets.

@daktak
Last active June 17, 2022 02:59
Show Gist options
  • Save daktak/f887352d564b54f9e529404cc0eb60d5 to your computer and use it in GitHub Desktop.
Save daktak/f887352d564b54f9e529404cc0eb60d5 to your computer and use it in GitHub Desktop.
Qubes-os port forwarding to allow external connections
#!/bin/sh
#4.0
#ip() { qvm-ls --raw-data ip -- "$1"; }
##4.1
ip() { qvm-ls --raw-data --fields ip -- "$1"; }
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")
iface=$(qvm-run -p -u root "$from_domain" "ifconfig \
| grep cast -B 1 --no-group-separator | grep -vE '^(vif|lo)' | grep -oE '^[^: ]+' | head -1")
[ X"$from_ip" = XNone ] && from_ip=
echo "$from_domain: forwarding on $iface port $port to $to_domain
($from_ip -> $to_ip)" >&2
qvm-run -p -u root "$from_domain" \
"iptables -t nat -A PREROUTING -i $iface -p $type \
--dport $port ${from_ip:+-d} $from_ip \
-j DNAT --to-destination $to_ip"
qvm-run -p -u root "$from_domain" \
"iptables -I FORWARD 2 -i $iface ${to_ip:+-d} $to_ip \
-p $type --dport $port -m conntrack --ctstate NEW -j ACCEPT"
}
input() {
local domain=$1
local port=$2
local type=$3
echo "$domain: allowing input to port $port" >&2
qvm-run -p -u root "$domain" "iptables -I INPUT 5 -p $type \
--dport $port -m conntrack --ctstate NEW -j ACCEPT"
}
recurse_netvms() {
local this_dom=$1
local port=$2
local type=$3
local outer_dom=$(netvm "$this_dom")
if [ -n "$outer_dom" ]; then
forward "$outer_dom" "$this_dom" "$port" "$type"
recurse_netvms "$outer_dom" "$port" "$type"
fi
}
usage() {
echo "Usage: ${0##*/} <vm> <port>" >&2
exit 1
}
[ $# -eq 2 ] || [ $# -eq 3 ] || usage
type=$3
if [ -z ${type} ]; then
type=$type
fi
input "$1" "$2" ${type}
recurse_netvms "$1" "$2" ${type}
@jpouellet
Copy link

I was inspired by this to create my own version which auto-detects the device names and netvm chain.

@daktak
Copy link
Author

daktak commented Apr 13, 2017

Thank you so much, I was not aware of the raw or qvm-prefs.
I've made some small updates and invoke like
qvm-port-forward.sh personal 1714:1764
qvm-port-forward.sh personal 1714:1764 udp
for kde connect

Updated the iface grep to look for broadcast as I'm on wifi most of the time, not enp0s0

@Joeviocoe
Copy link

Joeviocoe commented Feb 10, 2018

Created an updated version for Qubes 4.0 (RC4 tested) Joeviocoe's qvm-portfwd
qvm-portfwd <vm> <port> <proto> | <vm> clear all
Example: qvm-portfwd webserv 8888 tcp

Command line specify the "VM, Port and Protocol"... or just "VM clear all" to undo previous.
Script will recursively configure iptables/nft for all proxyVMs in use.
Now uses comments on iptables to remove previous entries (no duplicates)

Works with Fedora 25/26 which uses nft rules along with iptables
Works with Debian 8/9 too

@niccokunzmann
Copy link

@jpouellet @daktak @Joeviocoe

Now, I also created a script:
https://github.com/niccokunzmann/qvm-expose-port
When I was reading the documentation, I could not find that such a command exists.
I was wondering if we can join forces to create an official qubes command QubesOS/qubes-issues#4028.
What do you think?

@micah
Copy link

micah commented Sep 15, 2019

Its a good idea to get it integrated into qubes, but @niccokunzmann's script doesn't work in qubes4, so maybe joeviocoe's should be used instead?

@daktak
Copy link
Author

daktak commented Sep 17, 2019

@daktak
Copy link
Author

daktak commented Jun 17, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment