Ad-blocking ProxyVM?

508 views
Skip to first unread message

Joe Ruether

unread,
Feb 9, 2017, 7:32:13 AM2/9/17
to qubes-users
Hello!

I am trying to set up a proxy vm that will redirect DNS requests to a local DNS server, for the purposes of adblocking.

Here is the setup:

internet <-> sys-net <-> sys-firewall <-> MY_PROXYVM <-> appvm_with_firefox

I have created a proxyvm based on a debian-8 template, and have installed PiHole (https://pi-hole.net/) as an adblocker. PiHole works by starting a DNS server (dnsmasq) and rejecting any dns queries to domains that serve ads.

If (in the proxyvm) I set the contents of /etc/resolv.conf to 127.0.0.1 and open firefox (in the proxyvm), I can verify that the adblocker is working correctly.

The issue I am having is when I used the proxyvm as the netvm for another appvm. Without any other changes, my appvm's firefox has internet access, but the adblocker has no effect. Of course, some additional setup is needed, but I'm not exactly sure how to do that.

I'm not very good with iptables, and every attempt I have made to redirect DNS to 127.0.0.1 in the proxyvm has failed (and caused both the proxyvm and the appvm to lose the ability to browse). Here are the commands I ran (in the proxyvm):

#!/bin/bash
DNS=127.0.0.1
NS1=10.137.4.1
NS2=10.137.4.254
iptables -t nat -A PR-QBS -d $NS1 -p udp --dport 53 -j DNAT --to $DNS
iptables -t nat -A PR-QBS -d $NS1 -p tcp --dport 53 -j DNAT --to $DNS
iptables -t nat -A PR-QBS -d $NS2 -p udp --dport 53 -j DNAT --to $DNS
iptables -t nat -A PR-QBS -d $NS2 -p tcp --dport 53 -j DNAT --to $DNS

---

I pieced this together from what I could find from the VPN documentation on the qubes website as well as the contents of /usr/lib/qubes/qubes-setup-dnat-to-ns

Running the qubes-setup-dnat-to-dns script by itself after changing /etc/resolv.conf (all this on the proxyvm) didn't seem to have any impact.

So! My question is, am I going about this correctly? I think I need to modify the iptables in the proxyvm to redirect any incoming (from the appvm) DNS queries to 127.0.0.1, while still allowing outgoing (to the internet, from the proxyvm) DNS queries to get out. Along with this, I think I need to ensure that there are rules that allow all other traffic to pass through unhindered.

Or is there a different, qubes-specific way of handling DNS that I should be using? After inspecting the sys-firewall ipconfig and iptables, it is clear that something behind-the-scenes is happening where an additional NIC is created for each attached appvm, and the iptables are being populated automatically somehow. I'm not sure how the proxyvm is supposed to get the addresses of the appvm and sys-firewall (my script above had addresses hardcoded).

Thank you for any help! If I get all this working, I'm planning on making a Salt file that can create the adblocking proxyvm.

Unman

unread,
Feb 9, 2017, 10:21:26 AM2/9/17
to Joe Ruether, qubes-users
I don't see any reason why this shouldn't work.
I wouldn't be so specific in the nat rules but that's your call. Just
protocol and post would suffice.

One obvious point is that you are ADDING those rules to the end of the
PR-QBS chain without flushing it first. If you already have redirect
rules there they will trigger first.
What does your nat table look like after you run that script?

Another point may be that you don't have an incoming rule in the INPUT
chain allowing inbound traffic to the DNS ports. Unless you've changed
this the default rule will block inbound traffic from any vif interface.
So you need to ensure you are allowing that traffic with an:
iptables -I INPUT -i vif+ -p udp --dport 53 -j ALLOW

Finally, you need to consider the effects of the qubes-firewall and
qubes-netwatcher services.
If you want to retain these you can use
/rw/config/qubes-firewall-user-script to override the automatic Qubes
configuration and insert your own iptables rules.
You can also use rc.local to set initial iptables rules.
Remember to make those files executable if you want to use them.

Most of this is in the docs, although not easy to find.

Hope this helps

unman

Joe Ruether

unread,
Feb 10, 2017, 7:10:07 AM2/10/17
to qubes-users, jrru...@gmail.com, un...@thirdeyesecurity.org

Thank you for your help, I have more information about my configuration below. I am confident that I have an iptables issue, but I can't seem to figure out which rules need to be added.

ifconfig:

eth0 Link encap:Ethernet HWaddr 00:16:3e:5e:6c:01
inet addr:10.137.2.3 Bcast:10.255.255.255 Mask:255.255.255.255
inet6 addr: fe80::216:3eff:fe5e:6c01/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6830 errors:0 dropped:0 overruns:0 frame:0
TX packets:6436 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:4972238 (4.7 MiB) TX bytes:1381735 (1.3 MiB)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:241350 errors:0 dropped:0 overruns:0 frame:0
TX packets:241350 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:17164926 (16.3 MiB) TX bytes:17164926 (16.3 MiB)

vif99.0 Link encap:Ethernet HWaddr fe:ff:ff:ff:ff:ff
inet addr:10.137.4.1 Bcast:0.0.0.0 Mask:255.255.255.255
inet6 addr: fe80::fcff:ffff:feff:ffff/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:27475 errors:0 dropped:0 overruns:0 frame:0
TX packets:4201 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:32
RX bytes:1838038 (1.7 MiB) TX bytes:3767962 (3.5 MiB)

Here is my script with the modifications you suggested:

#!/bin/bash

DNS=127.0.0.1
NS1=10.137.4.1
NS2=10.137.4.254

iptables -t nat -F PR-QBS

iptables -t nat -A PR-QBS -d $NS1 -p udp --dport 53 -j DNAT --to $DNS
iptables -t nat -A PR-QBS -d $NS1 -p tcp --dport 53 -j DNAT --to $DNS

iptables -t nat -A PR-QBS -d $NS2 -p udp --dport 53 -j DNAT --to $DNS
iptables -t nat -A PR-QBS -d $NS2 -p tcp --dport 53 -j DNAT --to $DNS

iptables -I INPUT -i vif+ -p udp --dport 53 -j ACCEPT
iptables -I INPUT -i vif+ -p tcp --dport 53 -j ACCEPT

# Show the table
iptables -t nat -L -v -n

# Is this needed?
# echo 1 > /proc/sys/net/ipv4/ip_forward

---

Here are the results of iptables -L -v -n after running the script:

Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- vif+ * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
0 0 ACCEPT udp -- vif+ * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
0 0 DROP udp -- vif+ * 0.0.0.0/0 0.0.0.0/0 udp dpt:68
94520 8805K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
52952 2754K ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
37 4454 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited

Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
4884 3798K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 ACCEPT all -- vif0.0 * 0.0.0.0/0 0.0.0.0/0
0 0 DROP all -- vif+ vif+ 0.0.0.0/0 0.0.0.0/0
80 5672 ACCEPT udp -- * * 10.137.4.11 10.137.2.1 udp dpt:53
0 0 ACCEPT udp -- * * 10.137.4.11 10.137.2.254 udp dpt:53
0 0 ACCEPT tcp -- * * 10.137.4.11 10.137.2.1 tcp dpt:53
0 0 ACCEPT tcp -- * * 10.137.4.11 10.137.2.254 tcp dpt:53
0 0 ACCEPT icmp -- * * 10.137.4.11 0.0.0.0/0
0 0 DROP tcp -- * * 10.137.4.11 10.137.255.254 tcp dpt:8082
39 2556 ACCEPT all -- * * 10.137.4.11 0.0.0.0/0

Chain OUTPUT (policy ACCEPT 1613 packets, 120K bytes)
pkts bytes target prot opt in out source destination

---

And finally, here is netstat -pan | grep 53 to show the DNS server running:

tcp 0 0 0.0.0.0:53 0.0.0.0:* LISTEN 681/dnsmasq
tcp6 0 0 :::53 :::* LISTEN 681/dnsmasq
udp 0 0 0.0.0.0:5353 0.0.0.0:* 628/avahi-daemon: r
udp 0 0 0.0.0.0:53 0.0.0.0:* 681/dnsmasq
udp6 0 0 :::5353 :::* 628/avahi-daemon: r
udp6 0 0 :::53 :::* 681/dnsmasq
unix 2 [ ACC ] STREAM LISTENING 15533 1274/qrexec-fork-se /var/run/qubes/qrexec-server.user.sock
unix 3 [ ] STREAM CONNECTED 11905 653/meminfo-writer
unix 3 [ ] STREAM CONNECTED 14533 1233/nm-applet
unix 3 [ ] STREAM CONNECTED 14534 883/Xorg @/tmp/.X11-unix/X0

mb

unread,
Feb 10, 2017, 10:02:45 AM2/10/17
to qubes-users
Is there any particular reason you are setting up another app VM for this? Why not run it on the net o firewall VM?

raah...@gmail.com

unread,
Feb 10, 2017, 12:35:26 PM2/10/17
to qubes-users
I never heard of that program looks interesting. I still use iblocklist.com lists with peerguardian on debian 8. But I run it right in the vm. maybe a better idea if you have the resources to run it in a proxy. The vm is protected from the app the and app protected from other apps I guess. sys-net is regarded as untrusted anyways. but why make it even less so maybe.

Unman

unread,
Feb 10, 2017, 6:21:49 PM2/10/17
to Joe Ruether, qubes-users
You dont need to reset forwardijng as it is already enabled - check the
value of /proc/sys/net/ipv4/ip_forward

What I would really like to see would be the output AFTER you attempt a
client conenction.
use iptables -L with the -Z option to zero the counters, then attempt a
connection and look at the output of the nat and filter tables.
I suspect you will immediately see what the problem is.

Joe Ruether

unread,
Feb 12, 2017, 6:14:31 PM2/12/17
to qubes-users, jrru...@gmail.com, un...@thirdeyesecurity.org

Ok, I've spent a lot more time digging into this, and I still can't seem to find the issue. This is going to be a long message...

Below is a dump of the iptables before I made any modifications to them. I have also recently zeroed them out:

======================================


Chain INPUT (policy DROP 0 packets, 0 bytes)

num pkts bytes target prot opt in out source destination
1 0 0 DROP udp -- vif+ * 0.0.0.0/0 0.0.0.0/0 udp dpt:68
2 18 1611 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
3 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
4 10 520 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
5 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited

Chain FORWARD (policy DROP 0 packets, 0 bytes)

num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
2 0 0 ACCEPT all -- vif0.0 * 0.0.0.0/0 0.0.0.0/0
3 0 0 DROP all -- vif+ vif+ 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT udp -- * * 10.137.4.11 10.137.2.1 udp dpt:53
5 0 0 ACCEPT udp -- * * 10.137.4.11 10.137.2.254 udp dpt:53
6 0 0 ACCEPT tcp -- * * 10.137.4.11 10.137.2.1 tcp dpt:53
7 0 0 ACCEPT tcp -- * * 10.137.4.11 10.137.2.254 tcp dpt:53
8 0 0 ACCEPT icmp -- * * 10.137.4.11 0.0.0.0/0
9 0 0 DROP tcp -- * * 10.137.4.11 10.137.255.254 tcp dpt:8082
10 0 0 ACCEPT all -- * * 10.137.4.11 0.0.0.0/0
11 0 0 ACCEPT udp -- * * 10.137.4.18 10.137.2.1 udp dpt:53
12 0 0 ACCEPT udp -- * * 10.137.4.18 10.137.2.254 udp dpt:53
13 0 0 ACCEPT tcp -- * * 10.137.4.18 10.137.2.1 tcp dpt:53
14 0 0 ACCEPT tcp -- * * 10.137.4.18 10.137.2.254 tcp dpt:53
15 0 0 ACCEPT icmp -- * * 10.137.4.18 0.0.0.0/0
16 0 0 DROP tcp -- * * 10.137.4.18 10.137.255.254 tcp dpt:8082
17 0 0 ACCEPT all -- * * 10.137.4.18 0.0.0.0/0

Chain OUTPUT (policy ACCEPT 28 packets, 2131 bytes)
num pkts bytes target prot opt in out source destination
===
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 PR-QBS all -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 PR-QBS-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 10 packets, 520 bytes)
num pkts bytes target prot opt in out source destination

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT all -- * vif+ 0.0.0.0/0 0.0.0.0/0
2 10 520 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
3 0 0 MASQUERADE all -- * * 0.0.0.0/0 0.0.0.0/0

Chain PR-QBS (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DNAT udp -- * * 0.0.0.0/0 10.137.4.1 udp dpt:53 to:10.137.2.1
2 0 0 DNAT tcp -- * * 0.0.0.0/0 10.137.4.1 tcp dpt:53 to:10.137.2.1
3 0 0 DNAT udp -- * * 0.0.0.0/0 10.137.4.254 udp dpt:53 to:10.137.2.254
4 0 0 DNAT tcp -- * * 0.0.0.0/0 10.137.4.254 tcp dpt:53 to:10.137.2.254

Chain PR-QBS-SERVICES (1 references)
num pkts bytes target prot opt in out source destination

======================================

Here is what I think I know: First, the nat table's prerouting rules are applied, which enters into the PR-QBS chain. These rules set up the DNAT such that anything destined for 10.137.4.1 get routed to 10.137.2.1, which essentially tells the packet to forward through to the next netvm.

Next, the filter table's rules are applied. Since the DNS packet is destined for a non-local IP, the FORWARD rules are active, and due to rules 4-8 and 11-14, the DNS packets are allowed through.

So it seems like I need to do two things:
1) Change the prerouting rules to route the packet to the local machine (127.0.0.1)
2) Move the FORWARD rules to INPUT rules, and allow the external packets to enter the local machine, where the PiHole DNS server is running.

So I wrote a python script to do this (pasted at the bottom of this message) and my new iptables rules become this:

======================================


Chain INPUT (policy DROP 0 packets, 0 bytes)

num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT tcp -- * * 10.137.4.11 127.0.0.1 tcp dpt:53
2 0 0 ACCEPT udp -- * * 10.137.4.11 127.0.0.1 udp dpt:53
3 0 0 ACCEPT tcp -- * * 10.137.4.18 127.0.0.1 tcp dpt:53
4 0 0 ACCEPT udp -- * * 10.137.4.18 127.0.0.1 udp dpt:53
5 0 0 DROP udp -- vif+ * 0.0.0.0/0 0.0.0.0/0 udp dpt:68
6 786 71802 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
7 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
8 443 23036 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
9 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited

Chain FORWARD (policy DROP 0 packets, 0 bytes)

num pkts bytes target prot opt in out source destination
1 32 6048 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
2 0 0 ACCEPT all -- vif0.0 * 0.0.0.0/0 0.0.0.0/0
3 0 0 DROP all -- vif+ vif+ 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT icmp -- * * 10.137.4.11 0.0.0.0/0
5 0 0 DROP tcp -- * * 10.137.4.11 10.137.255.254 tcp dpt:8082
6 1 52 ACCEPT all -- * * 10.137.4.11 0.0.0.0/0
7 0 0 ACCEPT icmp -- * * 10.137.4.18 0.0.0.0/0
8 0 0 DROP tcp -- * * 10.137.4.18 10.137.255.254 tcp dpt:8082
9 0 0 ACCEPT all -- * * 10.137.4.18 0.0.0.0/0

Chain OUTPUT (policy ACCEPT 6 packets, 276 bytes)
num pkts bytes target prot opt in out source destination
===
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 3 198 PR-QBS all -- * * 0.0.0.0/0 0.0.0.0/0
2 1 52 PR-QBS-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 3 packets, 156 bytes)
num pkts bytes target prot opt in out source destination

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT all -- * vif+ 0.0.0.0/0 0.0.0.0/0
2 443 23036 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
3 6 396 MASQUERADE all -- * * 0.0.0.0/0 0.0.0.0/0

Chain PR-QBS (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DNAT udp -- * * 0.0.0.0/0 10.137.4.1 udp dpt:53 to:127.0.0.1
2 0 0 DNAT tcp -- * * 0.0.0.0/0 10.137.4.1 tcp dpt:53 to:127.0.0.1
3 0 0 DNAT udp -- * * 0.0.0.0/0 10.137.4.254 udp dpt:53 to:127.0.0.1
4 0 0 DNAT tcp -- * * 0.0.0.0/0 10.137.4.254 tcp dpt:53 to:127.0.0.1

Chain PR-QBS-SERVICES (1 references)
num pkts bytes target prot opt in out source destination

======================================

So at a glance, it looks correct to me:
1) The prerouting will route port 53 to 127.0.0.1
2) The input chain accepts DNS destined for 127.0.0.1
3) The output policy is set to ACCEPT, so when the proxyvm wants to send DNS requests, it should be able to

Unfortunately, after attempting to browse to cnn.com / msn.com etc, nothing ever loads. Here is a dump of the iptables while those pages try to load:

======================================


Chain INPUT (policy DROP 0 packets, 0 bytes)

num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT tcp -- * * 10.137.4.11 127.0.0.1 tcp dpt:53
2 0 0 ACCEPT udp -- * * 10.137.4.11 127.0.0.1 udp dpt:53
3 0 0 ACCEPT tcp -- * * 10.137.4.18 127.0.0.1 tcp dpt:53
4 0 0 ACCEPT udp -- * * 10.137.4.18 127.0.0.1 udp dpt:53
5 0 0 DROP udp -- vif+ * 0.0.0.0/0 0.0.0.0/0 udp dpt:68
6 584 56723 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
7 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
8 309 16068 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
9 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited

Chain FORWARD (policy DROP 0 packets, 0 bytes)

num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
2 0 0 ACCEPT all -- vif0.0 * 0.0.0.0/0 0.0.0.0/0
3 0 0 DROP all -- vif+ vif+ 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT icmp -- * * 10.137.4.11 0.0.0.0/0
5 0 0 DROP tcp -- * * 10.137.4.11 10.137.255.254 tcp dpt:8082
6 0 0 ACCEPT all -- * * 10.137.4.11 0.0.0.0/0
7 0 0 ACCEPT icmp -- * * 10.137.4.18 0.0.0.0/0
8 0 0 DROP tcp -- * * 10.137.4.18 10.137.255.254 tcp dpt:8082
9 0 0 ACCEPT all -- * * 10.137.4.18 0.0.0.0/0

Chain OUTPUT (policy ACCEPT 897 packets, 95080 bytes)
num pkts bytes target prot opt in out source destination
===
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 131 8183 PR-QBS all -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 PR-QBS-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 316 packets, 16558 bytes)
num pkts bytes target prot opt in out source destination

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT all -- * vif+ 0.0.0.0/0 0.0.0.0/0
2 309 16068 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
3 7 490 MASQUERADE all -- * * 0.0.0.0/0 0.0.0.0/0

Chain PR-QBS (1 references)
num pkts bytes target prot opt in out source destination
1 69 4293 DNAT udp -- * * 0.0.0.0/0 10.137.4.1 udp dpt:53 to:127.0.0.1
2 0 0 DNAT tcp -- * * 0.0.0.0/0 10.137.4.1 tcp dpt:53 to:127.0.0.1
3 62 3890 DNAT udp -- * * 0.0.0.0/0 10.137.4.254 udp dpt:53 to:127.0.0.1
4 0 0 DNAT tcp -- * * 0.0.0.0/0 10.137.4.254 tcp dpt:53 to:127.0.0.1

Chain PR-QBS-SERVICES (1 references)
num pkts bytes target prot opt in out source destination

======================================

I don't see packets getting dropped (the drop counters are zero), but I also don't see the INPUT rules I added getting triggered, and I cannot figure out why.

Any further help would be greatly appreciated!
Here is the python script I wrote:

======================================
#!/usr/bin/env python

import subprocess

# Executes the command and returns stdout as a string
def execute(command):
return subprocess.check_output(command.split(" "))

# Given a block of text, returns only the lines that contain the search string
def grep(search_string, text):
results = []
for line in text.split("\n"):
if search_string in line:
results.append(line)
return "\n".join(results)

# Given a block of text, returns only the selected column
# Intended to act like "awk '{print $N}'"
def column(number, text, separator=" "):
results = []
for line in text.split("\n"):
columns = line.split(separator)
columns = [c for c in columns if c != '']
results.append(columns[number])
return "\n".join(results)

# Return a map of key/value pairs parsed from the text, in "ini" format
def key_value(text):
results = {}
for line in text.split("\n"):
pair = line.split("=")
if len(pair) == 2:
results[pair[0]] = pair[1]
return results

# Get the netvm dns
with open("/var/run/qubes/qubes-ns", "r") as file:
content = file.read()
dns_servers = key_value(content).values()

# Get all the iptables rules
filter_rules = execute("iptables -L -n --line-numbers")
nat_rules = execute("iptables -L -n --line-numbers -t nat")

# Extract the DNS entries
dns_entries = grep("53", filter_rules)

# Get the line numbers for the rules to delete
rules_to_delete = [int(r) for r in column(0, dns_entries).split("\n")]

# Delete the rules backwards so the order doesn't get messed up
for rule in reversed(sorted(rules_to_delete)):
execute("iptables -D FORWARD %s" % rule)

# Flush the routing rules
execute("iptables -t nat -F PR-QBS")

# Set up new routes
for ns in dns_servers:
execute("iptables -t nat -A PR-QBS -d %s -p udp --dport 53 -j DNAT --to 127.0.0.1" % ns)
execute("iptables -t nat -A PR-QBS -d %s -p tcp --dport 53 -j DNAT --to 127.0.0.1" % ns)

# Get the source IP addresses for the new DNS rules
ip_addresses = column(4, dns_entries).split("\n")

# Open up the firewall for DNS ports
for ip in list(set(ip_addresses)):
execute("iptables -I INPUT 1 -s %s -p udp -d 127.0.0.1 --dport 53 -j ACCEPT" % ip)
execute("iptables -I INPUT 1 -s %s -p tcp -d 127.0.0.1 --dport 53 -j ACCEPT" % ip)
======================================

Joe Ruether

unread,
Feb 13, 2017, 9:35:52 PM2/13/17
to qubes-users, jrru...@gmail.com, un...@thirdeyesecurity.org
Ok, I need to simplify this. I need help, I don't know what I am missing. Is anyone able to recreate the following netcat test?

I cannot seem to get the DNAT portion of the iptables to work at all. Here is a very simple test:

On the proxyvm, I use the following rules to redirect port 5353 to localhost, and allow the connection:

iptables -t nat -I PR-QBS 1 -d 10.137.4.1 -p tcp --dport 5353 -j DNAT --to-destination 127.0.0.1
iptables -I INPUT 1 -p tcp --dport 5353 -j ACCEPT

Then, on the proxyvm, I run the following command to listen on that port (no other service is running on that port):

nc -l -p 5353

Finally, on the AppVM, I run the following command:

nc 10.137.4.1 5353

My expectation is that the two netcats will connect, however they don't. What do I need to do to get my AppVM to talk to my ProxyVM? Thanks

Joe Ruether

unread,
Feb 14, 2017, 7:08:37 AM2/14/17
to qubes-users, jrru...@gmail.com, un...@thirdeyesecurity.org

Well, I feel like a fool, I finally figured it out. I realized the DNAT rules aren't necessary at all, so all I needed was this:

iptables -I INPUT 1 -p tcp --dport 5353 -j ACCEPT

Of course I overcomplicated such a simple problem... I learned a bunch about iptables though.

I also have the PiHole adblocker working now. In case anyone stumbles onto this thread trying to do the same thing, the final trick was to add the Qubes vif interfaces to a dnsmasq config file to it would listen on them.

toma...@gmail.com

unread,
Apr 30, 2018, 2:40:32 PM4/30/18
to qubes-users
Hi Joe,
I'm would like to build a similar setup, with pi-hole as a proxyVM for some browsing AppVM on my fresh Qubes 4.0 install.
I'm quite a beginner to Qubes (and to linux more genrally) and I'm struggling following what you've done to make it work. (I have also tried to follow some other instructions here: https://blog.tufarolo.eu/how-to-configure-pihole-in-qubesos-proxyvm/ but either I'm missing something, or it doesn't work like this anymore with 4.0)
Have you updated your setup to Qubes 4.0 if needed ?
Would you please agree to summarize as simply and clearly as possible the necessary steps to make it work for a noob like me.
Thanks

Tom

awokd

unread,
May 1, 2018, 3:23:11 AM5/1/18
to toma...@gmail.com, qubes-users
On Mon, April 30, 2018 6:40 pm, toma...@gmail.com wrote:


> I'm would like to build a similar setup, with pi-hole as a proxyVM for
> some browsing AppVM on my fresh Qubes 4.0 install. I'm quite a beginner to
> Qubes (and to linux more genrally) and I'm struggling following what
> you've done to make it work. (I have also tried to follow some other
> instructions here:
> https://blog.tufarolo.eu/how-to-configure-pihole-in-qubesos-proxyvm/ but
> either I'm missing something, or it doesn't work like this anymore with
> 4.0)
> Have you updated your setup to Qubes 4.0 if needed ?
> Would you please agree to summarize as simply and clearly as possible the
> necessary steps to make it work for a noob like me. Thanks

Please see
https://github.com/Qubes-Community/Contents/blob/master/docs/configuration/http-proxy.md
for some ideas how to do it, including R4.0 specific steps.

Reply all
Reply to author
Forward
0 new messages