I created a test version of a RPZ add-on and I am looking for feedback

I created a test version of a RPZ add-on. I am looking for feedback so if you are interested please let me know.

It needs a little work like the addition of copyright and some documentation (in progress).


EDIT: Here is a draft of the RPZ add-on Wiki:

https://www.ipfire.org/docs/addons/rpz

Comments are welcome!


EDIT2: changed PDF to a Wiki page

4 Likes

I installed the test version using Jon’s instructions and restarted unbound without issues.

1 Like

Another suggestion for an RPZ Blocklist :

URLhaus - malicious URLs that are being used for malware distribution.

Download link
https://urlhaus.abuse.ch/downloads/rpz/
Allowed Update Frequency: every 5 minutes

1 Like

One suggestion for blocklists, more:

This is a comprehensive compilation of various lists for many use cases. Not only for the RPZ mechanism but for other means of DNS blocking, also.

4 Likes

Thank you for suggesting this great list. I have been using Gerd’s IP blocklist for a year since July 2023. It is a very well thought out and you can see how much effort he put into this repository. The blocklists are organized in such a meticulous way I haven’t seen anywhere else. He puts to shame even many so called security vendors :slight_smile:

3 Likes

I have been trying out some of the usage:

# rpz-config add urlhaus https://urlhaus.abuse.ch/downloads/rpz/
unbound: info: rpz: add config file "urlhaus.rpz.conf"
changed ownership of '/etc/unbound/zonefiles/urlhaus.rpz' from root:root to nobody:nobody
mode of '/etc/unbound/zonefiles/urlhaus.rpz' retained as 0644 (rw-r--r--)
unbound: rpz: running "unbound-control reload"
ok

# rpz-metrics 3
name         hits     active   lines    hits/line%  last update
---------------/usr/sbin/rpz-metrics: line 111: 100 * theHits / theLines : division by 0 (error token is "theLines ")
--------------
             =======           ========
Totals -->   0                 0

Looking through the unbound log, it looks like it is working as intended:
these domains or on the Threatfox or Urlhaus block lists

info: rpz: applied [threatfox] mail.08rococoephemeral.buzz. rpz-nxdomain 127.0. 0.1@33908 mail.08rococoephemeral.buzz. A IN
unbound: [7750:0]	info: rpz: applied [threatfox] mail.08rococoephemeral.buzz. rpz-nxdomain 127.0. 0.1@33908 mail.08rococoephemeral.buzz. AAAA IN
unbound: [7750:0]	info: rpz: applied [threatfox] mail.08rococoephemeral.buzz. rpz-nxdomain 127.0. 0.1@33821 mail.08rococoephemeral.buzz. A IN
unbound: [7750:0]	error: SERVFAIL <06melliineffable.buzz. A IN>: exceeded the maximum number of s ends

I assume the 300 seconds update interval for Threatfox and URLhaus is not modifiable

$TTL 30
@ SOA rpz.threatfox.abuse.ch. hostmaster.threatfox.abuse.ch. 2407301803 300 1800 604800 30

I added the tmpfs line to /etc/fstab to prevent flash memory wear
it is in Chapter 8

One of the rpz files is still empty and theLine count is zero. Enter

ls -al /etc/unbound/zonefiles 

and check if urlhaus.rpz is there and has data.

1 Like

urlhaus.rpz is 49 kB and has data

$TTL 30
@ SOA rpz.urlhaus.abuse.ch. hostmaster.urlhaus.abuse.ch. 2407302235 300 1800 604800 30
 NS localhost.
;
; abuse.ch URLhaus Response Policy Zones (RPZ)
; Last updated: 2024-07-30 22:35:06 (UTC)
;
; Terms Of Use: https://urlhaus.abuse.ch/api/
; For questions please contact urlhaus [at] abuse.ch
;
testentry.rpz.urlhaus.abuse.ch CNAME . ; Test entry for testing URLhaus RPZ
01melliserendipity.buzz CNAME . ; Malware download (2024-07-29), see https://urlhaus.abuse.ch/host/01melliserendipity.buzz/
01mystiquenebula.buzz CNAME . ; Malware download (2024-07-29), see https://urlhaus.abuse.ch/host/01mystiquenebula.buzz/

but the ‘block.rpz’ and ‘allow.rpz’ files are empty

I can wait and check tomorrow

ahhh! Good find! I’ll add a test for zero lines in a file!

3 Likes

I can send you the lines that changed. Or the entire /usr/sbin/rpz-metrics file. Let me know what is better for you.

I do not have the full rpz-n-n.ipfire build yet (it is still building!)

Here is the entire /usr/sbin/rpz-metrics file:

#!/bin/bash
###############################################################################
#                                                                             #
#  IPFire.org - A linux based firewall                                        #
#  Copyright (C) 2024  IPFire Team  <info@ipfire.org>                         #
#                                                                             #
#  This program is free software: you can redistribute it and/or modify       #
#  it under the terms of the GNU General Public License as published by       #
#  the Free Software Foundation, either version 3 of the License, or          #
#  (at your option) any later version.                                        #
#                                                                             #
#  This program is distributed in the hope that it will be useful,            #
#  but WITHOUT ANY WARRANTY; without even the implied warranty of             #
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              #
#  GNU General Public License for more details.                               #
#                                                                             #
#  You should have received a copy of the GNU General Public License          #
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.      #
#                                                                             #
###############################################################################

#	v19 on 2024-07-30

###############       Main        ###############

weeks="${1:-2}"			#	default to two message logs
sortBy="${2:-name}"  	#	by name or by hits

#	get the list of message logs for N weeks
messageLogs=$( find /var/log/messages* -type f |
	/usr/bin/sort --version-sort |
	head -"${weeks}" )

#	get the list of RPZ names & counts from the message log(s)
rpzNameCount=$( for logf in ${messageLogs} ; do
	/usr/bin/zgrep --text --extended-regexp 'info: rpz: applied.* A IN$' "${logf}" |
	/usr/bin/awk '$10 ~ /\[\w*]/ { print $10 }' ;
	done | /usr/bin/sort | /usr/bin/uniq --count )

#	flip results and remove brackets `[` and `]`
rpzNameCount=$( /bin/echo "${rpzNameCount}" |
	/usr/bin/awk '{ print $2, $1 }' |
	/bin/sed --regexp-extended 's|^\[(.*)\]|\1|' )

#	grab only names
rpzNames=$( /bin/echo "${rpzNameCount}" | /usr/bin/awk '{ print $1 }' )

#	get list of RPZ files
rpzFileList=$( /bin/find /etc/unbound/zonefiles -type f -iname "*.rpz" )

#	get basename of those files
rpzBaseNames=$( /bin/echo "${rpzFileList}" |
	/bin/sed 's|/etc/unbound/zonefiles/||g ; s|\.rpz||g ;' )

#	add to rpzNames
rpzNames="${rpzNames}"$'\n'"${rpzBaseNames}"

#	drop duplicate names
rpzNames=$( echo "${rpzNames}" | /usr/bin/sort --unique  )

#	get line count for each RPZ
lineCount=$( /bin/echo "${rpzFileList}" | /usr/bin/xargs wc -l )

#	get comment line count and blank line count for each RPZ
commentCount=$( /bin/echo "${rpzFileList}" |
	/usr/bin/xargs /bin/grep --count -e "^$" -e "^;" )

#	get modified date each RPZ
modDateList=$( /bin/echo "${rpzFileList}" | xargs stat -c '%.10y  %n' )

ucListAuthZones=$( /usr/sbin/unbound-control list_auth_zones )

#	get width of RPZ names
pWidth=$( /bin/echo "${rpzNames}" | /usr/bin/awk '{ print $1"   " }' | wc -L )
pFormat="%-${pWidth}s %-8s %-8s %-8s %10s %12s\n"

#	print title line
printf "${pFormat}" "name" "hits" "active" "lines" "hits/line%" "last update"
printf -- "--------------"

theResults=""
totalLines=0
totalHits=0
while read -r theName
do
	printf -- "-"									#	pretend progress bar
	#	get hit count
	theHits="0"
	if output=$( /bin/grep "^${theName}\s" <<< "${rpzNameCount}" ) ; then
		theHits=$( /bin/echo "${output}" |
		/usr/bin/awk '{ print $2 }' )
		totalHits=$(( totalHits + theHits ))
	fi

	#	is this RPZ list active?
	theActive="disabled"
	if /bin/grep --quiet "^${theName}\.rpz" <<< "${ucListAuthZones}"
	then
		theActive="enabled"
	fi

	#	get line count then subtract comment count and blank line count
	#	  from total line count
	theLines="n/a"
	hitsPerLine="0"
	if output=$( /bin/grep --fixed-strings "/${theName}.rpz" <<< "${lineCount}" ) ; then
		theLines=$( /bin/echo "${output}" | /usr/bin/awk '{ print $1 }' )
		totalLines=$(( totalLines + theLines ))

		if [[ "${theLines}" -gt 2 ]] ; then
			hitsPerLine=$(( 100 * theHits / theLines ))
		fi
	fi

	#	get modification date
	theModDate="n/a"
	if output=$( /bin/grep --fixed-strings "/${theName}.rpz" <<< "${modDateList}" ) ; then
		theModDate=$( /bin/echo "${output}" | /usr/bin/awk '{ print $1 }' )
	fi

	#	add to results list
	theResults+="${theName} ${theHits} ${theActive} ${theLines} ${hitsPerLine} ${theModDate}"$'\n'
done <<< "${rpzNames}"

case "${sortBy}" in
	names|name)	sortArg=(-k3,3r -k1,1)			;;	#	sort by "active" then by "name"

	hits|hit)	sortArg=(-k3,3r -k2,2nr -k1,1)	;;	#	sort by "active" then by "hits" then by "name"

	lines|line)	sortArg=(-k3,3r -k4,4nr -k1,1)	;;	#	sort by "active" then by "lines" then by "name"
esac

printf -- "--------------\n"
#	remove blank lines, sort, print as columns
/bin/echo "${theResults}" |
	/usr/bin/awk '!/^[[:space:]]*$/' |
	/usr/bin/sort "${sortArg[@]}"    |
	/usr/bin/awk --assign=width="${pWidth}" \
		'{ printf "%-*s %-8s %-8s %-8s %10s %12s\n", width, $1, $2, $3, $4, $5, $6 }'

printf "${pFormat}" "" "=======" "" "========" "" ""
printf "${pFormat}" "Totals -->" "${totalHits}" "" "${totalLines}" "" ""

exit
1 Like

The error with rpz-metrics is produced by the absence of the allow and blocked rpz files.

I edited the corresponding files in /var/ipfire/rpz by adding an empty line.
With this rpz-config make allowblock makes the missing files.

EDIT: @jon’s correction eliminated the error

1 Like

Another RPZ blocklist

Identify and blacklist SSL certificates used by botnet C&C servers.
Download link
https://sslbl.abuse.ch/blacklist/sslbl.rpz
Allowed Update Frequency: every 5 minutes

Edit: SSLBL blocklist gives me a lot of false positive.

it could be caused by the shared IP on Cloudflare but still not ideal.

unbound: [15652:0]	info: rpz: applied [sslbl] 188.114.96.3/32 rpz-nxdomain 192.168.1.51@36827 phi shing.army. A IN

unbound: [15652:0]	info: rpz: applied [sslbl] 188.114.96.3/32 rpz-nxdomain 192.168.1.51@40463 die tpi.com. A IN

Hi @jon ,
I downloaded JonMurphy:RPZ.pdf (1.1 MB) and tried to open the GIT Hub links toward RPZ scrips (section Usage in the above PDF): none seems to be valid anymore.

Same for www.ipfire.org - RPZ - Response Policy Zones - none of the links from Wiki that point toward scripts is not working nowadays.

How can someone get those scrips these days?

Thanks!

All of the scripts are bundled into a package for testing.

rpz-1.0.0-1.ipfire (20 KB)

Here are the steps to install:

Access the IPFire device via SSH (or serial console).

I am not sure of your setup so you may want to copy your existing conf files to a backup location. Do a backup of the files located in the /etc/unbound/local.d directory and place them somewhere safe (just incase).

Copy the rpz-1.0.0-1.ipfire file to the /opt/pakfire/tmp/ directory. (Speak up if you need assistance with this!)

Then:

#   go to this directory:
cd /opt/pakfire/tmp/

#   uncompress the file:
tar xvf rpz-1.0.0-1.ipfire

#   check to make sure there are files there:
ls -l /opt/pakfire/tmp

#   copy this one file to a new location
cp -v ROOTFILES /opt/pakfire/db/rootfiles/rpz

#   run the install
NAME=rpz ./install.sh

PS - please post comments in the Community post. Michael is looking for feedback for RPZ. Feel free to post in this thread.

2 Likes

Started!
Will do!

curl https://community.ipfire.org/uploads/short-url/p7ZMNOioiX0NqfXhZ1BaH2TXbzW.ipfire --output /opt/pakfire/tmp/rpz-1.0.0-1.ipfire

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 20480    0 20480    0     0  80312      0 --:--:-- --:--:-- --:--:-- 80629

cd /opt/pakfire/tmp/
tar xvf rpz-1.0.0-1.ipfire
ROOTFILES
files.tar.xz
install.sh
uninstall.sh
update.sh

ls -l
total 40
-rw-r--r-- 1 root root  4028 Aug  1 07:22 files.tar.xz
-rwxr-xr-- 1 root root  1671 Aug  1 07:22 install.sh
-rw-r--r-- 1 root root   293 Aug  1 07:22 ROOTFILES
-rw-r--r-- 1 root root 20480 Aug  4 19:00 rpz-1.0.0-1.ipfire
-rwxr-xr-- 1 root root  1738 Aug  1 07:22 uninstall.sh
-rwxr-xr-- 1 root root  1618 Aug  1 07:22 update.sh

cp -v ROOTFILES /opt/pakfire/db/rootfiles/rpz
'ROOTFILES' -> '/opt/pakfire/db/rootfiles/rpz'

Late edit: install went fine!

NAME=rpz ./install.sh
Extracting files...
etc/
etc/unbound/
etc/unbound/zonefiles/
etc/unbound/zonefiles/block.rpz
etc/unbound/zonefiles/allow.rpz
etc/unbound/local.d/
etc/unbound/local.d/00-rpz.conf
usr/
usr/sbin/
usr/sbin/rpz-sleep
usr/sbin/rpz-metrics
usr/sbin/rpz-config
var/
var/ipfire/
var/ipfire/dns/
var/ipfire/dns/rpz/
var/ipfire/dns/rpz/blocklist
var/ipfire/dns/rpz/allowlist
var/ipfire/backup/
var/ipfire/backup/addons/
var/ipfire/backup/addons/includes/
var/ipfire/backup/addons/includes/rpz
...Finished.
Stopping Unbound DNS Proxy...                                                                                                                                                       [  OK  ]
Starting Unbound DNS Proxy...                                                                                                                                                       [  OK  ]

Tested:

#load DOH.rpz list from above post 
rpz-config add BlockDOH_jpgpi250 https://raw.githubusercontent.com/jpgpi250/piholemanual/master/DOH.rpz
unbound: info: rpz: add config file "BlockDOH_jpgpi250.rpz.conf"
unbound: rpz: running "unbound-control reload"
ok

#Then test one of the DOH servers from that DOH.rpz list
nslookup 2.dnscrypt-cert.browser.yandex.net
Server:         127.0.0.1
Address:        127.0.0.1#53

** server can't find 2.dnscrypt-cert.browser.yandex.net: NXDOMAIN

Working fine, I would say!

3 Likes

[Testing for]

Loading more lists

rpz-config add SSLblAbuseCh https://sslbl.abuse.ch/blacklist/sslbl.rpz
 rpz-config add URLHausAbuseCh 
unbound: info: rpz: add config file "SSLblAbuseCh.rpz.conf"
unbound: rpz: running "unbound-control reload"
ok

rpz-config add URLHausAbuseCh https://urlhaus.abuse.ch/downloads/rpz/
unbound: info: rpz: add config file "URLHausAbuseCh.rpz.conf"
unbound: rpz: running "unbound-control reload"
ok


Some metrics after loading several lists:

rpz-metrics
name                 hits     active   lines    hits/line%  last update
---------------------------------
allow                0        enabled  0                 0   2024-08-01
block                0        enabled  0                 0   2024-08-01
BlockDOH_jpgpi250    1        enabled  3651              0   2024-08-04
SSLblAbuseCh         0        enabled  52                0   2024-08-04
URLHausAbuseCh       0        enabled  251               0   2024-08-04
                     =======           ========
Totals -->           1                 3954
2 Likes

Just for the records.

I’m using @jon’s work now for weeks. No real problems ( which couldn’t solved by jon or myself :wink: )

I think the concept of DNS block lists is effective in times of more and more HTTPS URLs. HTTPS is not manageable by the proxy without doing MITM steps.
Therefore PiHole and similiar got more and more importance. RPZ in unbound does the same job and unbound is part of IPFire, yet.

Remark for the careful, which fear about stability:
The RPZ feature is added by some easy config lines in unbound.conf.
A deletion of these lines and unbound-control reload stops it.
RPZ uses mechanisms for name resolution already active in unbound.

2 Likes

[More testing for DOH.rpz list]

I tried Opendns.com web pages (the DOH servers are in DOH.rpz source) and site worked. I guess that is ok…

But other sites from that DOH.rpz list are blocked:

19:23:51	unbound: [14790:0]	info: rpz: applied [BlockDOH_jpgpi250] 2.dnscrypt-cert.browser.yandex.net. rpz- nxdomain 127.0.0.1@51509 2.dnscrypt-cert.browser.yandex.net. A IN
19:42:22	unbound: [14790:0]	info: rpz: applied [BlockDOH_jpgpi250] 2.11i.eu. rpz-nxdomain 192.168.10.254@51 031 2.11i.eu. A IN
19:42:29	unbound: [14790:0]	info: rpz: applied [BlockDOH_jpgpi250] 2.11i.eu. rpz-nxdomain 192.168.10.254@41 449 2.11i.eu. A IN

 rpz-metrics
name                 hits     active   lines    hits/line%  last update
---------------------------------
allow                0        enabled  0                 0   2024-08-01
block                0        enabled  0                 0   2024-08-01
BlockDOH_jpgpi250    3        enabled  3651              0   2024-08-04
SSLblAbuseCh         0        enabled  52                0   2024-08-04
URLHausAbuseCh       0        enabled  253               0   2024-08-04
                     =======           ========
Totals -->           3                 3956

I think the DOH servers have a FQDN of doh.opendns.com, f.e.
This FQDN is blocked.
opendns.com is the FQDN of the opendns product. This should be accessible, if you want get information about the service. :wink: