How to make proxy VM with HTTP/Socks5 proxy instead of VPN?

I have created proxy and client VMs. I checked provides network when creating proxy and set NetVM of client to proxy and the NetVM of proxy is sys-firewall. Both client and proxy can connect to network at start.
Then I install and run proxy program in proxy VM and make it be transparent by updating iptables, now traffic of terminal and browser in proxy VM goes through proxy program but traffic from client VM doesn’t go through proxy program although client can still connect to network. I think I may need to update iptables about client in proxy VM but I am not familiar with iptables.
I want traffic from client VM to go through the proxy program in proxy VM.

iptables in proxy VM

$ sudo iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
PR-QBS     all  --  anywhere             anywhere            
PR-QBS-SERVICES  all  --  anywhere             anywhere            

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
clash_out  tcp  --  anywhere             anywhere            
clash_dns_out  udp  --  anywhere             anywhere            

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
MASQUERADE  all  --  anywhere             anywhere            

Chain PR-QBS (1 references)
target     prot opt source               destination         
DNAT       udp  --  anywhere             10.139.1.1           udp dpt:domain to:10.139.1.1
DNAT       tcp  --  anywhere             10.139.1.1           tcp dpt:domain to:10.139.1.1
DNAT       udp  --  anywhere             10.139.1.2           udp dpt:domain to:10.139.1.2
DNAT       tcp  --  anywhere             10.139.1.2           tcp dpt:domain to:10.139.1.2

Chain PR-QBS-SERVICES (1 references)
target     prot opt source               destination         

Chain clash_dns_out (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere             owner GID match shellclash
REDIRECT   udp  --  anywhere             anywhere             udp dpt:domain redir ports 1053
REDIRECT   tcp  --  anywhere             anywhere             tcp dpt:domain redir ports 1053

Chain clash_out (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere             owner GID match shellclash
RETURN     all  --  anywhere             0.0.0.0/8           
RETURN     all  --  anywhere             10.0.0.0/8          
RETURN     all  --  anywhere             127.0.0.0/8         
RETURN     all  --  anywhere             169.254.0.0/16      
RETURN     all  --  anywhere             172.16.0.0/12       
RETURN     all  --  anywhere             192.168.0.0/16      
RETURN     all  --  anywhere             base-address.mcast.net/4 
RETURN     all  --  anywhere             240.0.0.0/4         
REDIRECT   tcp  --  anywhere             anywhere             multiport dports ssh,domain,submission,submissions,pop3s,imaps,imap2,http,https,http-alt redir ports 7892
# iptables -L -v
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  any    any     anywhere             anywhere             state INVALID
    0     0 DROP       udp  --  vif+   any     anywhere             anywhere             udp dpt:bootpc
46620   47M ACCEPT     all  --  any    any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  vif+   any     anywhere             anywhere            
  554 31835 ACCEPT     all  --  lo     any     anywhere             anywhere            
    0     0 REJECT     all  --  vif+   any     anywhere             anywhere             reject-with icmp-host-prohibited
    0     0 DROP       all  --  any    any     anywhere             anywhere            

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  any    any     anywhere             anywhere             state INVALID
 2616 5905K ACCEPT     all  --  any    any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
   23  1421 QBS-FORWARD  all  --  any    any     anywhere             anywhere            
    0     0 DROP       all  --  vif+   vif+    anywhere             anywhere            
    0     0 ACCEPT     all  --  vif+   any     anywhere             anywhere            
    0     0 DROP       all  --  any    any     anywhere             anywhere            

Chain OUTPUT (policy ACCEPT 28962 packets, 11M bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain QBS-FORWARD (1 references)
 pkts bytes target     prot opt in     out     source               destination         
   23  1421 qbs-10-137-0-27  all  --  any    any     10.137.0.27          anywhere            
    0     0 RETURN     all  --  !vif+  any     anywhere             anywhere            
    0     0 DROP       all  --  any    any     anywhere             anywhere            

Chain qbs-10-137-0-27 (1 references)
 pkts bytes target     prot opt in     out     source               destination         
   23  1421 ACCEPT     all  --  any    any     anywhere             anywhere            
    0     0 REJECT     all  --  any    any     anywhere             anywhere             reject-with icmp-admin-prohibited
1 Like

I don’t see a PREROUTING rule in your nat table to redirect to your transparent proxy; it will only capture outgoing traffic with the rules currently listed. Assuming DNS listener is port 1053 and TCP transparent proxy listener (redsocks?) is at port 7892, this might do it:

iptables -t nat -I PREROUTING -i vif+ -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j REDIRECT --to-ports 7892
iptables -I INPUT -i vif+ -p tcp -m tcp --dport 7892 -j ACCEPT
iptables -t nat -I PREROUTING -i vif+ -p udp -m udp --dport 53 -j REDIRECT --to-ports 1053
iptables -I INPUT -i vif+ -p udp -m udp --dport 1053 -j ACCEPT

First two rules forward all new TCP SYN packets from vif interfaces to port 7892, other forwards UDP port 53 (DNS) from vif interfaces to port 1053.

You also want to make sure forwarding is disabled to prevent leaks.

How to proxy Qubes UDP traffic?

Sorry to interrupt you again, but I have tried multiple rules and I don’t know how to debug iptables problem.

I use TPROXY to proxy UDP

-A table_name -s 192.168.0.0/16 -p udp -j TPROXY --on-port 7892 --on-ip 0.0.0.0 --tproxy-mark tproxy-mark
-A table_name -s 10.0.0.0/8 -p udp -j TPROXY --on-port 7892 --on-ip 0.0.0.0 --tproxy-mark tproxy-mark

I tried to redirect Qubes vif+ traffic, but this doesn’t work

iptables -t nat -I PREROUTING -i vif+ -p udp -m udp -j REDIRECT --to-ports 7892
iptables -I INPUT -i vif+ -p udp -m udp --dport 7892 -j ACCEPT
1 Like

You may like this GitHub - hexstore/qubes-proxy: 集成通用代理工具(sing-box)在Qubes OS | mirror from https://git.sr.ht/~qubes/proxy

Hi, I prefer to be modular and let one thing do one job, so I have created a very simple ProxyVM which shall block all non-tcp traffic (including the Qubes’ special DNS handling), and forward everything to a SOCKS proxy. For this I used tun2socks (one of the many, GitHub - xjasonlyu/tun2socks: tun2socks - powered by gVisor TCP/IP stack), and created the following content in /rw/config/rc.local:

# configure socks server
SOCKS_SERVER=10.138.14.50
SOCKS_PORT=3333

#disable ipv6
sysctl -w net.ipv6.conf.all.disable_ipv6=1
sysctl -w net.ipv6.conf.default.disable_ipv6=1

ip route del default
ip tuntap add mode tun dev tun0
ip addr add 192.168.192.1/24 dev tun0
ip link set dev tun0 up
ip route add default via 192.168.192.1 dev tun0 metric 1

ip route add $SOCKS_SERVER dev eth0 metric 10
/home/user/tun2socks-linux-amd64 -device tun0 -interface eth0 -loglevel silent -proxy socks5://$SOCKS_SERVER:$SOCKS_PORT

and some basic anti-leak rules in /rw/config/qubes-firewall-user-script:

iptables -I FORWARD -o eth0 -j DROP
iptables -I FORWARD -i eth0 -j DROP
ip6tables -I FORWARD -j DROP

iptables -I FORWARD ! -p tcp -j REJECT
iptables -I OUTPUT ! -p tcp -j REJECT

iptables -F PR-QBS

Does this look safe, or did I miss something?