VPN instructions for 4.2

It’s a full debian-12 template but I will check if the prerequisite packages are all there…

Then what’s the output of these commands?

sudo nft list ruleset
ip a

Only missing package in my template was wireguard; I’ve added that but it has made no difference. App VM startup still errors out.
List command shows a whole bunch of chain defs.
IP command shows lo and eth0 addresses, but nothing else.

What’s the output of this command?
sudo nft list chain ip qubes custom-forward

1 Like

…this:

This chain should be present by default:

Do you use some custom nft rules in this qube that could delete this chain?

2 Likes

This is brand new app VM based on a debian-12 template, no rules apply. Also what is the “qubes” reference here, because that’s where it appears to die…

Is it default debian-12 template installed from Qubes OS repository? Or did you upgrade it from debian-11 maybe? If it’s default one then what changes did you make there?

Can you post the output of this command?

sudo nft list ruleset

Are you talking about qubes in table ip qubes? That’s how Qubes OS named its table for the firewall rules.

It was an early debian-12 template from the testing repo, so I guess that’s a possible problem. I am currently downloading the stable version so will mess around with that one… Thanks for looking at this for me :slightly_smiling_face:

So after a few days messing around with this, all I am getting is one issue after another.

I started by downloading a fresh debian-12 template and using that as the basis for this install.

First issue is that there is no nft table called “qubes” in this template; there is a table called “qubes-firewall” but you are not referencing that.

I figured out that if I do the following in the rc.local script in the app VM:

nft add table ip qubes
nft add table ip6 qubes
nft add chain ip qubes custom-forward
nft add chain ip6 qubes custom-forward

…then I can get your setup script to run. But then I have found a bug in the qubes-vpn-setup script where line 56 should be:

… list chain ip6 qubes …

in the last part of the if statement.

Third issue: when installing to the app VM the setup script is not even copying the necessary scripts locally, not sure what’s happening as yet…

Nft rules are loaded by qubes-iptables script:

Which is called by systemd qubes-iptables.service:

Check the service status to see if it was started successfully:

sudo systemctl status qubes-iptables.service

And check the logs in sudo journalctl to see if there’re some errors or failures.

I am on Qubes 4.1, and I thouhgt your changes would be relevant for that version too, but I guess not. Yes, service is started but that script is completely missing any nft statements in my template/app VM. Looks like it is a recent (3 mths ago) update to qubes-core-agent-linux? Is it stable? Should the debian-12 template for 4.1 have it?

Oh, I’ve assumed that you have Qubes OS 4.2 since this topic is about 4.2.
For Qubes OS 4.1 you should use Qubes-vpn-support without my patch and it should work.
But seeing that you’re not the only one with this problem:

Maybe some recent update in Qubes OS 4.1 broke something for Qubes-vpn-support.
Can you post the output of these commands?

I think the issue with this (@tasket’s) vpn access using debian-12 is an ongoing issue. I’ve had the problem ever since I started moving stuff to 12. 11 still works fine, and I have that in place still. And the issue seems to be nft related, which is why I thought your patch may have worked in 4.1.

Just out of interest, your --install process never put the proxy-firewall-restrict script in the /rw/config area at all. Other files that were in the old debian-11 install were also missing.

Lets continue this in this topic:

I’ve been playing with this for hours I don’t know what the hell I’m doing wrong.
Getting the script to run and everything configured was straight forward enough.
The VPN is up the journal and qubes-vpn-handler status confirm that, and using sudo to ping as qvpn is both resolving and getting replies.

However any qubes I point to it to use for networking can’t ping anything and can’t resolve anything.
I’m frankly at a loss at this point, I’m sure it will turn out to be something simple.
I’m on 4.2 RC3 using your ported script for nft. Install was on a debian-12-minimal template (from the repo no upgraded). All the packages listed in this thread are installed except wireguard as I’m not using it currently. The final config command was issued in an AppVM.
Rules seem to be there and in effect based on behavior, within the Proxy VM.

Did you install this script?

What’s the output of this command in your VPN qube?

sudo nft list ruleset

Maybe you have some up/down script in your openvpn config that is changing the firewall rules.

Shouldn’t be anything extra there the original minimal template I cloned shows a blank ruleset

table ip qubes {
	set downstream {
		type ipv4_addr
		elements = { 10.138.3.69 }
	}

	set allowed {
		type ifname . ipv4_addr
		elements = { "vif66.0" . 10.138.3.69 }
	}

	chain prerouting {
		type filter hook prerouting priority raw; policy accept;
		iifgroup 2 goto antispoof
		ip saddr @downstream counter packets 0 bytes 0 drop
	}

	chain antispoof {
		iifname . ip saddr @allowed accept
		counter packets 0 bytes 0 drop
	}

	chain postrouting {
		type nat hook postrouting priority srcnat; policy accept;
		oifgroup 2 accept
		oif "lo" accept
		masquerade
	}

	chain input {
		type filter hook input priority filter; policy drop;
		jump custom-input
		ct state invalid counter packets 0 bytes 0 drop
		iifgroup 2 udp dport 68 counter packets 0 bytes 0 drop
		ct state established,related accept
		iifgroup 2 meta l4proto icmp accept
		iif "lo" accept
		iifgroup 2 counter packets 0 bytes 0 reject with icmp host-prohibited
		counter packets 0 bytes 0
	}

	chain forward {
		type filter hook forward priority filter; policy drop;
		jump custom-forward
		ct state invalid counter packets 0 bytes 0 drop
		ct state established,related accept
		oifgroup 2 counter packets 0 bytes 0 drop
	}

	chain custom-input {
	}

	chain custom-forward {
		iifgroup 9 oifgroup 2 accept
		iifgroup 2 oifgroup 9 accept
		iifgroup 1 drop
		oifgroup 1 drop
	}

	chain output {
		type filter hook output priority filter; policy drop;
		oifgroup 1 meta skgid 994 accept
		oif "lo" accept
		meta l4proto icmp meta skgid 994 accept
	}

	chain dnat-dns {
		type nat hook prerouting priority dstnat; policy accept;
		ip daddr 10.139.1.1 udp dport 53 dnat to 10.139.1.1
		ip daddr 10.139.1.1 tcp dport 53 dnat to 10.139.1.1
		ip daddr 10.139.1.2 udp dport 53 dnat to 10.139.1.2
		ip daddr 10.139.1.2 tcp dport 53 dnat to 10.139.1.2
	}
}
table ip6 qubes {
	set downstream {
		type ipv6_addr
	}

	set allowed {
		type ifname . ipv6_addr
	}

	chain antispoof {
		iifname . ip6 saddr @allowed accept
		counter packets 33 bytes 2040 drop
	}

	chain prerouting {
		type filter hook prerouting priority raw; policy accept;
		iifgroup 2 goto antispoof
		ip6 saddr @downstream counter packets 0 bytes 0 drop
	}

	chain postrouting {
		type nat hook postrouting priority srcnat; policy accept;
		oifgroup 2 accept
		oif "lo" accept
		masquerade
	}

	chain _icmpv6 {
		meta l4proto != ipv6-icmp counter packets 0 bytes 0 reject with icmpv6 admin-prohibited
		icmpv6 type { nd-router-advert, nd-redirect } counter packets 0 bytes 0 drop
		accept
	}

	chain input {
		type filter hook input priority filter; policy drop;
		jump custom-input
		ct state invalid counter packets 0 bytes 0 drop
		ct state established,related accept
		iifgroup 2 goto _icmpv6
		iif "lo" accept
		ip6 saddr fe80::/64 ip6 daddr fe80::/64 udp dport 546 accept
		meta l4proto ipv6-icmp accept
		counter packets 0 bytes 0
	}

	chain forward {
		type filter hook forward priority filter; policy drop;
		jump custom-forward
		ct state invalid counter packets 0 bytes 0 drop
		ct state established,related accept
		oifgroup 2 counter packets 0 bytes 0 drop
	}

	chain custom-input {
	}

	chain custom-forward {
		iifgroup 9 oifgroup 2 accept
		iifgroup 2 oifgroup 9 accept
		iifgroup 1 drop
		oifgroup 1 drop
	}

	chain output {
		type filter hook output priority filter; policy drop;
		oifgroup 1 meta skgid 994 accept
		oif "lo" accept
		meta l4proto icmp meta skgid 994 accept
	}
}
table ip qubes-firewall {
	chain forward {
		type filter hook forward priority filter; policy drop;
		ct state established,related accept
		iifname != "vif*" accept
		ip saddr 10.138.0.254 jump qbs-10-138-0-254
		ip saddr 10.138.3.69 jump qbs-10-138-3-69
	}

	chain prerouting {
		type filter hook prerouting priority raw; policy accept;
		iifname != "vif*" ip saddr { 10.137.0.7, 10.138.3.69 } drop
	}

	chain postrouting {
		type filter hook postrouting priority raw; policy accept;
		oifname != "vif*" ip daddr { 10.137.0.7, 10.138.3.69 } drop
	}

	chain qbs-10-138-0-254 {
		accept
		reject with icmp admin-prohibited
	}

	chain qbs-10-138-3-69 {
		accept
		reject with icmp admin-prohibited
	}
}
table ip6 qubes-firewall {
	chain forward {
		type filter hook forward priority filter; policy drop;
		ct state established,related accept
		iifname != "vif*" accept
	}

	chain prerouting {
		type filter hook prerouting priority raw; policy accept;
	}

	chain postrouting {
		type filter hook postrouting priority raw; policy accept;
	}
}
table inet qubes-nat-accel {
	flowtable qubes-accel {
		hook ingress priority filter
		devices = { eth0, lo, vif66.0 }
	}

	chain qubes-accel {
		type filter hook forward priority filter + 5; policy accept;
		meta l4proto { tcp, udp } iifgroup 2 oifgroup 1 flow add @qubes-accel
		counter packets 0 bytes 0
	}
}

Does ping 9.9.9.9 work in qubes connected to your VPN qube?

You need to set DNS server in your VPN config so DNS queries to Qubes OS virtual DNS servers 10.139.1.1/10.139.1.2 from qubes connected to VPN qube will be redirected to real DNS server.

No I can’t ping 9.9.9.9 or 1.1.1.1 or any other public IP I manage that I know should respond.

I had already added: setenv vpn_dns '9.9.9.9 1.1.1.1' to the vpn-client config file. I assumed that was simply setting an internal variable within the service and called scripts since I didn’t see any environment variable being generated.

It’s a straightforward setup I can delete the template and appvm and clone the minimal template again if need be.

The appvm’s unable to pass traffic is only reason I’ve spent so much time on it was just troubleshooting this problem. Getting it up was quite easy.

I added the setenv after everything was up and running. I don’t know maybe that’s throwing something off?