This guide is for users who want to let a qube access some specific websites, but not the entire Internet. It’s especially useful when using the Qubes firewall isn’t enough — for example, when websites change their IPs often, making domain-based rules unreliable.
⚠️ This guide assumes you know what an HTTP(S) proxy is, and that you're comfortable using the terminal to run commands or edit files.
The setup will create a sys-proxy-out qube that filters access to a list of allowed domains. It uses qvm-connect-tcp so that other qubes can use this proxy, even if they don’t have a NetVM. That way, those qubes can reach only the websites you’ve allowed — nothing more.
I based it on debian 12 xfce so it's easy to setup and will be supported long term.
sudo apt install -y squidsudo systemctl disable squid/etc/squid/squid.conf with this content (the default file is not suitable at all)acl localnet src 127.0.0.1/32
acl SSL_ports port 443
acl Safe_ports port 80
acl Safe_ports port 443
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
acl permit_list dstdomain '/rw/config/domains.txt'
http_access allow localnet permit_list
http_port 3128
logfile_rotate 0
coredump_dir /var/spool/squid
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern . 0 20% 4320
Close the template, you are done with it.
This step could be repeated multiple times, if you want to have multiple proxies with different lists of domains.
* and port TCP 443, and also * and port TCP 80 (this covers basic needs for doing http/https). This is an extra safety to be sure the proxy will not use another port./rw/config/rc.local: systemctl start squid/rw/config/domains.txt with this format:# for a single domain
domain.example
# for all direct subdomains of qubes.org including qubes.org
# this work for doc.qubes-os.org for instance, but not foo.doc.qubes-os.org
.qubes-os.org
⚠️ If you have a line with a domain included by another line, squid will not start as it considers it an error! For instance .qubes.org includes doc.qubes-os.org.
In dom0, edit the file /etc/qubes/policy.d/50-squid.policy with this content:
qubes.ConnectTCP +3128 MyQube @default allow target=sys-proxy-out
qubes.ConnectTCP +3128 MyQube2 @default allow target=sys-proxy-out
This will allow qubes MyQube and MyQube2 to use the proxy from sys-proxy-out. Adapt to your needs here. 👍
Now the proxy is set up, and MyQube is allowed to use it, a few more things are required:
MyQube/rw/config/rc.local to add qvm-connect-tcp ::3128localhost:3128 as a proxyIt's possible to define the proxy user wide, this should be picked by all running programs, using this:
mkdir -p /home/user/.config/environment.d/
cat <<EOF >/home/user/.config/environment.d/proxy.conf
all_proxy=http://127.0.0.1:3128/
EOF
Congratulations for reaching this line!
The sys-proxy-out could be a disposable. In order to proceed:
In the proxy qube, you can check all requests done in /var/log/squid/access.log, you can filter with grep TCP_DENIED to see denied requests, this can be useful to adapt the domain list.
From the http(s) client qube, you can try this command to see if the proxy is working:
curl -x http://localhost:3128 https://a_domain_you_allowed/
If the output is not curl: (56) CONNECT tunnel failed, response 403 then it's working.
Use the same command as above, but with a domain you did not allow
curl -x http://localhost:3128 https://a_domain_you_allowed/
The output should be curl: (56) CONNECT tunnel failed, response 403.