-
-
Save Joeviocoe/6c4dc0c283f6d6c5b1a3f5af8793292b to your computer and use it in GitHub Desktop.
| #!/bin/bash | |
| #change dev to your exposed device name | |
| #./qvm-exposeip.sh personal 80 | |
| dev=wlp0s1 | |
| appvm=$1 | |
| port=$2 | |
| net=$3 | |
| fw=$4 | |
| if [ -z ${net} ]; then | |
| net=sys-net | |
| fi | |
| if [ -z ${fw} ]; then | |
| fw=sys-firewall | |
| fi | |
| externip=`qvm-run -p ${net} -u root "ifconfig ${dev}" | grep broadcast |col -x | awk '{print $2}'` | |
| fwip=`qvm-ls -n | grep \{${fw}\} | col -x | awk '{print $14}'` | |
| vmip=`qvm-ls -n | grep ${appvm} | col -x | awk '{print $13}'` | |
| exenet="iptables -t nat -A PREROUTING -i ${dev} -p tcp --dport ${port} -d ${externip} -j DNAT --to-destination ${fwip} && iptables -I FORWARD 2 -i ${dev} -d ${fwip} -p tcp --dport ${port} -m conntrack --ctstate NEW -j ACCEPT" | |
| qvm-run -p -u root ${net} "${exenet}" | |
| exefw="iptables -t nat -A PREROUTING -i eth0 -p tcp --dport $port -d ${fwip} -j DNAT --to-destination ${vmip} && iptables -I FORWARD 2 -i eth0 -d ${vmip} -p tcp --dport ${port} -m conntrack --ctstate NEW -j ACCEPT" | |
| qvm-run -p -u root ${fw} "${exefw}" | |
| exevm="iptables -I INPUT 5 -p tcp --dport ${port} -m conntrack --ctstate NEW -j ACCEPT" | |
| qvm-run -p -u root ${appvm} "${exevm}" |
[[ ... =~ .. ]] is a bashism, but you're using /bin/sh (which is not guaranteed to be bash)
Also, for safety and portability I'd suggest:
[ X"$foo" = Xbar ]or[ bar = "$foo" ]instead of[[ $foo = bar ]][ ... -a ... ]/[ ... -o ... ]instead of[[ ... && ... ]]/[[ ... || ...]].
Otherwise nice, and your script is probably better than mine. 🍻
Also, I don't like how you're reaching into a VM to grab nft_handle, processing the (untrusted!) result in dom0, and then using the result to decide whether to issue another command. A safer way would be to issue only one command which does the checking and conditional command entirely on the VM, discarding any output back to dom0. Might be over-paranoid, but then again, we had shellshock.
... | grep -qx '[0-9]+' && ( ... ) in the command passed to the VM should do it and remove the bashism at the same time.
how do i use/install this on Qubes 4.0 I need to port forward correctly on Qubes 4.0 and and also I have a router so kinda confusing... any help is appreciated! thanks
Simpy put it in ~/bin in dom0 or any other directory in your PATH and use it. Here is an example how I use it for samba:
#!/bin/sh
# Configure ports for samba server
qvm-portfwd server 445 tcp
qvm-portfwd server 445 udp
qvm-portfwd server 139 tcp
qvm-portfwd server 138 udp
qvm-portfwd server 137 udp
# and make conncections between VMS
qvm-portfwd server 445 tcp work
qvm-portfwd server 445 udp work
qvm-portfwd server 139 tcp work
qvm-portfwd server 138 udp work
qvm-portfwd server 137 udp work
I hope that I didn't make any changes. But I don't think so.
this sounds really stupid but what is the exact command to do that?
`
qvm-portfwd PTFAssaultMachine 443 tcp
isn't working lol i can get the file into dom0 but it wont recognize the command
for the command
sudo nano /rw/config/rc.local
#!/bin/sh
####################
# My service routing
# Create a new firewall natting chain for my service
if iptables -t nat -N MY-HTTPS; then
# Add a natting rule if it did not exit (to avoid cluter if script executed multiple times)
iptables -t nat -A MY-HTTPS -j DNAT --to-destination 10.137.1.x
fi
# If no prerouting rule exist for my service
if ! iptables -t nat -n -L PREROUTING | grep --quiet MY-HTTPS; then
# add a natting rule for the traffic (same reason)
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -d 192.168.0.x -j MY-HTTPS
fi
######################
# My service filtering
# Create a new firewall filtering chain for my service
if iptables -N MY-HTTPS; then
# Add a filtering rule if it did not exit (to avoid cluter if script executed multiple times)
iptables -A MY-HTTPS -s 192.168.x.0/24 -j ACCEPT
fi
# If no forward rule exist for my service
if ! iptables -n -L FORWARD | grep --quiet MY-HTTPS; then
# add a forward rule for the traffic (same reason)
iptables -I FORWARD 2 -d 10.137.1.x -p tcp --dport 443 -m conntrack --ctstate NEW -j MY-HTTPS
fi
Note: Again in R4 the following needs to be added:
#############
# In Qubes R4
# If not already present
if nft -nn list table ip qubes-firewall | grep "tcp dport 443 ct state new"; then
# Add a filtering rule
nft add rule ip qubes-firewall forward meta iifname eth0 ip daddr 10.137.0.x tcp dport 443 ct state new counter accept
fi
Finally make this file executable, so it runs at each boot
sudo chmod +x /rw/config/rc.local
what is MY-HTTPS referring to? it is confusing me lol its on
https://www.qubes-os.org/doc/firewall/#port-forwarding-to-a-qube-from-the-outside-world
also what does this mean for me(at the bottom of the same page mentioned):
Where to put firewall rules (R4.0)
Implicit in the above example scripts, but worth calling attention to: for all qubes except AppVMs supplying networking, iptables commands should be added to the /rw/config/rc.local script. For AppVMs supplying networking (sys-firewall inclusive), iptables commands should be added to /rw/config/qubes-firewall-user-script.
if i have a basic configuration with app machines : firewall sys-net and PTFAssaultMachine with all three being App machines, also i have a WiFi router and I am wondering if that matters
This is awesome! - worked like a charm.
Thanks
This works well for me. As the instructions said, put it in dom0's ~/bin directory. I used the following instructions:
https://www.qubes-os.org/doc/copy-from-dom0/
From my debian-9 vm, it was:
qvm-run --pass-io debian-9 'cat /home/user/Downloads/qvm-portfwd' > ~/bin/qvm-portfwd
chmod +x ~/bin/qvm-portfwd
Good luck to all others.
[[ ... =~ .. ]]is a bashism, but you're using /bin/sh (which is not guaranteed to be bash)Also, for safety and portability I'd suggest:
* `[ X"$foo" = Xbar ]` or `[ bar = "$foo" ]` instead of `[[ $foo = bar ]]` * `[ ... -a ... ]` / `[ ... -o ... ]` instead of `[[ ... && ... ]]` / `[[ ... || ...]]`.Otherwise nice, and your script is probably better than mine. beers
Also, I don't like how you're reaching into a VM to grab nft_handle, processing the (untrusted!) result in dom0....
Thanks. I haven't had time to implement these changes but they are good changes to make.
Honestly, I use a new script that is more in line with Qubism (not Picasso). Everything I need for port fowarding is TCP based... so this script is much safer and uses socat over Qubes own RPC. It connects the net-vm directly to the app-vm without the need for either NFT or IPtables on a proxy-vm/firewall.
It requires some 'install' commands outside/prior to the script... but that could be scripted as well.
https://gist.github.com/Joeviocoe/90ec9fd9a0769b4671a8ae9c87584187
Dear @Joeviocoe are the changes applied persistent upon next reboot or even beyond that?
Why this double fw thing tho?
nf and ip tables
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
Updated version for Qubes 4.0 (RC4 tested)
Usage:
qvm-portfwd <vm> <port> <proto> | <vm> clear allExample:
qvm-portfwd webserv 8888 tcpCommand 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