This guide describes setting up a sys-proxy qube, which will transparently route the traffic of qubes using it as their networking qube through a SOCKS5, HTTP(S) or other supported proxy.
We'll be using a minimal Fedora template. To install it, run in dom0:
sudo qubes-dom0-update qubes-template-fedora-38-minimal
After it has finished installing, open the Qubes update tool in dom0, enable Enable updates for qubes without known available updates, check fedora-38-minimal and hit next, wait for it to finish updateing.
Open Qube Manager, find fedora-38-minimal, right-click it, choose Clone qube, name it fedora-38-minimal-proxy and hit OK.
Open a terminal window in dom0, open up a root terminal in the cloned template:
qvm-run -u root fedora-38-minimal-proxy xterm
Install the necessary software in the template by running in the opened terminal window of the template:
dnf install qubes-core-agent-networking iproute clash dnscrypt-proxy
systemctl disable dnscrypt-proxy
poweroff
sys-proxy qubeOpen the Qube creation tool and configure the qube as follows:
* Name: sys-proxy
* Type: AppVM
* Template: fedora-38-minimal-proxy
* Networking: this is for you to decide, perhaps you want to use a VPN qube, default is sys-firewall
Tick Launch settings after creation and hit OK
Select tab Advanced, tick Provides network
click Apply and then OK
Launch a terminal in dom0 and run:
qvm-firewall sys-proxy del --rule-no 0
qvm-firewall sys-proxy add drop
qvm-firewall sys-proxy add --before 0 drop proto=icmp
qvm-firewall sys-proxy add --before 0 drop specialtarget=dns
qvm-firewall sys-proxy add --before 0 accept PROXY_IP
qvm-firewall sys-proxy
PROXY_IP with your proxy’s IP
last command should show accept → drop DNS → drop ICMP → drop
sys-proxy qubeOpen sys-proxy's terminal by running in dom0:
qvm-run -u root sys-proxy xterm
In sys-proxy's terminal run: mkdir -p /rw/proxy/dns /rw/proxy/clash
Edit /rw/proxy/dns/dnscrypt-proxy.toml in sys-proxy and add:
listen_addresses = ['127.0.0.1:5353']
max_clients = 250
proxy = 'socks5://127.0.0.1:7891'
timeout = 5000
keepalive = 30
ignore_system_dns = true
netprobe_timeout = 0
cache = true
[static]
[static.quad9_doh]
stamp = 'sdns://AgMAAAAAAAAABzkuOS45LjkgKhX11qy258CQGt5Ou8dDsszUiQMrRuFkLwaTaDABJYoSZG5zOS5xdWFkOS5uZXQ6NDQzCi9kbnMtcXVlcnk'
[static.mullvad_doh]
stamp = 'sdns://AgcAAAAAAAAAAAAPZG9oLm11bGx2YWQubmV0Ci9kbnMtcXVlcnk'
Edit /rw/proxy/clash/config.yaml in sys-proxy and add:
socks-port: 7891
redir-port: 7892
mode: rule
allow-lan: true
bind-address: '*'
dns:
enable: false
proxies:
- name: "socks_proxy"
type: socks5
server: PROXY_IP
port: 1080
# username: username
# password: password
# - name: "http_proxy"
# type: http
# server: PROXY_IP
# port: 80
# # username: username
# # password: password
# # tls: true # https
# # skip-cert-verify: true
rules:
- MATCH,socks_proxy # or http_proxy
PROXY_IP and with your proxy’s IP, modify proxy settings as needed
Edit /rw/config/rc.local in sys-proxy and add:
sysctl -w net.ipv4.conf.all.route_localnet=1
iptables -I FORWARD -o eth0 -j DROP
iptables -I FORWARD -i eth0 -j DROP
ip6tables -I FORWARD -o eth0 -j DROP
ip6tables -I FORWARD -i eth0 -j DROP
iptables -P OUTPUT DROP
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -d PROXY_IP -j ACCEPT
iptables -t nat -F PR-QBS
iptables -t nat -A PR-QBS -d 10.139.1.1 -p udp --dport 53 -j DNAT --to 127.0.0.1:5353
iptables -t nat -A PR-QBS -d 10.139.1.1 -p tcp --dport 53 -j DNAT --to 127.0.0.1:5353
iptables -t nat -A PR-QBS -d 10.139.1.2 -p udp --dport 53 -j DNAT --to 127.0.0.1:5353
iptables -t nat -A PR-QBS -d 10.139.1.2 -p tcp --dport 53 -j DNAT --to 127.0.0.1:5353
iptables -t nat -A PREROUTING -i vif+ -p udp -j REDIRECT --to-ports 7892
iptables -t nat -A PREROUTING -i vif+ -p tcp -j REDIRECT --to-ports 7892
iptables -I INPUT -i vif+ -p tcp --dport 7892 -j ACCEPT
iptables -I INPUT -i vif+ -p udp --dport 7892 -j ACCEPT
iptables -I INPUT -i vif+ -p tcp --dport 5353 -j ACCEPT
iptables -I INPUT -i vif+ -p udp --dport 5353 -j ACCEPT
clash -d /rw/proxy/clash >/dev/null 2>&1 &
sleep 0.5
dnscrypt-proxy -config /rw/proxy/dns/dnscrypt-proxy.toml >/dev/null 2>&1 &
PROXY_IP and with your proxy’s IP
Edit /rw/config/rc.local in sys-proxy and add:
sysctl -w net.ipv4.conf.all.route_localnet=1
nft 'add rule ip qubes custom-forward oifname "eth0" drop'
nft 'add rule ip6 qubes custom-forward oifname "eth0" drop'
nft 'add rule ip qubes custom-forward iifname "eth0" drop'
nft 'add rule ip6 qubes custom-forward iifname "eth0" drop'
nft flush chain ip qubes dnat-dns
nft 'add rule ip qubes dnat-dns ip daddr 10.139.1.1 udp dport 53 dnat to 127.0.0.1:5353'
nft 'add rule ip qubes dnat-dns ip daddr 10.139.1.1 tcp dport 53 dnat to 127.0.0.1:5353'
nft 'add rule ip qubes dnat-dns ip daddr 10.139.1.2 udp dport 53 dnat to 127.0.0.1:5353'
nft 'add rule ip qubes dnat-dns ip daddr 10.139.1.2 tcp dport 53 dnat to 127.0.0.1:5353'
nft 'add rule ip qubes custom-input iifname "vif*" tcp dport 7892 accept'
nft 'add rule ip qubes custom-input iifname "vif*" udp dport 7892 accept'
nft 'add rule ip qubes custom-input iifname "vif*" tcp dport 5353 accept'
nft 'add rule ip qubes custom-input iifname "vif*" udp dport 5353 accept'
nft 'add chain ip qubes redir { type nat hook prerouting priority -99 ; policy accept; }'
nft 'add rule ip qubes redir iifname "vif*" ip protocol udp redirect to :7892'
nft 'add rule ip qubes redir iifname "vif*" ip protocol tcp redirect to :7892'
nft 'add chain ip qubes output { type filter hook output priority filter ; policy drop; }'
nft 'add rule ip qubes output ct state related,established accept'
nft 'add rule ip qubes output oifname "lo" accept'
nft 'add rule ip qubes output ip daddr PROXY_IP accept'
clash -d /rw/proxy/clash >/dev/null 2>&1 &
sleep 0.5
dnscrypt-proxy -config /rw/proxy/dns/dnscrypt-proxy.toml >/dev/null 2>&1 &
PROXY_IP and with your proxy’s IP
Download Country.mmdb from here in another qube, move it to sys-proxy’s /rw/proxy/clash directory.
It doesn't actually get used, but the proxy client refuses to start without it, meaning it doesn't have to be kept up-to-date.
Last but not least, restart sys-proxy!
sys-proxyAfter having restarted sys-proxy, you can create a new qube that uses sys-proxy as its networking qube.
To test if it's indeed working, in the new qube curl https://ip.me should show the proxy's IP address.
clash, the proxy client used, also supports other proxy protocols such as Shadowsocks in addition to SOCKS5 and HTTP(S), see their documentation for more details.dnscrypt-proxy, the DNS client used, is being used with a minimal configuration that has two preconfigured DNS servers: Quad9's and Mullvad's DoH servers. You can also configure sources for lists of DNS servers, but make sure to preserve the custom configuration in our dnscrypt-proxy.toml file (before [static]). See their documentation and example config file for details.qvm-firewall is used to block all traffic of all kinds from sys-proxy to any non-proxy IPs.