Port forwarding to allow external connections (`qvm-portfwd-iptables`)

(see usage notes at bottom)

1 Like

A script to make it possible to reach a qube its port through the external interface of the qubes-os host, with undo functionality.

I am writing out what seems to be the “essential” parts of the script.
In long-form, to hopefully make them easier to understand (for people unfamiliar with the ip command).

A long form that was less clean to me, was ctstate.
Which is a list of connection states to match, see man iptables-extensions.

Initially:

comment="$( printf \''PortFwd %s:%s%s'\' "${qube?}" "${protocol?}" "${port?}" )"
iptables \
    --insert INPUT 5 \
    --protocol ${protocol?} \
    --destination-port ${port?} \
    --match conntrack \
        --ctstate NEW \
    --jump ACCEPT \
    --match comment \
        --comment "${comment?}"

And then traverse all the network providing qubes as well,
passing on packets from incoming to outgoing (ip) address with:

comment="$( printf \''PortFwd %s>%s:%s%s'\' "${from_qube?}" "${to_qube?}" "${protocol?}" "${port?}" )"

iptables \
    --table nat \
    --append PREROUTING \
    --in-interface ${incomingPacketInterface?} \
    --protocol ${protocol?} \
    ${incomingPacketRecipient:+--destination ${incomingPacketRecipient?}} \
    --destination-port ${port?} \
    --jump DNAT \
    --to-destination ${outgoingPacketRecipient?} \
    --match comment \
        --comment "${comment?}"

iptables \
    --insert FORWARD 2 \
    --in-interface ${incomingInterface?}
    --protocol ${protocol?} \
    ${incomingPacketRecipient:+--destination ${incomingPacketRecipient?}} \
    --destination-port ${port?} \
    --match conntrack \
        --ctstate NEW \
    --jump ACCEPT \
    --match comment \
        --comment "${comment?}"

nft add rule ip qubes-firewall forward meta iifname ${incomingInterface?} accept

This script didn’t work for me on Qubes 4.2-rc5. It errors with:

$ qvm-portfwd-iptables.sh --action create --qube myDestQube --port 22066
myDestQube: Allowing input to port 22066
/bin/bash: line 1: iptables-save: command not found
/bin/bash: line 1: iptables-restore: command not found
/bin/bash: line 1: iptables: command not found
/bin/bash: line 1: ifconfig: command not found
sys-firewall: Forwarding on port 22066 to myDestQube (10.138.11.174 → 10.137.0.17)
/bin/bash: line 1: iptables-restore: command not found
/bin/bash: line 1: iptables-save: command not found
/bin/bash: line 1: iptables: command not found
/bin/bash: line 1: iptables: command not found
Error: syntax error, unexpected accept
add rule ip qubes-firewall forward meta iifname accept
^^^^^^
/bin/bash: line 1: ifconfig: command not found
sys-net: Forwarding on port 22066 to sys-firewall (10.137.0.5 → 10.138.11.174)
/bin/bash: line 1: iptables-save: command not found
/bin/bash: line 1: iptables-restore: command not found
/bin/bash: line 1: iptables: command not found
/bin/bash: line 1: iptables: command not found
Error: syntax error, unexpected accept
add rule ip qubes-firewall forward meta iifname accept

I used this much more simple/elegant solution instead.