DoHblock - Blocking DNS over HTTPS via RPZ

Continuing the discussion from:

I read through many of the PDFs from jpgpi250 and I really like this one for DoH blocking:
https://github.com/jpgpi250/piholemanual/blob/master/doc/Unbound%20response%20policy%20zones.pdf

This looks like it will block DoH servers and (this is the best part) the DoH rpz list is updated most every day. I think RPZ (i.e., Unbound’s Response Policy Zones) will solve the issues found when running it as a blocklist.

So I gave it a try. Installing RPZ on an IPFire device is easy to set-up and activate and to use:

Note
• All of the info below came from jpgpi250’s PDF. And from experiments while using RPZ on IPFire.
• For the most part I followed the steps in the PDF but some instructions changed to fit within IPFire.
Please experiment on your test IPFire system and not on a production system.
Keep in mind this will block DoH servers you may want to access (e.g., doh.dns.apple.com or mozilla.cloudflare-dns.com).

1. Set-up

A new directory is needed. Enter the command:

mkdir -v -p -m757 /etc/unbound/zonefiles

Now edit a new configuration file:

nano /etc/unbound/local.d/doh.conf

And add these lines:

server:
	module-config: "respip validator iterator"

rpz:
	name: doh
 	zonefile: /etc/unbound/zonefiles/block.doh.rpz.zone
 	url: https://raw.githubusercontent.com/jpgpi250/piholemanual/master/DOH.rpz
	rpz-action-override: nxdomain
	rpz-log: yes 
	rpz-log-name: doh

Exit `nano` and save file.

Since the unbound program runs as nobody the following lines are needed for all zonefiles to avoid permission errors:

touch /etc/unbound/zonefiles/block.doh.rpz.zone
chown nobody:nobody /etc/unbound/zonefiles/block.doh.rpz.zone
chmod 644 /etc/unbound/zonefiles/block.doh.rpz.zone

Quick test

To check for issues in the config file, run the command on IPFire:

unbound-checkconf 

2. Activate

Restart unbound to load config file:

/etc/init.d/unbound restart

3. Test

  1. Pick a DNS server in the DOH.rpz list and run it on a computer connected to IPFire local GREEN or BLUE network.

    dig 1111.cloudflare-dns.com | grep status
    
  2. Look for status: NXDOMAIN (this is good!):

    $ dig 1111.cloudflare-dns.com | grep status
    
    ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 10004
    
  3. Look for this in the IPFire message log:

    ipfire unbound: [12639:0] info: rpz: applied [doh] mozilla.cloudflare-dns.com. rpz-nxdomain 192.168.60.2@55807 mozilla.cloudflare-dns.com. A IN

Monitoring on IPFire

grep rpz /var/log/messages
#    -or-
tail -f /var/log/messages | grep -i rpz

FAQs

  1. How often does RPZ update?
    • the DOH.rpz file is updated per an SOA line. DOH.rpz updates once a day per the SOA line and its refresh number.
  2. Does anything need to restart to get a new update?
    • Yes, for a change to the doh.conf config file (see above)
    • No, not for the RPZ zone files
  3. What “bad” can happen from enable DoHblock?
    • There will be LOTS of messages like this in the message log:
    Sep  4 20:01:32 ipfire unbound: [12639:0] info: rpz: applied 
    [doh] doh.dns.apple.com. rpz-nxdomain 192.168.60.2@40360 
    doh.dns.apple.com. HTTPS IN
    ...
    Sep 5 09:38:35 ipfire unbound: [12639:0] info: rpz: applied 
    [doh] mozilla.cloudflare-dns.com. rpz-nxdomain 192.168.60.2@34446 
    mozilla.cloudflare-dns.com. A IN
    
    • On Apple iOS / Mac OS: I know this stops the Apple’s Private Relay and maybe the Apple’s Limit IP Address Tracking.
    • On a Firefox browser: This stops Firefox’s DoH via Cloudflare.
    • Android probably has something similar…

And I am still learning… And more changes coming…


EDIT: I made a few mistakes above concerning RPZ refreshing…


EDIT2: updated zonefile directory permissions:

mkdir -v -p -m757 /etc/unbound/zonefiles

updated /etc/unbound/local.d/doh.conf config file:

 	zonefile: /etc/unbound/zonefiles/block.doh.rpz.zone
1 Like

EDIT : The items below are NOT needed for DOH.rpz . Something similar might be needed for an allowlist.

Not needed items - left in-place for reference

To update the RPZ file only once per day:

  1. Edit a new script file:

    nano /etc/fcron.daily/get_doh_rpz.sh
    
  2. And add these lines:

    #!/bin/sh
    theURL="https://raw.githubusercontent.com/jpgpi250/piholemanual/master/DOH.rpz"
    #	download the new file
    /usr/bin/curl --silent "${theURL}" -o /etc/unbound/zonefiles/doh.rpz
    
  3. Make the script executable:

    chmod -v a+x /etc/fcron.daily/get_doh_rpz.sh
    
  4. Launch it to make sure it works and to download the first doh.rpz file!

    /etc/fcron.daily/get_doh_rpz.sh
    
  5. Now update the configuration file:

    nano /etc/unbound/local.d/doh.conf
    
  6. It should look like this:

    server:
    	module-config: "respip validator iterator"
    
    rpz:
    	name: doh
    	zonefile: /etc/unbound/zonefiles/doh.rpz
    	rpz-action-override: nxdomain
    	rpz-log: yes
    	rpz-log-name: doh
    
  7. To check for issues in the config file, run the command on IPFire:

    unbound-checkconf 
    
  8. Restart unbound to load the recently changed config file:

    /etc/init.d/unbound restart
    

Now Test it (like above) and Monitor the message file.

5 Likes

Excellent job Jon !!

DoH servers blocked: view stats with this command:

EDIT: removed cat command line

[root@ipfire ~] # grep -F '[doh]' /var/log/messages | \
  grep -Eo '([a-zA-Z0-9-]{0,62}[a-zA-Z0-9]\.)+[a-zA-Z]{2,63}' | \
  sort | uniq -c | sort -k1,1nr -k2,2
   4286 mozilla.cloudflare-dns.com
   2252 doh.dns.apple.com
   1104 mask-api.icloud.com
      6 1111.cloudflare-dns.com
      2 cloudflare-dns.com
[root@ipfire ~] # 
1 Like

@peppetech and all others,

Can someone give this a try?

If there is interest (and if the IPFire developers approve), I think I can turn this into an add-on.

4 Likes

I had to download manually ,

https://raw.githubusercontent.com/jpgpi250/piholemanual/master/DOH.rpz

the domain was N/A, ironically
but now IPfire is able to download using the silent sh script

Works good now. Will keep reporting back.

FYI - I found two ways to do an “allowlist” for DoH (your favorite DoH server in a list that you cannot live without).

The first is 'hacky" and adds a semicolon before the domain name. It changes this:

doh.dns.apple.com CNAME .

to this:

;doh.dns.apple.com CNAME .

and that allows the DoH server to work as usual.

And the second creates an allowlist with a similar format to this:
https://raw.githubusercontent.com/jpgpi250/piholemanual/master/DOH.rpz

My test allowlist is only two domains long.

I still need to finish scripting the second one.

Is this (either of the above) helpful to anyone?

1 Like

The DoHBlocks can also be monitored in the system logs:

This happens automagically with the existing system log code (no changes by me!)

2 Likes

There are two more edits to the first post.

EDIT2: updated zonefile directory permissions:

mkdir -v -p -m757 /etc/unbound/zonefiles

updated /etc/unbound/local.d/doh.conf config file:

 	zonefile: /etc/unbound/zonefiles/block.doh.rpz.zone
1 Like

Need to disable a zone for testing?

Disable zone

unbound-control rpz_disable [name].zone

Enable zone

unbound-control rpz_enable [name].zone

Disable multiple rpz-type zones

If the name of the zone includes rpz then disable zone(s):

for zone in $( unbound-control list_auth_zones | awk '/rpz/{print $1}' ) ; \
	do printf "$zone\t" ; unbound-control rpz_disable "$zone" ; done

Example output:

[root@ipfire ~] # for zone in $( unbound-control list_auth_zones | awk '/rpz/{print $1}' ) ;    do printf "$zone\t" ; unbound-control rpz_disable "$zone" ; done
allow.doh.rpz.zone.	ok
block.doh.rpz.zone.	ok
block.tld.rpz.zone.	ok
block.sblack.rpz.zone.	ok
block.urlhaus.rpz.zone.	ok
[root@ipfire ~] # 
1 Like

hi
i test you work
i have this file conf

server:
	module-config: "respip validator iterator"

rpz:
	name: allow
 	#zonefile: zonefiles/allow.rpz.zone
 	zonefile: /etc/unbound/zonefiles/allow.rpz.zone
	rpz-log: yes 
	rpz-log-name: allow

rpz:
	name: doh
 	#zonefile: zonefiles/doh.zone
 	zonefile: /etc/unbound/zonefiles/block.doh.rpz.zone
 	url: https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/doh.txt
	rpz-action-override: nxdomain
	rpz-log: yes 
	rpz-log-name: doh

rpz:
	name: block
 	#zonefile: block.rpz.zone
 	zonefile: /etc/unbound/zonefiles/block.rpz.zone
	rpz-action-override: nxdomain
	rpz-log: yes 
	rpz-log-name: block

rpz:
	name: ultimate
 	#zonefile: ultimate.rpz.zone
 	zonefile: /etc/unbound/zonefiles/ultimate.rpz.zone
 	url: https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/ultimate.txt
	rpz-action-override: nxdomain
	rpz-log: yes 
	rpz-log-name: ultimate

rpz:
	name: anti-piracy
 	#zonefile: antipiracy.rpz.zone
 	zonefile: /etc/unbound/zonefiles/anti-piracy.rpz.zone
 	url: https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/anti.piracy.txt
	rpz-action-override: nxdomain
	rpz-log: yes 
	rpz-log-name: anti-piracy

rpz:
	name: doh-vpn-proxy-bypass
 	#zonefile: doh-vpn-proxy-bypass.rpz.zone
 	zonefile: /etc/unbound/zonefiles/doh-vpn-proxy-bypass.rpz.zone
 	url: https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/doh-vpn-proxy-bypass.txt
	rpz-action-override: nxdomain
	rpz-log: yes 
	rpz-log-name: doh-vpn-proxy-bypass

rpz:
	name: dyndns
 	#zonefile: dyndns.rpz.zone
 	zonefile: /etc/unbound/zonefiles/dyndns.rpz.zone
 	url: https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/dyndns.txt
	rpz-action-override: nxdomain
	rpz-log: yes 
	rpz-log-name: dyndns

rpz:
	name: tif
 	#zonefile: tif.rpz.zone
 	zonefile: /etc/unbound/zonefiles/tif.rpz.zone
 	url: https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/tif.txt
	rpz-action-override: nxdomain
	rpz-log: yes 
	rpz-log-name: tif

rpz:
	name: gambling
 	#zonefile: gambling.rpz.zone
 	zonefile: /etc/unbound/zonefiles/gambling.rpz.zone
 	url: https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/gambling.txt
	rpz-action-override: nxdomain
	rpz-log: yes 
	rpz-log-name: gambling

rpz:
	name: hoster
 	#zonefile: hoster.rpz.zone
 	zonefile: /etc/unbound/zonefiles/hoster.rpz.zone
 	url: https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/hoster.txt
	rpz-action-override: nxdomain
	rpz-log: yes 
	rpz-log-name: hoster

rpz:
	name: multi
 	#zonefile: multi.rpz.zone
 	zonefile: /etc/unbound/zonefiles/multi.rpz.zone
 	url: https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/multi.txt
	rpz-action-override: nxdomain
	rpz-log: yes 
	rpz-log-name: multi

is ok for block list but no good for allowlist
the best is possible a add web ui in ipfire for control rpz list
ty

2 Likes

A post was merged into an existing topic: Any way to block all DNS queries and whitelist some?

Agree. But I don’t know how to do this. Any volunteers?!?

Add these lines to the config file. This is an example of the config for my allow zone for the DoH block (1st post):

rpz:
	name: allow.doh.rpz.zone
	zonefile: /etc/unbound/zonefiles/allow.doh.rpz.zone
	rpz-action-override: passthru
	rpz-log: no
	rpz-log-name: dohAllow

NOTE: This MUST go near the top of the config. Like this:

The"allows" go above the “blocks”, otherwise it won’t work.

Notice the rpz-action-override: passthru replaces the rpz-action-override: nxdomain.


Below is the DoH allow zone I use. It is placed in the /etc/unbound/zonefiles directory.

File: /etc/unbound/zonefiles/allow.doh.rpz.zone

$TTL 30			;time (in seconds) that DNS responses are cached
@ SOA LOCALHOST. ipfire.org. (	
	1			; serial number
	1d			; refresh period
	30m			; retry period
	30d			; expire time
	30			; minimum TTL
)
 NS localhost.
;
;	domains and actions list
;
doh.dns.apple.com				CNAME	rpz-passthru.
doh.dns.apple.com.v.aaplimg.com	CNAME	rpz-passthru.
mask-api.icloud.com				CNAME	rpz-passthru.
mask-api.fe.apple-dns.net		CNAME	rpz-passthru.
mask.icloud.com					CNAME	rpz-passthru.
mask-h2.icloud.com				CNAME	rpz-passthru.
mask.apple-dns.net				CNAME	rpz-passthru.

The above is my example, Remove my items first and then place the items you want to allow in the list.

Notice the CNAME rpz-passthru. replaces the CNAME .

Make sure you increment the serial number otherwise the new zone file will not be captured into RPZ.


EDIT: Since we changed the config file make sure you do these commands:

Quick test

To check for issues in the config file, run the command on IPFire:

unbound-checkconf 

Activate

Restart unbound to load config file:

/etc/init.d/unbound restart
1 Like

More info about RPZ:

1 Like

A post was merged into an existing topic: Any way to block all DNS queries and whitelist some?

3 posts were merged into an existing topic: Any way to block all DNS queries and whitelist some?

I was looking through your conf file: Keep in mind with lots of RPZ zones (each with many lines of domains) you may slow down DNS to a crawl (i.e., it takes a long time to resolve a domain name).

Also, Thank you for testing! I do appreciate the feedback!

1 Like

hi
i test other config rpz

server:
	module-config: "respip validator iterator"

	define-tag: "ipfire"
	define-tag: "allow block"
	define-tag: "wiffi"
	define-tag: "nas"

	# Per client IP ...
	access-control-tag: 127.0.0.1/32 "ipfire"
	access-control-tag: 192.168.1.2/32 "allow block"
	access-control-tag: 192.168.1.5/32 "nas"
	access-control-tag: 192.168.2.0/24 "wiffi"

rpz:
	# The name of the RPZ authority zone
	name: ipfire

	# The location of the remote RPZ zonefile.
	# url: http://www.example.com/example.org.zone (not a real RPZ file)
 	#zonefile: zonefiles/ipfire.rpz.zone
 	zonefile: /etc/unbound/zonefiles/ipfire.rpz.zone
 	tags: "ipfire"

 	# Always use this RPZ action for matching triggers from this zone.
	# Possible action are: nxdomain, nodata, passthru, drop, disabled,
	# and cname.
	rpz-action-override: passthru

	# Log all applied RPZ actions for this RPZ zone. Default is no.
	rpz-log: yes

	# Specify a string to be part of the log line.
	rpz-log-name: IPFIRE

rpz:
	# The name of the RPZ authority zone
	name: nas

	# The location of the remote RPZ zonefile.
	# url: http://www.example.com/example.org.zone (not a real RPZ file)
 	#zonefile: zonefiles/nas.rpz.zone
 	zonefile: /etc/unbound/zonefiles/nas.rpz.zone
 	tags: "nas"

 	# Always use this RPZ action for matching triggers from this zone.
	# Possible action are: nxdomain, nodata, passthru, drop, disabled,
	# and cname.
	rpz-action-override: passthru

	# Log all applied RPZ actions for this RPZ zone. Default is no.
	rpz-log: yes

	# Specify a string to be part of the log line.
	rpz-log-name: NAS

rpz:
	# The name of the RPZ authority zone
	name: wiffi

	# The location of the remote RPZ zonefile.
	# url: http://www.example.com/example.org.zone (not a real RPZ file)
 	#zonefile: zonefiles/wiffi.rpz.zone
 	zonefile: /etc/unbound/zonefiles/wiffi.rpz.zone
 	tags: "wiffi"

 	# Always use this RPZ action for matching triggers from this zone.
	# Possible action are: nxdomain, nodata, passthru, drop, disabled,
	# and cname.
	rpz-action-override: passthru

	# Log all applied RPZ actions for this RPZ zone. Default is no.
	rpz-log: yes

	# Specify a string to be part of the log line.
	rpz-log-name: WIFFI

rpz:
	# The name of the RPZ authority zone
	name: allow

	# The location of the remote RPZ zonefile.
	# url: http://www.example.com/example.org.zone (not a real RPZ file)
 	#zonefile: zonefiles/allow.rpz.zone
 	zonefile: /etc/unbound/zonefiles/allow.rpz.zone
 	tags: "allow"

 	# Always use this RPZ action for matching triggers from this zone.
	# Possible action are: nxdomain, nodata, passthru, drop, disabled,
	# and cname.
	rpz-action-override: passthru

	# Log all applied RPZ actions for this RPZ zone. Default is no.
	rpz-log: yes

	# Specify a string to be part of the log line.
	rpz-log-name: ALLOW

rpz:
	# The name of the RPZ authority zone
	name: block

	# The location of the remote RPZ zonefile.
	# url: http://www.example.com/example.org.zone (not a real RPZ file)
 	#zonefile: block.rpz.zone
 	zonefile: /etc/unbound/zonefiles/block.rpz.zone
	tags: "block"

 	# Always use this RPZ action for matching triggers from this zone.
	# Possible action are: nxdomain, nodata, passthru, drop, disabled,
	# and cname.
	rpz-action-override: nxdomain

	# Log all applied RPZ actions for this RPZ zone. Default is no.
	rpz-log: yes

	# Specify a string to be part of the log line.
	rpz-log-name: BLOCK

the files in zone directory
allow.rpz.zone block.rpz.zone ipfire.rpz.zone nas.rpz.zone wiffi.rpz.zone
all work fine
ty

1 Like

I just started reading about “tags”. Do you see something different in the logs when using tags?

1 Like