Qubes-vpn-support icon indicating copy to clipboard operation
Qubes-vpn-support copied to clipboard

Replace iptables with nftables

Open 1cho1ce opened this issue 1 year ago • 8 comments

Qubes dropped iptables support and replaced it with nftables: https://github.com/QubesOS/qubes-core-agent-linux/commit/28b95535c7cbd15543c804e822c0e4c997f5966e This pull request replaces iptables with nftables.

Removed allow established input rules from proxy-firewall-restrict since they are already present in nft tables ip/ip6 qubes.

TODO: Need to think of a better way to check in --check-firewall in qubes-vpn-setup script if the forward drop rules are present (or proxy-firewall-restrict script finished successfully).

1cho1ce avatar May 25 '23 19:05 1cho1ce

Thanks for the PR. I will start reviewing this tomorrow and hopefully get the nftables support ready in June.

tasket avatar May 29 '23 19:05 tasket

Sorry, I didn't check openvpn and forgot to add forward rules for it. Also changed nft to use custom chains.

1cho1ce avatar May 31 '23 05:05 1cho1ce

@1cho1ce - I have been trying to use your forked version on Qubes 4.2 and after a lot of trying, I couldn't get it to work with Fedora templates, but eventually when I changed to a Debian 11 template it worked fine.

I do have one problem though, I was previously (on 4.1) using edited qubes-firewall-user-script & rc.local to allow local network access (192.168.150.0/24 in my case). I have copied & adjusted these as below but can't get any lan access now:

# from qubes-firewall-user-script

#    Allow forwarding of connections through upstream network device
#    if they're to 192.168.150.x

#iptables -I FORWARD -o eth0 -d 192.168.150.0/24 -j ACCEPT
#iptables -I FORWARD -i eth0 -s 192.168.150.0/24 -j ACCEPT

nft 'insert rule ip filter FORWARD oifname "eth0" ip daddr 192.168.150.0/24 counter accept'
nft 'insert rule ip filter FORWARD iifname "eth0" ip saddr 192.168.150.0/24 counter accept'
# from rc.local
# Allow access to home network for backup, etc.
ip route add 192.168.150.0/24 via 10.137.0.7 dev eth0

TBH - I'm not very familiar with nft & edited the iptables-I FORWARD rules above using iptables-translate. Has anyone got local access working on 4.2 with nft?

tquest1 avatar Jun 17 '23 07:06 tquest1

I have been trying to use your forked version on Qubes 4.2 and after a lot of trying, I couldn't get it to work with Fedora templates, but eventually when I changed to a Debian 11 template it worked fine.

I've fixed this issue with Fedora template.

I do have one problem though, I was previously (on 4.1) using edited qubes-firewall-user-script & rc.local to allow local network access (192.168.150.0/24 in my case). I have copied & adjusted these as below but can't get any lan access now:

You can replace these iptables rules:

iptables -I FORWARD -o eth0 -d 192.168.150.0/24 -j ACCEPT
iptables -I FORWARD -i eth0 -s 192.168.150.0/24 -j ACCEPT

With these nftables rules:

nft insert rule ip qubes custom-forward oifgroup 1 ip daddr 192.168.150.0/24 accept
nft insert rule ip qubes custom-forward iifgroup 1 ip saddr 192.168.150.0/24 accept

1cho1ce avatar Jun 20 '23 22:06 1cho1ce

Is this pull request in good working order? Has it been deemed insufficient? I am just wondering what further needs to be done in order to create a working solution. I am not yet familiar with nftables rules, but I will research and see if I can help if something is missing.

moonlitOrca avatar Sep 04 '23 20:09 moonlitOrca

Also would like to know if this PR works, I just need to be able to VPN with 4.2

dylangerdaly avatar Sep 21 '23 09:09 dylangerdaly

This PR worked out of the box for me - many thanks. Not tested failure modes. Running on debian-12-minimal. @1cho1ce, like many others I am struggling with nft - would it be possible to add a paragraph to the Firewall Notes section to provide an example of port forwarding setup ? Thanks

[ed] My best guess that seems to be working - in a file in qubes-firewall.d: PORTS="{ 1234, 1235 }" nft add rule ip qubes dnat-dns iifgroup 9 tcp dport $PORTS dnat to 10.137.0.XX and the same for udp. Anything else recommended?

Eric678 avatar Oct 01 '23 22:10 Eric678

There are a few errors in the PR with allowing traffic from VPN to qubes and typos related to IPv6. This was discussed here: https://forum.qubes-os.org/t/vpn-instructions-for-4-2/20738/78

Here is a patch:
diff --git a/files-main/proxy-firewall-restrict b/files-main/proxy-firewall-restrict
index a3aba10..8142ad2 100644
--- a/files-main/proxy-firewall-restrict
+++ b/files-main/proxy-firewall-restrict
@@ -22,11 +22,9 @@ nft chain ip6 qubes forward '{ policy drop; }'
 nft insert rule ip6 qubes custom-forward oifgroup 1 drop
 nft insert rule ip6 qubes custom-forward iifgroup 1 drop
 
-# Accept forward traffic between dowstream (vif+, group 2) and VPN interface (group 9)
+# Accept forward traffic from dowstream (vif+, group 2) to VPN interface (group 9)
 nft insert rule ip qubes custom-forward iifgroup 2 oifgroup 9 accept
-nft insert rule ip qubes custom-forward iifgroup 9 oifgroup 2 accept
 nft insert rule ip6 qubes custom-forward iifgroup 2 oifgroup 9 accept
-nft insert rule ip6 qubes custom-forward iifgroup 9 oifgroup 2 accept
 
 # Block INPUT from tunnel(s):
 nft chain ip qubes input '{ policy drop; }'
diff --git a/files-main/qubes-vpn-ns b/files-main/qubes-vpn-ns
index 62510d4..d510954 100644
--- a/files-main/qubes-vpn-ns
+++ b/files-main/qubes-vpn-ns
@@ -85,11 +85,11 @@ up)
         if [[ ${#vpn_dns_ip6[@]} != 0 ]] && [[ ${#qubes_dns_ip6[@]} != 0 ]]; then
             for i in $(seq 0 $((${#qubes_dns_ip6[@]} - 1))); do
                 if [[ $i < ${#vpn_dns_ip6[@]} ]] ; then
-                    nft add rule ip6 qubes dnat-dns iifgroup 2 ip6 daddr ${qubes_dns_ip6[$i]} tcp dport 53 dnat to ${qubes_dns_ip6[$i]}
-                    nft add rule ip6 qubes dnat-dns iifgroup 2 ip6 daddr ${qubes_dns_ip6[$i]} udp dport 53 dnat to ${qubes_dns_ip6[$i]}
+                    nft add rule ip6 qubes dnat-dns iifgroup 2 ip6 daddr ${qubes_dns_ip6[$i]} tcp dport 53 dnat to ${vpn_dns_ip6[$i]}
+                    nft add rule ip6 qubes dnat-dns iifgroup 2 ip6 daddr ${qubes_dns_ip6[$i]} udp dport 53 dnat to ${vpn_dns_ip6[$i]}
                 else
-                    nft add rule ip6 qubes dnat-dns iifgroup 2 ip6 daddr ${qubes_dns_ip6[$i]} tcp dport 53 dnat to ${qubes_dns_ip6[0]}
-                    nft add rule ip6 qubes dnat-dns iifgroup 2 ip6 daddr ${qubes_dns_ip6[$i]} udp dport 53 dnat to ${qubes_dns_ip6[0]}
+                    nft add rule ip6 qubes dnat-dns iifgroup 2 ip6 daddr ${qubes_dns_ip6[$i]} tcp dport 53 dnat to ${vpn_dns_ip6[0]}
+                    nft add rule ip6 qubes dnat-dns iifgroup 2 ip6 daddr ${qubes_dns_ip6[$i]} udp dport 53 dnat to ${vpn_dns_ip6[0]}
                 fi
             done
         fi
diff --git a/files-main/qubes-vpn-setup b/files-main/qubes-vpn-setup
index 995ae33..f9b3512 100755
--- a/files-main/qubes-vpn-setup
+++ b/files-main/qubes-vpn-setup
@@ -53,7 +53,7 @@ firewall_link() {
 case "$1" in
 --check-firewall)
     for i in 1 2 3; do
-        if (nft -j -s list chain ip qubes custom-forward && nft -j -s list chain ip qubes custom-forward) | python3 -c "
+        if (nft -j -s list chain ip qubes custom-forward && nft -j -s list chain ip6 qubes custom-forward) | python3 -c "
 import sys, json;
 def main():
   rule_out_ipv4_exists = False

You can apply the patch using this command:

~/Qubes-vpn-support$ git apply /path/to/patch

Additional notes: If no Qubes OS virtual IPv6 DNS servers are used then the IPv6 DNS from VPN provider won’t be used and qubes will use their own IPv6 DNS servers. I saw a pull request from 1choice to add virtual IPv6 DNS support to Qubes OS so I guess that was related to this change. If no DNS is provided by VPN server then requests to virtual DNS IPs will leak from qubes. I guess it's better to use some default DNS like 9.9.9.9 in case no DNS will be provided by VPN.

apparatius avatar Jul 03 '24 05:07 apparatius