Route qube traffic transparently through a proxy qube (Qubes R4.1 and R4.2)

Original forum link
https://forum.qubes-os.org/t/19902
Original poster
lovemesomesocks5
Created at
2023-07-17 10:25:30
Last wiki edit
2023-07-17 11:35:59
Revisions
2 revisions
Posts count
27
Likes count
16
Tags
networking

Introduction

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.

Requirements

  1. Qubes OS R4.1 or R4.2
  2. A proxy server (SOCKS5, HTTP(S), Shadowsocks)

Setup

Setting up the template

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

Creating sys-proxy qube

Open 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
replace PROXY_IP with your proxy’s IP last command should show accept → drop DNS → drop ICMP → drop

Configuring sys-proxy qube

Open 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
Replace PROXY_IP and with your proxy’s IP, modify proxy settings as needed

For Qubes R4.1

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 &
Replace PROXY_IP and with your proxy’s IP

For Qubes R4.2

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 &
Replace PROXY_IP and with your proxy’s IP

End of Qubes version specific instructions

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!

Using sys-proxy

After 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.

Notes