- feature: added "list" action - update: changed "cat << heredocs" to "echo > file" - update: remove path to executables - update: reformatted code and comments (tabs to spaces) - update: reworded some msg_log messages - update: change exit codes from "1" to unique exit code numbers - bug: added check for empty allow/block config file - bug: removed auth_zone_reload (had double reload for allow/block) - bug: change rpz config file to `chown nobody:nobody` - bug: change rpz config file to `chmod 644`
Signed-off-by: Jon Murphy jon.murphy@ipfire.org --- config/rootfiles/packages/rpz | 1 + config/rpz/00-rpz.conf | 22 +-- config/rpz/block.rpz.conf | 7 + config/rpz/rpz-config | 292 ++++++++++++++++++---------------- config/rpz/rpz-metrics | 163 ++++++++++--------- config/rpz/rpz-sleep | 26 +-- lfs/rpz | 20 ++- src/paks/rpz/uninstall.sh | 4 + src/paks/rpz/update.sh | 22 ++- 9 files changed, 297 insertions(+), 260 deletions(-) create mode 100644 config/rpz/block.rpz.conf
diff --git a/config/rootfiles/packages/rpz b/config/rootfiles/packages/rpz index 183825362..73c3efa06 100644 --- a/config/rootfiles/packages/rpz +++ b/config/rootfiles/packages/rpz @@ -1,4 +1,5 @@ etc/unbound/local.d/00-rpz.conf +etc/unbound/local.d/block.rpz.conf etc/unbound/zonefiles etc/unbound/zonefiles/allow.rpz etc/unbound/zonefiles/block.rpz diff --git a/config/rpz/00-rpz.conf b/config/rpz/00-rpz.conf index 72c1d12e5..f005a4f2e 100644 --- a/config/rpz/00-rpz.conf +++ b/config/rpz/00-rpz.conf @@ -1,18 +1,10 @@ server: - module-config: "respip validator iterator" + module-config: "respip validator iterator"
rpz: - name: allow.rpz - zonefile: /etc/unbound/zonefiles/allow.rpz - rpz-action-override: passthru - rpz-log: yes - rpz-log-name: allow - rpz-signal-nxdomain-ra: yes - -rpz: - name: block.rpz - zonefile: /etc/unbound/zonefiles/block.rpz - rpz-action-override: nxdomain - rpz-log: yes - rpz-log-name: block - rpz-signal-nxdomain-ra: yes + name: allow.rpz + zonefile: /etc/unbound/zonefiles/allow.rpz + rpz-action-override: passthru + rpz-log: yes + rpz-log-name: allow + rpz-signal-nxdomain-ra: yes diff --git a/config/rpz/block.rpz.conf b/config/rpz/block.rpz.conf new file mode 100644 index 000000000..605684257 --- /dev/null +++ b/config/rpz/block.rpz.conf @@ -0,0 +1,7 @@ +rpz: + name: block.rpz + zonefile: /etc/unbound/zonefiles/block.rpz + rpz-action-override: nxdomain + rpz-log: yes + rpz-log-name: block + rpz-signal-nxdomain-ra: yes diff --git a/config/rpz/rpz-config b/config/rpz/rpz-config index a24a5c132..9278aa004 100644 --- a/config/rpz/rpz-config +++ b/config/rpz/rpz-config @@ -19,176 +19,186 @@ # # ###############################################################################
-# v23 - 2024-07-30 +version="2024-08-18" # v28
############### Functions ###############
msg_log () { - /usr/bin/logger --tag "${tagName}" "$*" - if tty --silent ; then - echo "${tagName}:" "$*" - fi + logger --tag "${tagName}" "$*" + if tty --silent ; then + echo "${tagName}:" "$*" + fi }
check_name () { - local testName="${1}" - # check for a valid name - regex='^[a-zA-Z0-9_]+$' - if [[ ! "${testName}" =~ $regex ]] ; then - msg_log "error: rpz: the NAME is not valid: "${testName}". exit." - exit 1 - fi + local testName="${1}" + # check for a valid name + regex='^[a-zA-Z0-9_]+$' + if [[ ! "${testName}" =~ $regex ]] || [[ "${testName}" == "allow" ]] || [[ "${testName}" == "block" ]]; then + msg_log "error: rpz: the NAME is not valid: "${testName}". exit." + exit 101 + fi }
check_unbound_conf () { - # check the above config files - msg_log "info: rpz: check for errors with "unbound-checkconf"" - /usr/sbin/unbound-checkconf - exit_code=$? - if [[ "${exit_code}" -ne 0 ]] ; then - msg_log "error: rpz: unbound-checkconf. exit." - exit "${exit_code}" - fi + # check the above config files + msg_log "info: rpz: check for errors with "unbound-checkconf"" + unbound-checkconf + exit_code=$? + if [[ "${exit_code}" -ne 0 ]] ; then + msg_log "error: rpz: unbound-checkconf found invalid configuration." + msg_log "error: rpz: In the Terminal run the command \ + "unbound-checkconf" for more information. exit." + exit 102 + fi }
make_rpz_file () { - local theType="${1}" # allow or block - - theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains - theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ - - theAction='.' - if [[ "${theType}" =~ "allow" ]] ; then - theAction='rpz-passthru.' - fi - - # does a list exist? - if [[ -s "${theList}" ]] ; then - # drop any extra "blanks" and add "CNAME <RPZ action>." to each line - actionList=$( /usr/bin/awk '{$1=$1};1' "${theList}" | - /bin/sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" ) - - msg_log "info: rpz: create zonefile for ${theList}" - - /bin/cat <<-EOF > "${theZoneFile}" - ; Name: ${theType} list - ; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z") - ; - ; domains with actions list - ; - ${actionList} - EOF - - # reload the zone that was just updated - zoneBase=$( basename "${theZoneFile}" ) - /usr/sbin/unbound-control auth_zone_reload -q "${zoneBase}" - fi + local theType="${1}" # allow or block + + theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains + theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ + + # does a list exist? + if ! [[ -s "${theList}" ]] ; then + msg_log "error: rpz: the ${theList} is empty. exit." + exit 103 + fi + + theAction='.' + if [[ "${theType}" =~ "allow" ]] ; then + theAction='rpz-passthru.' + fi + + # drop any extra "blanks" and add "CNAME <RPZ action>." to each line + actionList=$( awk '{$1=$1};1' "${theList}" | + sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" ) + + msg_log "info: rpz: create zonefile for ${theList}" + +echo " +; Name: ${theType} list +; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z") +; +; domains with actions list +; +${actionList} +" > "${theZoneFile}" + }
############### Main ###############
tagName="unbound"
-theAction="${1}" # input action -theName="${2}" # input RPZ name -theURL="${3}" # input RPZ URL - -check_name "${theName}" # is this a valid name? +theAction="${1}" # input action +theName="${2}" # input RPZ name +theURL="${3}" # input RPZ URL
-rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file -rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file +rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file +rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file
case "${theAction}" in
- # add new rpz list - add ) - # does this config already exist? If yes, then exit - if [[ -f "${rpzConfig}" ]] ; then - msg_log "info: rpz: ${rpzConfig} already exists. exit" - exit 1 - fi - - # is this a valid URL? - regex='^https://%5B-%5B:alnum:%5D%5C+&@#/%?=~_%7C!:,.;%5D*%5B-%5B:alnum:%5D%5C+&...]' - if ! [[ "${theURL}" =~ $regex ]] ; then - msg_log "error: rpz: the URL is not valid: "${theURL}". exit." - exit 1 - fi - - # create the zone config file - msg_log "info: rpz: add config file "${theName}.rpz.conf"" - cat <<-EOF > "${rpzConfig}" - rpz: - name: ${theName}.rpz - zonefile: /etc/unbound/zonefiles/${theName}.rpz - url: ${theURL} - rpz-action-override: nxdomain - rpz-log: yes - rpz-log-name: ${theName} - rpz-signal-nxdomain-ra: yes - EOF - - # set-up zone file - /usr/bin/touch "${rpzFile}" - # unbound requires these settings for rpz files - /bin/chown nobody:nobody "${rpzFile}" - /bin/chmod 644 "${rpzFile}" - ;; - - # trash config file & rpz file - remove ) - if ! [[ -f "${rpzConfig}" ]] ; then - msg_log "info: rpz: ${rpzConfig} does not exist. exit" - exit 1 - fi - - msg_log "info: rpz: remove config file & rpz file "${theName}"" - /bin/rm "${rpzConfig}" - /bin/rm "${rpzFile}" - - check_unbound_conf - ;; - - # make a new allow or block rpz file - make ) - case "${theName}" in - allow ) - make_rpz_file allow - ;; - - block ) - make_rpz_file block - ;; - - allowblock ) - make_rpz_file allow - make_rpz_file block - ;; - - * ) - msg_log "error: rpz: the NAME is not valid: "${theName}". exit." - exit 1 - ;; - esac - - check_unbound_conf - ;; - - *) - msg_log "error: rpz: missing or incorrect parameter" - /usr/bin/printf "Usage: rpzConfig.sh <ACTION> <NAME> <URL>\n" - exit 1 - ;; + # add new rpz list + add ) + check_name "${theName}" # is this a valid name? + # does this config already exist? If yes, then exit + if [[ -f "${rpzConfig}" ]] ; then + msg_log "error: rpz: duplicate - ${rpzConfig} already exists. exit" + exit 104 + fi + + # is this a valid URL? + regex='^https://%5B-%5B:alnum:%5D%5C+&@#/%?=~_%7C!:,.;%5D*%5B-%5B:alnum:%5D%5C+&...]' + if ! [[ "${theURL}" =~ $regex ]] ; then + msg_log "error: rpz: the URL is not valid: "${theURL}". exit." + exit 105 + fi + + # create the zone config file + msg_log "info: rpz: add config file "${theName}.rpz.conf"" +echo "rpz: + name: ${theName}.rpz + zonefile: ${rpzFile} + url: ${theURL} + rpz-action-override: nxdomain + rpz-log: yes + rpz-log-name: ${theName} + rpz-signal-nxdomain-ra: yes +" > "${rpzConfig}" + + # set-up zonefile + # create an empty rpz file + touch "${rpzFile}" + # unbound requires these settings for rpz files + chown nobody:nobody "${rpzFile}" "${rpzConfig}" + chmod 644 "${rpzFile}" "${rpzConfig}" + ;; + + # trash config file & rpz file + remove ) + check_name "${theName}" # is this a valid name? + if ! [[ -f "${rpzConfig}" ]] ; then + msg_log "error: rpz: cannot remove ${rpzConfig}, does not exist. exit" + exit 106 + fi + + msg_log "info: rpz: remove config file & rpz file "${theName}"" + rm "${rpzConfig}" + rm "${rpzFile}" + + check_unbound_conf + ;; + + # make a new allow or block rpz file + make ) + case "${theName}" in + allow ) + make_rpz_file allow + ;; + + block ) + make_rpz_file block + ;; + + allowblock ) + make_rpz_file allow + make_rpz_file block + ;; + + * ) + msg_log \ + "error: rpz: the NAME "${theName}" is not valid - "allow" or "block" only. exit." + exit 107 + ;; + esac + + check_unbound_conf + ;; + + list) + awk -F' ' '/^name:|\sname:/{ gsub(/.rpz/, "" ) ; printf $2} /\surl:|^url:/{print "="$2}' \ + /etc/unbound/local.d/*.rpz.conf + exit + ;; + + *) + msg_log "error: rpz: missing or incorrect parameter" + printf "Usage: rpzConfig <ACTION> <NAME> <URL>\n" + printf "Version: ${version}\n" + exit 108 + ;;
esac
-# reload due to the changes +# reload due to the changes msg_log "rpz: running "unbound-control reload"" -/usr/sbin/unbound-control reload +unbound-control reload exit_code=$? if [[ "${exit_code}" -ne 0 ]] ; then - msg_log "error: rpz: unbound-control "${theName}". exit." - exit "${exit_code}" + msg_log "error: rpz: unbound-control "${theName}". exit." + exit 109 fi
exit diff --git a/config/rpz/rpz-metrics b/config/rpz/rpz-metrics index 4d932726e..d154f70b9 100644 --- a/config/rpz/rpz-metrics +++ b/config/rpz/rpz-metrics @@ -19,62 +19,61 @@ # # ###############################################################################
-# v19 on 2024-07-30 +version="2024-08-16" # v20
############### Main ###############
-weeks="${1:-2}" # default to two message logs -sortBy="${2:-name}" # by name or by hits +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 message logs for N weeks +messageLogs=$( find /var/log/messages* -type f | sort --version-sort | + head -"${weeks}" )
-# get the list of RPZ names & counts from the message log(s) +# 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 ) + zgrep --text --extended-regexp 'info: rpz: applied.* A IN$' "${logf}" | + awk '$10 ~ /[\w*]/ { print $10 }' ; + done | sort | uniq --count )
-# flip results and remove brackets `[` and `]` -rpzNameCount=$( /bin/echo "${rpzNameCount}" | - /usr/bin/awk '{ print $2, $1 }' | - /bin/sed --regexp-extended 's|^[(.*)]|\1|' ) +# flip results and remove brackets `[` and `]` +rpzNameCount=$( echo "${rpzNameCount}" | + awk '{ print $2, $1 }' | + sed --regexp-extended 's|^[(.*)]|\1|' )
-# grab only names -rpzNames=$( /bin/echo "${rpzNameCount}" | /usr/bin/awk '{ print $1 }' ) +# grab only names +rpzNames=$( echo "${rpzNameCount}" | awk '{ print $1 }' )
-# get list of RPZ files -rpzFileList=$( /bin/find /etc/unbound/zonefiles -type f -iname "*.rpz" ) +# get list of RPZ files +rpzFileList=$( 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 ;' ) +# get basename of those files +rpzBaseNames=$( echo "${rpzFileList}" | + sed 's|/etc/unbound/zonefiles/||g ; s|.rpz||g ;' )
-# add to rpzNames +# add to rpzNames rpzNames="${rpzNames}"$'\n'"${rpzBaseNames}"
-# drop duplicate names -rpzNames=$( echo "${rpzNames}" | /usr/bin/sort --unique ) +# drop duplicate names +rpzNames=$( echo "${rpzNames}" | sort --unique )
-# get line count for each RPZ -lineCount=$( /bin/echo "${rpzFileList}" | /usr/bin/xargs wc -l ) +# get line count for each RPZ +lineCount=$( echo "${rpzFileList}" | 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 comment line count and blank line count for each RPZ +commentCount=$( echo "${rpzFileList}" | + xargs grep --count -e "^$" -e "^;" )
-# get modified date each RPZ -modDateList=$( /bin/echo "${rpzFileList}" | xargs stat -c '%.10y %n' ) +# get modified date each RPZ +modDateList=$( echo "${rpzFileList}" | xargs stat -c '%.10y %n' )
-ucListAuthZones=$( /usr/sbin/unbound-control list_auth_zones ) +ucListAuthZones=$( unbound-control list_auth_zones )
-# get width of RPZ names -pWidth=$( /bin/echo "${rpzNames}" | /usr/bin/awk '{ print $1" " }' | wc -L ) +# get width of RPZ names +pWidth=$( echo "${rpzNames}" | awk '{ print $1" " }' | wc -L ) pFormat="%-${pWidth}s %-8s %-8s %-8s %10s %12s\n"
-# print title line +# print title line printf "${pFormat}" "name" "hits" "active" "lines" "hits/line%" "last update" printf -- "--------------"
@@ -83,60 +82,60 @@ 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' + printf -- "-" # pretend progress bar + # get hit count + theHits="0" + if output=$( grep "^${theName}\s" <<< "${rpzNameCount}" ) ; then + theHits=$( echo "${output}" | + awk '{ print $2 }' ) + totalHits=$(( totalHits + theHits )) + fi + + # is this RPZ list active? + theActive="disabled" + if grep --quiet "^${theName}.rpz" <<< "${ucListAuthZones}" + then + theActive="enabled" + fi + + # get line count + theLines="n/a" + hitsPerLine="0" + if output=$( grep --fixed-strings "/${theName}.rpz" <<< "${lineCount}" ) ; then + theLines=$( echo "${output}" | 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=$( grep --fixed-strings "/${theName}.rpz" <<< "${modDateList}" ) ; then + theModDate=$( echo "${output}" | 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" + 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" + 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" + 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 }' +# remove blank lines, sort, print as columns +echo "${theResults}" | + awk '!/^[[:space:]]*$/' | + sort "${sortArg[@]}" | + 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}" "" "" diff --git a/config/rpz/rpz-sleep b/config/rpz/rpz-sleep index eeef1174a..dd3603599 100644 --- a/config/rpz/rpz-sleep +++ b/config/rpz/rpz-sleep @@ -19,38 +19,38 @@ # # ###############################################################################
-# v04 on 2024-07-05 +version="2024-08-16" # v05
############### Functions ###############
-# send message to message log +# send message to message log msg_log () { - /usr/bin/logger --tag "${tagName}" "$*" - if /usr/bin/tty --silent ; then - echo "${tagName}:" "$*" - fi + logger --tag "${tagName}" "$*" + if tty --silent ; then + echo "${tagName}:" "$*" + fi }
############### Main ###############
tagName="unbound"
-sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes) +sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes)
-zoneList=$( /usr/sbin/unbound-control list_auth_zones | /usr/bin/awk '{print $1}' ) +zoneList=$( unbound-control list_auth_zones | awk '{print $1}' )
for zone in ${zoneList} ; do - /usr/bin/printf "disable ${zone}\t" - /usr/sbin/unbound-control rpz_disable "${zone}" + printf "disable ${zone}\t" + unbound-control rpz_disable "${zone}" done
msg_log "info: rpz: disabled all zones for ${sleepTime}"
-/bin/sleep "${sleepTime}" +sleep "${sleepTime}"
for zone in ${zoneList} ; do - /usr/bin/printf "enable ${zone}\t" - /usr/sbin/unbound-control rpz_enable "${zone}" + printf "enable ${zone}\t" + unbound-control rpz_enable "${zone}" done
msg_log "info: rpz: enabled all zones" diff --git a/lfs/rpz b/lfs/rpz index 73f6f2b1b..16d1d0803 100644 --- a/lfs/rpz +++ b/lfs/rpz @@ -62,25 +62,31 @@ $(TARGET) : @$(PREBUILD) @rm -rf $(DIR_APP)
- # install RPZ scripts + # install RPZ scripts install -v -m 755 \ $(DIR_CONF)/rpz/{rpz-config,rpz-metrics,rpz-sleep} -t /usr/sbin
+ # Add conf file to /etc directory + cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d + cp -vf $(DIR_CONF)/rpz/block.rpz.conf /etc/unbound/local.d + # Install settings folder and two empty files mkdir -pv /var/ipfire/dns/rpz touch /var/ipfire/dns/rpz/allowlist touch /var/ipfire/dns/rpz/blocklist
- # Add conf file to /etc directory - cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d - - # create zonefiles directory for the RPZ files and add two empty RPZ - # files to avoid a unbound config error + # create zonefiles directory for the RPZ files and add two empty RPZ + # files to avoid a unbound config error mkdir -pv /etc/unbound/zonefiles - chown -v nobody:nobody /etc/unbound/zonefiles touch /etc/unbound/zonefiles/allow.rpz touch /etc/unbound/zonefiles/block.rpz
+ # set owner for unbound related files + chown -vR nobody:nobody \ + /var/ipfire/dns/rpz \ + /etc/unbound/zonefiles \ + /etc/unbound/local.d + # Install backup definition cp -vf $(DIR_CONF)/backup/includes/rpz /var/ipfire/backup/addons/includes/rpz
diff --git a/src/paks/rpz/uninstall.sh b/src/paks/rpz/uninstall.sh index 4fb20e127..51edaa176 100644 --- a/src/paks/rpz/uninstall.sh +++ b/src/paks/rpz/uninstall.sh @@ -27,5 +27,9 @@ make_backup ${NAME} remove_files
+# delete rpz config files. Otherwise unbound will throw error: +# "[1723428668] unbound-control[17117:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm -fv /etc/unbound/local.d/*.rpz.conf + # start unbound to load unbound config file /etc/init.d/unbound start diff --git a/src/paks/rpz/update.sh b/src/paks/rpz/update.sh index 938a93a40..fd46a185a 100644 --- a/src/paks/rpz/update.sh +++ b/src/paks/rpz/update.sh @@ -20,6 +20,24 @@ ############################################################################### # . /opt/pakfire/lib/functions.sh + +# from update.sh extract_backup_includes -./uninstall.sh -./install.sh + +# stop unbound to delete RPZ conf file +/etc/init.d/unbound stop + +# from uninstall.sh +make_backup ${NAME} +remove_files + +# delete rpz config files. Otherwise unbound will throw error: +# "unbound-control[nn:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm --verbose --force /etc/unbound/local.d/*.rpz.conf + +# from install.sh +extract_files +restore_backup ${NAME} + +# restart unbound to load config files +/etc/init.d/unbound start
Gentle reminder…
On Aug 23, 2024, at 4:39 PM, Jon Murphy jon.murphy@ipfire.org wrote:
- feature: added "list" action
- update: changed "cat << heredocs" to "echo > file"
- update: remove path to executables
- update: reformatted code and comments (tabs to spaces)
- update: reworded some msg_log messages
- update: change exit codes from "1" to unique exit code numbers
- bug: added check for empty allow/block config file
- bug: removed auth_zone_reload (had double reload for allow/block)
- bug: change rpz config file to `chown nobody:nobody`
- bug: change rpz config file to `chmod 644`
Signed-off-by: Jon Murphy jon.murphy@ipfire.org
config/rootfiles/packages/rpz | 1 + config/rpz/00-rpz.conf | 22 +-- config/rpz/block.rpz.conf | 7 + config/rpz/rpz-config | 292 ++++++++++++++++++---------------- config/rpz/rpz-metrics | 163 ++++++++++--------- config/rpz/rpz-sleep | 26 +-- lfs/rpz | 20 ++- src/paks/rpz/uninstall.sh | 4 + src/paks/rpz/update.sh | 22 ++- 9 files changed, 297 insertions(+), 260 deletions(-) create mode 100644 config/rpz/block.rpz.conf
diff --git a/config/rootfiles/packages/rpz b/config/rootfiles/packages/rpz index 183825362..73c3efa06 100644 --- a/config/rootfiles/packages/rpz +++ b/config/rootfiles/packages/rpz @@ -1,4 +1,5 @@ etc/unbound/local.d/00-rpz.conf +etc/unbound/local.d/block.rpz.conf etc/unbound/zonefiles etc/unbound/zonefiles/allow.rpz etc/unbound/zonefiles/block.rpz diff --git a/config/rpz/00-rpz.conf b/config/rpz/00-rpz.conf index 72c1d12e5..f005a4f2e 100644 --- a/config/rpz/00-rpz.conf +++ b/config/rpz/00-rpz.conf @@ -1,18 +1,10 @@ server:
- module-config: "respip validator iterator"
- module-config: "respip validator iterator"
rpz:
- name: allow.rpz
- zonefile: /etc/unbound/zonefiles/allow.rpz
- rpz-action-override: passthru
- rpz-log: yes
- rpz-log-name: allow
- rpz-signal-nxdomain-ra: yes
-rpz:
- name: block.rpz
- zonefile: /etc/unbound/zonefiles/block.rpz
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: block
- rpz-signal-nxdomain-ra: yes
- name: allow.rpz
- zonefile: /etc/unbound/zonefiles/allow.rpz
- rpz-action-override: passthru
- rpz-log: yes
- rpz-log-name: allow
- rpz-signal-nxdomain-ra: yes
diff --git a/config/rpz/block.rpz.conf b/config/rpz/block.rpz.conf new file mode 100644 index 000000000..605684257 --- /dev/null +++ b/config/rpz/block.rpz.conf @@ -0,0 +1,7 @@ +rpz:
- name: block.rpz
- zonefile: /etc/unbound/zonefiles/block.rpz
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: block
- rpz-signal-nxdomain-ra: yes
diff --git a/config/rpz/rpz-config b/config/rpz/rpz-config index a24a5c132..9278aa004 100644 --- a/config/rpz/rpz-config +++ b/config/rpz/rpz-config @@ -19,176 +19,186 @@ # # ###############################################################################
-# v23 - 2024-07-30 +version="2024-08-18" # v28
############### Functions ###############
msg_log () {
- /usr/bin/logger --tag "${tagName}" "$*"
- if tty --silent ; then
echo "${tagName}:" "$*"
- fi
- logger --tag "${tagName}" "$*"
- if tty --silent ; then
echo "${tagName}:" "$*"
- fi
}
check_name () {
- local testName="${1}"
- # check for a valid name
- regex='^[a-zA-Z0-9_]+$'
- if [[ ! "${testName}" =~ $regex ]] ; then
msg_log "error: rpz: the NAME is not valid: \"${testName}\". exit."
exit 1
- fi
- local testName="${1}"
- # check for a valid name
- regex='^[a-zA-Z0-9_]+$'
- if [[ ! "${testName}" =~ $regex ]] || [[ "${testName}" == "allow" ]] || [[ "${testName}" == "block" ]]; then
msg_log "error: rpz: the NAME is not valid: \"${testName}\". exit."
exit 101
- fi
}
check_unbound_conf () {
- # check the above config files
- msg_log "info: rpz: check for errors with "unbound-checkconf""
- /usr/sbin/unbound-checkconf
- exit_code=$?
- if [[ "${exit_code}" -ne 0 ]] ; then
msg_log "error: rpz: unbound-checkconf. exit."
exit "${exit_code}"
- fi
- # check the above config files
- msg_log "info: rpz: check for errors with "unbound-checkconf""
- unbound-checkconf
- exit_code=$?
- if [[ "${exit_code}" -ne 0 ]] ; then
msg_log "error: rpz: unbound-checkconf found invalid configuration."
msg_log "error: rpz: In the Terminal run the command \
\"unbound-checkconf\" for more information. exit."
exit 102
- fi
}
make_rpz_file () {
- local theType="${1}" # allow or block
- theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains
- theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ
- theAction='.'
- if [[ "${theType}" =~ "allow" ]] ; then
theAction='rpz-passthru.'
- fi
- # does a list exist?
- if [[ -s "${theList}" ]] ; then
# drop any extra "blanks" and add "CNAME <RPZ action>." to each line
actionList=$( /usr/bin/awk '{$1=$1};1' "${theList}" |
/bin/sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" )
msg_log "info: rpz: create zonefile for ${theList}"
/bin/cat <<-EOF > "${theZoneFile}"
; Name: ${theType} list
; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z")
;
; domains with actions list
;
${actionList}
EOF
# reload the zone that was just updated
zoneBase=$( basename "${theZoneFile}" )
/usr/sbin/unbound-control auth_zone_reload -q "${zoneBase}"
- fi
- local theType="${1}" # allow or block
- theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains
- theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ
- # does a list exist?
- if ! [[ -s "${theList}" ]] ; then
msg_log "error: rpz: the ${theList} is empty. exit."
exit 103
- fi
- theAction='.'
- if [[ "${theType}" =~ "allow" ]] ; then
theAction='rpz-passthru.'
- fi
- # drop any extra "blanks" and add "CNAME <RPZ action>." to each line
- actionList=$( awk '{$1=$1};1' "${theList}" |
sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" )
- msg_log "info: rpz: create zonefile for ${theList}"
+echo " +; Name: ${theType} list +; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z") +; +; domains with actions list +; +${actionList} +" > "${theZoneFile}"
}
############### Main ###############
tagName="unbound"
-theAction="${1}" # input action -theName="${2}" # input RPZ name -theURL="${3}" # input RPZ URL
-check_name "${theName}" # is this a valid name? +theAction="${1}" # input action +theName="${2}" # input RPZ name +theURL="${3}" # input RPZ URL
-rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file -rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file +rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file +rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file
case "${theAction}" in
- # add new rpz list
- add )
# does this config already exist? If yes, then exit
if [[ -f "${rpzConfig}" ]] ; then
msg_log "info: rpz: ${rpzConfig} already exists. exit"
exit 1
fi
# is this a valid URL?
regex='^https://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
if ! [[ "${theURL}" =~ $regex ]] ; then
msg_log "error: rpz: the URL is not valid: \"${theURL}\". exit."
exit 1
fi
# create the zone config file
msg_log "info: rpz: add config file \"${theName}.rpz.conf\""
cat <<-EOF > "${rpzConfig}"
rpz:
name: ${theName}.rpz
zonefile: /etc/unbound/zonefiles/${theName}.rpz
url: ${theURL}
rpz-action-override: nxdomain
rpz-log: yes
rpz-log-name: ${theName}
rpz-signal-nxdomain-ra: yes
EOF
# set-up zone file
/usr/bin/touch "${rpzFile}"
# unbound requires these settings for rpz files
/bin/chown nobody:nobody "${rpzFile}"
/bin/chmod 644 "${rpzFile}"
;;
- # trash config file & rpz file
- remove )
if ! [[ -f "${rpzConfig}" ]] ; then
msg_log "info: rpz: ${rpzConfig} does not exist. exit"
exit 1
fi
msg_log "info: rpz: remove config file & rpz file \"${theName}\""
/bin/rm "${rpzConfig}"
/bin/rm "${rpzFile}"
check_unbound_conf
;;
- # make a new allow or block rpz file
- make )
case "${theName}" in
allow )
make_rpz_file allow
;;
block )
make_rpz_file block
;;
allowblock )
make_rpz_file allow
make_rpz_file block
;;
* )
msg_log "error: rpz: the NAME is not valid: \"${theName}\". exit."
exit 1
;;
esac
check_unbound_conf
;;
- *)
msg_log "error: rpz: missing or incorrect parameter"
/usr/bin/printf "Usage: rpzConfig.sh <ACTION> <NAME> <URL>\n"
exit 1
;;
- # add new rpz list
- add )
- check_name "${theName}" # is this a valid name?
# does this config already exist? If yes, then exit
if [[ -f "${rpzConfig}" ]] ; then
msg_log "error: rpz: duplicate - ${rpzConfig} already exists. exit"
exit 104
fi
# is this a valid URL?
regex='^https://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
if ! [[ "${theURL}" =~ $regex ]] ; then
msg_log "error: rpz: the URL is not valid: \"${theURL}\". exit."
exit 105
fi
# create the zone config file
msg_log "info: rpz: add config file \"${theName}.rpz.conf\""
+echo "rpz:
- name: ${theName}.rpz
- zonefile: ${rpzFile}
- url: ${theURL}
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: ${theName}
- rpz-signal-nxdomain-ra: yes
+" > "${rpzConfig}"
# set-up zonefile
# create an empty rpz file
touch "${rpzFile}"
# unbound requires these settings for rpz files
chown nobody:nobody "${rpzFile}" "${rpzConfig}"
chmod 644 "${rpzFile}" "${rpzConfig}"
;;
- # trash config file & rpz file
- remove )
- check_name "${theName}" # is this a valid name?
if ! [[ -f "${rpzConfig}" ]] ; then
msg_log "error: rpz: cannot remove ${rpzConfig}, does not exist. exit"
exit 106
fi
msg_log "info: rpz: remove config file & rpz file \"${theName}\""
rm "${rpzConfig}"
rm "${rpzFile}"
check_unbound_conf
;;
- # make a new allow or block rpz file
- make )
case "${theName}" in
allow )
make_rpz_file allow
;;
block )
make_rpz_file block
;;
allowblock )
make_rpz_file allow
make_rpz_file block
;;
* )
msg_log \
"error: rpz: the NAME \"${theName}\" is not valid - \"allow\" or \"block\" only. exit."
exit 107
;;
esac
check_unbound_conf
;;
- list)
awk -F' ' '/^name:|\sname:/{ gsub(/.rpz/, "" ) ; printf $2} /\surl:|^url:/{print "="$2}' \
/etc/unbound/local.d/*.rpz.conf
exit
;;
- *)
msg_log "error: rpz: missing or incorrect parameter"
printf "Usage: rpzConfig <ACTION> <NAME> <URL>\n"
printf "Version: ${version}\n"
exit 108
;;
esac
-# reload due to the changes +# reload due to the changes msg_log "rpz: running "unbound-control reload"" -/usr/sbin/unbound-control reload +unbound-control reload exit_code=$? if [[ "${exit_code}" -ne 0 ]] ; then
- msg_log "error: rpz: unbound-control "${theName}". exit."
- exit "${exit_code}"
- msg_log "error: rpz: unbound-control "${theName}". exit."
- exit 109
fi
exit diff --git a/config/rpz/rpz-metrics b/config/rpz/rpz-metrics index 4d932726e..d154f70b9 100644 --- a/config/rpz/rpz-metrics +++ b/config/rpz/rpz-metrics @@ -19,62 +19,61 @@ # # ###############################################################################
-# v19 on 2024-07-30 +version="2024-08-16" # v20
############### Main ###############
-weeks="${1:-2}" # default to two message logs -sortBy="${2:-name}" # by name or by hits +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 message logs for N weeks +messageLogs=$( find /var/log/messages* -type f | sort --version-sort |
- head -"${weeks}" )
-# get the list of RPZ names & counts from the message log(s) +# 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 )
- zgrep --text --extended-regexp 'info: rpz: applied.* A IN$' "${logf}" |
awk '$10 ~ /\[\w*]/ { print $10 }' ;
- done | sort | uniq --count )
-# flip results and remove brackets `[` and `]` -rpzNameCount=$( /bin/echo "${rpzNameCount}" |
- /usr/bin/awk '{ print $2, $1 }' |
- /bin/sed --regexp-extended 's|^[(.*)]|\1|' )
+# flip results and remove brackets `[` and `]` +rpzNameCount=$( echo "${rpzNameCount}" |
- awk '{ print $2, $1 }' |
sed --regexp-extended 's|^\[(.*)\]|\1|' )
-# grab only names -rpzNames=$( /bin/echo "${rpzNameCount}" | /usr/bin/awk '{ print $1 }' ) +# grab only names +rpzNames=$( echo "${rpzNameCount}" | awk '{ print $1 }' )
-# get list of RPZ files -rpzFileList=$( /bin/find /etc/unbound/zonefiles -type f -iname "*.rpz" ) +# get list of RPZ files +rpzFileList=$( 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 ;' )
+# get basename of those files +rpzBaseNames=$( echo "${rpzFileList}" |
- sed 's|/etc/unbound/zonefiles/||g ; s|.rpz||g ;' )
-# add to rpzNames +# add to rpzNames rpzNames="${rpzNames}"$'\n'"${rpzBaseNames}"
-# drop duplicate names -rpzNames=$( echo "${rpzNames}" | /usr/bin/sort --unique ) +# drop duplicate names +rpzNames=$( echo "${rpzNames}" | sort --unique )
-# get line count for each RPZ -lineCount=$( /bin/echo "${rpzFileList}" | /usr/bin/xargs wc -l ) +# get line count for each RPZ +lineCount=$( echo "${rpzFileList}" | 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 comment line count and blank line count for each RPZ +commentCount=$( echo "${rpzFileList}" |
- xargs grep --count -e "^$" -e "^;" )
-# get modified date each RPZ -modDateList=$( /bin/echo "${rpzFileList}" | xargs stat -c '%.10y %n' ) +# get modified date each RPZ +modDateList=$( echo "${rpzFileList}" | xargs stat -c '%.10y %n' )
-ucListAuthZones=$( /usr/sbin/unbound-control list_auth_zones ) +ucListAuthZones=$( unbound-control list_auth_zones )
-# get width of RPZ names -pWidth=$( /bin/echo "${rpzNames}" | /usr/bin/awk '{ print $1" " }' | wc -L ) +# get width of RPZ names +pWidth=$( echo "${rpzNames}" | awk '{ print $1" " }' | wc -L ) pFormat="%-${pWidth}s %-8s %-8s %-8s %10s %12s\n"
-# print title line +# print title line printf "${pFormat}" "name" "hits" "active" "lines" "hits/line%" "last update" printf -- "--------------"
@@ -83,60 +82,60 @@ 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'
- printf -- "-" # pretend progress bar
- # get hit count
- theHits="0"
- if output=$( grep "^${theName}\s" <<< "${rpzNameCount}" ) ; then
theHits=$( echo "${output}" |
awk '{ print $2 }' )
totalHits=$(( totalHits + theHits ))
- fi
- # is this RPZ list active?
- theActive="disabled"
- if grep --quiet "^${theName}.rpz" <<< "${ucListAuthZones}"
- then
theActive="enabled"
- fi
- # get line count
- theLines="n/a"
- hitsPerLine="0"
- if output=$( grep --fixed-strings "/${theName}.rpz" <<< "${lineCount}" ) ; then
theLines=$( echo "${output}" | 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=$( grep --fixed-strings "/${theName}.rpz" <<< "${modDateList}" ) ; then
theModDate=$( echo "${output}" | 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"
- 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"
- 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"
- 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 }'
+# remove blank lines, sort, print as columns +echo "${theResults}" |
- awk '!/^[[:space:]]*$/' |
- sort "${sortArg[@]}" |
- 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}" "" "" diff --git a/config/rpz/rpz-sleep b/config/rpz/rpz-sleep index eeef1174a..dd3603599 100644 --- a/config/rpz/rpz-sleep +++ b/config/rpz/rpz-sleep @@ -19,38 +19,38 @@ # # ###############################################################################
-# v04 on 2024-07-05 +version="2024-08-16" # v05
############### Functions ###############
-# send message to message log +# send message to message log msg_log () {
- /usr/bin/logger --tag "${tagName}" "$*"
- if /usr/bin/tty --silent ; then
echo "${tagName}:" "$*"
- fi
- logger --tag "${tagName}" "$*"
- if tty --silent ; then
echo "${tagName}:" "$*"
- fi
}
############### Main ###############
tagName="unbound"
-sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes) +sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes)
-zoneList=$( /usr/sbin/unbound-control list_auth_zones | /usr/bin/awk '{print $1}' ) +zoneList=$( unbound-control list_auth_zones | awk '{print $1}' )
for zone in ${zoneList} ; do
- /usr/bin/printf "disable ${zone}\t"
- /usr/sbin/unbound-control rpz_disable "${zone}"
- printf "disable ${zone}\t"
- unbound-control rpz_disable "${zone}"
done
msg_log "info: rpz: disabled all zones for ${sleepTime}"
-/bin/sleep "${sleepTime}" +sleep "${sleepTime}"
for zone in ${zoneList} ; do
- /usr/bin/printf "enable ${zone}\t"
- /usr/sbin/unbound-control rpz_enable "${zone}"
- printf "enable ${zone}\t"
- unbound-control rpz_enable "${zone}"
done
msg_log "info: rpz: enabled all zones" diff --git a/lfs/rpz b/lfs/rpz index 73f6f2b1b..16d1d0803 100644 --- a/lfs/rpz +++ b/lfs/rpz @@ -62,25 +62,31 @@ $(TARGET) : @$(PREBUILD) @rm -rf $(DIR_APP)
- # install RPZ scripts
# install RPZ scripts install -v -m 755 \ $(DIR_CONF)/rpz/{rpz-config,rpz-metrics,rpz-sleep} -t /usr/sbin
# Add conf file to /etc directory
cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d
cp -vf $(DIR_CONF)/rpz/block.rpz.conf /etc/unbound/local.d
# Install settings folder and two empty files mkdir -pv /var/ipfire/dns/rpz touch /var/ipfire/dns/rpz/allowlist touch /var/ipfire/dns/rpz/blocklist
- # Add conf file to /etc directory
- cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d
- # create zonefiles directory for the RPZ files and add two empty RPZ
- # files to avoid a unbound config error
- # create zonefiles directory for the RPZ files and add two empty RPZ
- # files to avoid a unbound config error mkdir -pv /etc/unbound/zonefiles
- chown -v nobody:nobody /etc/unbound/zonefiles touch /etc/unbound/zonefiles/allow.rpz touch /etc/unbound/zonefiles/block.rpz
- # set owner for unbound related files
- chown -vR nobody:nobody \
/var/ipfire/dns/rpz \
/etc/unbound/zonefiles \
/etc/unbound/local.d
- # Install backup definition cp -vf $(DIR_CONF)/backup/includes/rpz /var/ipfire/backup/addons/includes/rpz
diff --git a/src/paks/rpz/uninstall.sh b/src/paks/rpz/uninstall.sh index 4fb20e127..51edaa176 100644 --- a/src/paks/rpz/uninstall.sh +++ b/src/paks/rpz/uninstall.sh @@ -27,5 +27,9 @@ make_backup ${NAME} remove_files
+# delete rpz config files. Otherwise unbound will throw error: +# "[1723428668] unbound-control[17117:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm -fv /etc/unbound/local.d/*.rpz.conf
# start unbound to load unbound config file /etc/init.d/unbound start diff --git a/src/paks/rpz/update.sh b/src/paks/rpz/update.sh index 938a93a40..fd46a185a 100644 --- a/src/paks/rpz/update.sh +++ b/src/paks/rpz/update.sh @@ -20,6 +20,24 @@ ############################################################################### # . /opt/pakfire/lib/functions.sh
+# from update.sh extract_backup_includes -./uninstall.sh -./install.sh
+# stop unbound to delete RPZ conf file +/etc/init.d/unbound stop
+# from uninstall.sh +make_backup ${NAME} +remove_files
+# delete rpz config files. Otherwise unbound will throw error: +# "unbound-control[nn:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm --verbose --force /etc/unbound/local.d/*.rpz.conf
+# from install.sh +extract_files +restore_backup ${NAME}
+# restart unbound to load config files
+/etc/init.d/unbound start
2.30.2
Jon
What are you reminding us about?
On 28 Sep 2024, at 20:34, jon jon.murphy@ipfire.org wrote:
Gentle reminder…
On Aug 23, 2024, at 4:39 PM, Jon Murphy jon.murphy@ipfire.org wrote:
- feature: added "list" action
- update: changed "cat << heredocs" to "echo > file"
- update: remove path to executables
- update: reformatted code and comments (tabs to spaces)
- update: reworded some msg_log messages
- update: change exit codes from "1" to unique exit code numbers
- bug: added check for empty allow/block config file
- bug: removed auth_zone_reload (had double reload for allow/block)
- bug: change rpz config file to `chown nobody:nobody`
- bug: change rpz config file to `chmod 644`
Signed-off-by: Jon Murphy jon.murphy@ipfire.org
config/rootfiles/packages/rpz | 1 + config/rpz/00-rpz.conf | 22 +-- config/rpz/block.rpz.conf | 7 + config/rpz/rpz-config | 292 ++++++++++++++++++---------------- config/rpz/rpz-metrics | 163 ++++++++++--------- config/rpz/rpz-sleep | 26 +-- lfs/rpz | 20 ++- src/paks/rpz/uninstall.sh | 4 + src/paks/rpz/update.sh | 22 ++- 9 files changed, 297 insertions(+), 260 deletions(-) create mode 100644 config/rpz/block.rpz.conf
diff --git a/config/rootfiles/packages/rpz b/config/rootfiles/packages/rpz index 183825362..73c3efa06 100644 --- a/config/rootfiles/packages/rpz +++ b/config/rootfiles/packages/rpz @@ -1,4 +1,5 @@ etc/unbound/local.d/00-rpz.conf +etc/unbound/local.d/block.rpz.conf etc/unbound/zonefiles etc/unbound/zonefiles/allow.rpz etc/unbound/zonefiles/block.rpz diff --git a/config/rpz/00-rpz.conf b/config/rpz/00-rpz.conf index 72c1d12e5..f005a4f2e 100644 --- a/config/rpz/00-rpz.conf +++ b/config/rpz/00-rpz.conf @@ -1,18 +1,10 @@ server:
- module-config: "respip validator iterator"
- module-config: "respip validator iterator"
rpz:
- name: allow.rpz
- zonefile: /etc/unbound/zonefiles/allow.rpz
- rpz-action-override: passthru
- rpz-log: yes
- rpz-log-name: allow
- rpz-signal-nxdomain-ra: yes
-rpz:
- name: block.rpz
- zonefile: /etc/unbound/zonefiles/block.rpz
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: block
- rpz-signal-nxdomain-ra: yes
- name: allow.rpz
- zonefile: /etc/unbound/zonefiles/allow.rpz
- rpz-action-override: passthru
- rpz-log: yes
- rpz-log-name: allow
- rpz-signal-nxdomain-ra: yes
diff --git a/config/rpz/block.rpz.conf b/config/rpz/block.rpz.conf new file mode 100644 index 000000000..605684257 --- /dev/null +++ b/config/rpz/block.rpz.conf @@ -0,0 +1,7 @@ +rpz:
- name: block.rpz
- zonefile: /etc/unbound/zonefiles/block.rpz
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: block
- rpz-signal-nxdomain-ra: yes
diff --git a/config/rpz/rpz-config b/config/rpz/rpz-config index a24a5c132..9278aa004 100644 --- a/config/rpz/rpz-config +++ b/config/rpz/rpz-config @@ -19,176 +19,186 @@ # # ###############################################################################
-# v23 - 2024-07-30 +version="2024-08-18" # v28
############### Functions ###############
msg_log () {
- /usr/bin/logger --tag "${tagName}" "$*"
- if tty --silent ; then
- echo "${tagName}:" "$*"
- fi
- logger --tag "${tagName}" "$*"
- if tty --silent ; then
echo "${tagName}:" "$*"
- fi
}
check_name () {
- local testName="${1}"
- # check for a valid name
- regex='^[a-zA-Z0-9_]+$'
- if [[ ! "${testName}" =~ $regex ]] ; then
- msg_log "error: rpz: the NAME is not valid: "${testName}". exit."
- exit 1
- fi
- local testName="${1}"
- # check for a valid name
- regex='^[a-zA-Z0-9_]+$'
- if [[ ! "${testName}" =~ $regex ]] || [[ "${testName}" == "allow" ]] || [[ "${testName}" == "block" ]]; then
msg_log "error: rpz: the NAME is not valid: \"${testName}\". exit."
exit 101
- fi
}
check_unbound_conf () {
- # check the above config files
- msg_log "info: rpz: check for errors with "unbound-checkconf""
- /usr/sbin/unbound-checkconf
- exit_code=$?
- if [[ "${exit_code}" -ne 0 ]] ; then
- msg_log "error: rpz: unbound-checkconf. exit."
- exit "${exit_code}"
- fi
- # check the above config files
- msg_log "info: rpz: check for errors with "unbound-checkconf""
- unbound-checkconf
- exit_code=$?
- if [[ "${exit_code}" -ne 0 ]] ; then
msg_log "error: rpz: unbound-checkconf found invalid configuration."
msg_log "error: rpz: In the Terminal run the command \
\"unbound-checkconf\" for more information. exit."
exit 102
- fi
}
make_rpz_file () {
- local theType="${1}" # allow or block
- theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains
- theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ
- theAction='.'
- if [[ "${theType}" =~ "allow" ]] ; then
- theAction='rpz-passthru.'
- fi
- # does a list exist?
- if [[ -s "${theList}" ]] ; then
- # drop any extra "blanks" and add "CNAME <RPZ action>." to each line
- actionList=$( /usr/bin/awk '{$1=$1};1' "${theList}" |
- /bin/sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" )
- msg_log "info: rpz: create zonefile for ${theList}"
- /bin/cat <<-EOF > "${theZoneFile}"
- ; Name: ${theType} list
- ; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z")
- ;
- ; domains with actions list
- ;
- ${actionList}
- EOF
- # reload the zone that was just updated
- zoneBase=$( basename "${theZoneFile}" )
- /usr/sbin/unbound-control auth_zone_reload -q "${zoneBase}"
- fi
- local theType="${1}" # allow or block
- theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains
- theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ
- # does a list exist?
- if ! [[ -s "${theList}" ]] ; then
msg_log "error: rpz: the ${theList} is empty. exit."
exit 103
- fi
- theAction='.'
- if [[ "${theType}" =~ "allow" ]] ; then
theAction='rpz-passthru.'
- fi
- # drop any extra "blanks" and add "CNAME <RPZ action>." to each line
- actionList=$( awk '{$1=$1};1' "${theList}" |
sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" )
- msg_log "info: rpz: create zonefile for ${theList}"
+echo " +; Name: ${theType} list +; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z") +; +; domains with actions list +; +${actionList} +" > "${theZoneFile}"
}
############### Main ###############
tagName="unbound"
-theAction="${1}" # input action -theName="${2}" # input RPZ name -theURL="${3}" # input RPZ URL
-check_name "${theName}" # is this a valid name? +theAction="${1}" # input action +theName="${2}" # input RPZ name +theURL="${3}" # input RPZ URL
-rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file -rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file +rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file +rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file
case "${theAction}" in
- # add new rpz list
- add )
- # does this config already exist? If yes, then exit
- if [[ -f "${rpzConfig}" ]] ; then
- msg_log "info: rpz: ${rpzConfig} already exists. exit"
- exit 1
- fi
- # is this a valid URL?
- regex='^https://%5B-%5B:alnum:%5D%5C+&@#/%?=~_%7C!:,.;%5D*%5B-%5B:alnum:%5D%5C+&...]'
- if ! [[ "${theURL}" =~ $regex ]] ; then
- msg_log "error: rpz: the URL is not valid: "${theURL}". exit."
- exit 1
- fi
- # create the zone config file
- msg_log "info: rpz: add config file "${theName}.rpz.conf""
- cat <<-EOF > "${rpzConfig}"
- rpz:
- name: ${theName}.rpz
- zonefile: /etc/unbound/zonefiles/${theName}.rpz
- url: ${theURL}
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: ${theName}
- rpz-signal-nxdomain-ra: yes
- EOF
- # set-up zone file
- /usr/bin/touch "${rpzFile}"
- # unbound requires these settings for rpz files
- /bin/chown nobody:nobody "${rpzFile}"
- /bin/chmod 644 "${rpzFile}"
- ;;
- # trash config file & rpz file
- remove )
- if ! [[ -f "${rpzConfig}" ]] ; then
- msg_log "info: rpz: ${rpzConfig} does not exist. exit"
- exit 1
- fi
- msg_log "info: rpz: remove config file & rpz file "${theName}""
- /bin/rm "${rpzConfig}"
- /bin/rm "${rpzFile}"
- check_unbound_conf
- ;;
- # make a new allow or block rpz file
- make )
- case "${theName}" in
- allow )
- make_rpz_file allow
- ;;
- block )
- make_rpz_file block
- ;;
- allowblock )
- make_rpz_file allow
- make_rpz_file block
- ;;
- )
- msg_log "error: rpz: the NAME is not valid: "${theName}". exit."
- exit 1
- ;;
- esac
- check_unbound_conf
- ;;
- *)
- msg_log "error: rpz: missing or incorrect parameter"
- /usr/bin/printf "Usage: rpzConfig.sh <ACTION> <NAME> <URL>\n"
- exit 1
- ;;
- # add new rpz list
- add )
- check_name "${theName}" # is this a valid name?
# does this config already exist? If yes, then exit
if [[ -f "${rpzConfig}" ]] ; then
msg_log "error: rpz: duplicate - ${rpzConfig} already exists. exit"
exit 104
fi
# is this a valid URL?
regex='^https://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
if ! [[ "${theURL}" =~ $regex ]] ; then
msg_log "error: rpz: the URL is not valid: \"${theURL}\". exit."
exit 105
fi
# create the zone config file
msg_log "info: rpz: add config file \"${theName}.rpz.conf\""
+echo "rpz:
- name: ${theName}.rpz
- zonefile: ${rpzFile}
- url: ${theURL}
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: ${theName}
- rpz-signal-nxdomain-ra: yes
+" > "${rpzConfig}"
# set-up zonefile
# create an empty rpz file
touch "${rpzFile}"
# unbound requires these settings for rpz files
chown nobody:nobody "${rpzFile}" "${rpzConfig}"
chmod 644 "${rpzFile}" "${rpzConfig}"
;;
- # trash config file & rpz file
- remove )
- check_name "${theName}" # is this a valid name?
if ! [[ -f "${rpzConfig}" ]] ; then
msg_log "error: rpz: cannot remove ${rpzConfig}, does not exist. exit"
exit 106
fi
msg_log "info: rpz: remove config file & rpz file \"${theName}\""
rm "${rpzConfig}"
rm "${rpzFile}"
check_unbound_conf
;;
- # make a new allow or block rpz file
- make )
case "${theName}" in
allow )
make_rpz_file allow
;;
block )
make_rpz_file block
;;
allowblock )
make_rpz_file allow
make_rpz_file block
;;
* )
msg_log \
"error: rpz: the NAME \"${theName}\" is not valid - \"allow\" or \"block\" only. exit."
exit 107
;;
esac
check_unbound_conf
;;
- list)
awk -F' ' '/^name:|\sname:/{ gsub(/.rpz/, "" ) ; printf $2} /\surl:|^url:/{print "="$2}' \
/etc/unbound/local.d/*.rpz.conf
exit
;;
- *)
msg_log "error: rpz: missing or incorrect parameter"
printf "Usage: rpzConfig <ACTION> <NAME> <URL>\n"
printf "Version: ${version}\n"
exit 108
;;
esac
-# reload due to the changes +# reload due to the changes msg_log "rpz: running "unbound-control reload"" -/usr/sbin/unbound-control reload +unbound-control reload exit_code=$? if [[ "${exit_code}" -ne 0 ]] ; then
- msg_log "error: rpz: unbound-control "${theName}". exit."
- exit "${exit_code}"
- msg_log "error: rpz: unbound-control "${theName}". exit."
- exit 109
fi
exit diff --git a/config/rpz/rpz-metrics b/config/rpz/rpz-metrics index 4d932726e..d154f70b9 100644 --- a/config/rpz/rpz-metrics +++ b/config/rpz/rpz-metrics @@ -19,62 +19,61 @@ # # ###############################################################################
-# v19 on 2024-07-30 +version="2024-08-16" # v20
############### Main ###############
-weeks="${1:-2}" # default to two message logs -sortBy="${2:-name}" # by name or by hits +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 message logs for N weeks +messageLogs=$( find /var/log/messages* -type f | sort --version-sort |
- head -"${weeks}" )
-# get the list of RPZ names & counts from the message log(s) +# 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 )
- zgrep --text --extended-regexp 'info: rpz: applied.* A IN$' "${logf}" |
awk '$10 ~ /\[\w*]/ { print $10 }' ;
- done | sort | uniq --count )
-# flip results and remove brackets `[` and `]` -rpzNameCount=$( /bin/echo "${rpzNameCount}" |
- /usr/bin/awk '{ print $2, $1 }' |
- /bin/sed --regexp-extended 's|^[(.*)]|\1|' )
+# flip results and remove brackets `[` and `]` +rpzNameCount=$( echo "${rpzNameCount}" |
- awk '{ print $2, $1 }' |
sed --regexp-extended 's|^\[(.*)\]|\1|' )
-# grab only names -rpzNames=$( /bin/echo "${rpzNameCount}" | /usr/bin/awk '{ print $1 }' ) +# grab only names +rpzNames=$( echo "${rpzNameCount}" | awk '{ print $1 }' )
-# get list of RPZ files -rpzFileList=$( /bin/find /etc/unbound/zonefiles -type f -iname "*.rpz" ) +# get list of RPZ files +rpzFileList=$( 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 ;' )
+# get basename of those files +rpzBaseNames=$( echo "${rpzFileList}" |
- sed 's|/etc/unbound/zonefiles/||g ; s|.rpz||g ;' )
-# add to rpzNames +# add to rpzNames rpzNames="${rpzNames}"$'\n'"${rpzBaseNames}"
-# drop duplicate names -rpzNames=$( echo "${rpzNames}" | /usr/bin/sort --unique ) +# drop duplicate names +rpzNames=$( echo "${rpzNames}" | sort --unique )
-# get line count for each RPZ -lineCount=$( /bin/echo "${rpzFileList}" | /usr/bin/xargs wc -l ) +# get line count for each RPZ +lineCount=$( echo "${rpzFileList}" | 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 comment line count and blank line count for each RPZ +commentCount=$( echo "${rpzFileList}" |
- xargs grep --count -e "^$" -e "^;" )
-# get modified date each RPZ -modDateList=$( /bin/echo "${rpzFileList}" | xargs stat -c '%.10y %n' ) +# get modified date each RPZ +modDateList=$( echo "${rpzFileList}" | xargs stat -c '%.10y %n' )
-ucListAuthZones=$( /usr/sbin/unbound-control list_auth_zones ) +ucListAuthZones=$( unbound-control list_auth_zones )
-# get width of RPZ names -pWidth=$( /bin/echo "${rpzNames}" | /usr/bin/awk '{ print $1" " }' | wc -L ) +# get width of RPZ names +pWidth=$( echo "${rpzNames}" | awk '{ print $1" " }' | wc -L ) pFormat="%-${pWidth}s %-8s %-8s %-8s %10s %12s\n"
-# print title line +# print title line printf "${pFormat}" "name" "hits" "active" "lines" "hits/line%" "last update" printf -- "--------------"
@@ -83,60 +82,60 @@ 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'
- printf -- "-" # pretend progress bar
- # get hit count
- theHits="0"
- if output=$( grep "^${theName}\s" <<< "${rpzNameCount}" ) ; then
theHits=$( echo "${output}" |
awk '{ print $2 }' )
totalHits=$(( totalHits + theHits ))
- fi
- # is this RPZ list active?
- theActive="disabled"
- if grep --quiet "^${theName}.rpz" <<< "${ucListAuthZones}"
- then
theActive="enabled"
- fi
- # get line count
- theLines="n/a"
- hitsPerLine="0"
- if output=$( grep --fixed-strings "/${theName}.rpz" <<< "${lineCount}" ) ; then
theLines=$( echo "${output}" | 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=$( grep --fixed-strings "/${theName}.rpz" <<< "${modDateList}" ) ; then
theModDate=$( echo "${output}" | 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"
- 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"
- 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"
- 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 }'
+# remove blank lines, sort, print as columns +echo "${theResults}" |
- awk '!/^[[:space:]]*$/' |
- sort "${sortArg[@]}" |
- 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}" "" "" diff --git a/config/rpz/rpz-sleep b/config/rpz/rpz-sleep index eeef1174a..dd3603599 100644 --- a/config/rpz/rpz-sleep +++ b/config/rpz/rpz-sleep @@ -19,38 +19,38 @@ # # ###############################################################################
-# v04 on 2024-07-05 +version="2024-08-16" # v05
############### Functions ###############
-# send message to message log +# send message to message log msg_log () {
- /usr/bin/logger --tag "${tagName}" "$*"
- if /usr/bin/tty --silent ; then
- echo "${tagName}:" "$*"
- fi
- logger --tag "${tagName}" "$*"
- if tty --silent ; then
echo "${tagName}:" "$*"
- fi
}
############### Main ###############
tagName="unbound"
-sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes) +sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes)
-zoneList=$( /usr/sbin/unbound-control list_auth_zones | /usr/bin/awk '{print $1}' ) +zoneList=$( unbound-control list_auth_zones | awk '{print $1}' )
for zone in ${zoneList} ; do
- /usr/bin/printf "disable ${zone}\t"
- /usr/sbin/unbound-control rpz_disable "${zone}"
- printf "disable ${zone}\t"
- unbound-control rpz_disable "${zone}"
done
msg_log "info: rpz: disabled all zones for ${sleepTime}"
-/bin/sleep "${sleepTime}" +sleep "${sleepTime}"
for zone in ${zoneList} ; do
- /usr/bin/printf "enable ${zone}\t"
- /usr/sbin/unbound-control rpz_enable "${zone}"
- printf "enable ${zone}\t"
- unbound-control rpz_enable "${zone}"
done
msg_log "info: rpz: enabled all zones" diff --git a/lfs/rpz b/lfs/rpz index 73f6f2b1b..16d1d0803 100644 --- a/lfs/rpz +++ b/lfs/rpz @@ -62,25 +62,31 @@ $(TARGET) : @$(PREBUILD) @rm -rf $(DIR_APP)
- # install RPZ scripts
- # install RPZ scripts
install -v -m 755 \ $(DIR_CONF)/rpz/{rpz-config,rpz-metrics,rpz-sleep} -t /usr/sbin
- # Add conf file to /etc directory
- cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d
- cp -vf $(DIR_CONF)/rpz/block.rpz.conf /etc/unbound/local.d
# Install settings folder and two empty files mkdir -pv /var/ipfire/dns/rpz touch /var/ipfire/dns/rpz/allowlist touch /var/ipfire/dns/rpz/blocklist
- # Add conf file to /etc directory
- cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d
- # create zonefiles directory for the RPZ files and add two empty RPZ
- # files to avoid a unbound config error
- # create zonefiles directory for the RPZ files and add two empty RPZ
- # files to avoid a unbound config error
mkdir -pv /etc/unbound/zonefiles
- chown -v nobody:nobody /etc/unbound/zonefiles
touch /etc/unbound/zonefiles/allow.rpz touch /etc/unbound/zonefiles/block.rpz
- # set owner for unbound related files
- chown -vR nobody:nobody \
- /var/ipfire/dns/rpz \
- /etc/unbound/zonefiles \
- /etc/unbound/local.d
# Install backup definition cp -vf $(DIR_CONF)/backup/includes/rpz /var/ipfire/backup/addons/includes/rpz
diff --git a/src/paks/rpz/uninstall.sh b/src/paks/rpz/uninstall.sh index 4fb20e127..51edaa176 100644 --- a/src/paks/rpz/uninstall.sh +++ b/src/paks/rpz/uninstall.sh @@ -27,5 +27,9 @@ make_backup ${NAME} remove_files
+# delete rpz config files. Otherwise unbound will throw error: +# "[1723428668] unbound-control[17117:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm -fv /etc/unbound/local.d/*.rpz.conf
# start unbound to load unbound config file /etc/init.d/unbound start diff --git a/src/paks/rpz/update.sh b/src/paks/rpz/update.sh index 938a93a40..fd46a185a 100644 --- a/src/paks/rpz/update.sh +++ b/src/paks/rpz/update.sh @@ -20,6 +20,24 @@ ############################################################################### # . /opt/pakfire/lib/functions.sh
+# from update.sh extract_backup_includes -./uninstall.sh -./install.sh
+# stop unbound to delete RPZ conf file +/etc/init.d/unbound stop
+# from uninstall.sh +make_backup ${NAME} +remove_files
+# delete rpz config files. Otherwise unbound will throw error: +# "unbound-control[nn:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm --verbose --force /etc/unbound/local.d/*.rpz.conf
+# from install.sh +extract_files +restore_backup ${NAME}
+# restart unbound to load config files
+/etc/init.d/unbound start
2.30.2
Jon
-- Jon Murphy jon.murphy@ipfire.org
To review and approve
See: https://lists.ipfire.org/hyperkitty/list/development@lists.ipfire.org/messag...
Jon
On Sep 29, 2024, at 6:31 AM, Michael Tremer michael.tremer@ipfire.org wrote:
What are you reminding us about?
On 28 Sep 2024, at 20:34, jon jon.murphy@ipfire.org wrote:
Gentle reminder…
On Aug 23, 2024, at 4:39 PM, Jon Murphy jon.murphy@ipfire.org wrote:
- feature: added "list" action
- update: changed "cat << heredocs" to "echo > file"
- update: remove path to executables
- update: reformatted code and comments (tabs to spaces)
- update: reworded some msg_log messages
- update: change exit codes from "1" to unique exit code numbers
- bug: added check for empty allow/block config file
- bug: removed auth_zone_reload (had double reload for allow/block)
- bug: change rpz config file to `chown nobody:nobody`
- bug: change rpz config file to `chmod 644`
Signed-off-by: Jon Murphy jon.murphy@ipfire.org
config/rootfiles/packages/rpz | 1 + config/rpz/00-rpz.conf | 22 +-- config/rpz/block.rpz.conf | 7 + config/rpz/rpz-config | 292 ++++++++++++++++++---------------- config/rpz/rpz-metrics | 163 ++++++++++--------- config/rpz/rpz-sleep | 26 +-- lfs/rpz | 20 ++- src/paks/rpz/uninstall.sh | 4 + src/paks/rpz/update.sh | 22 ++- 9 files changed, 297 insertions(+), 260 deletions(-) create mode 100644 config/rpz/block.rpz.conf
diff --git a/config/rootfiles/packages/rpz b/config/rootfiles/packages/rpz index 183825362..73c3efa06 100644 --- a/config/rootfiles/packages/rpz +++ b/config/rootfiles/packages/rpz @@ -1,4 +1,5 @@ etc/unbound/local.d/00-rpz.conf +etc/unbound/local.d/block.rpz.conf etc/unbound/zonefiles etc/unbound/zonefiles/allow.rpz etc/unbound/zonefiles/block.rpz diff --git a/config/rpz/00-rpz.conf b/config/rpz/00-rpz.conf index 72c1d12e5..f005a4f2e 100644 --- a/config/rpz/00-rpz.conf +++ b/config/rpz/00-rpz.conf @@ -1,18 +1,10 @@ server:
- module-config: "respip validator iterator"
- module-config: "respip validator iterator"
rpz:
- name: allow.rpz
- zonefile: /etc/unbound/zonefiles/allow.rpz
- rpz-action-override: passthru
- rpz-log: yes
- rpz-log-name: allow
- rpz-signal-nxdomain-ra: yes
-rpz:
- name: block.rpz
- zonefile: /etc/unbound/zonefiles/block.rpz
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: block
- rpz-signal-nxdomain-ra: yes
- name: allow.rpz
- zonefile: /etc/unbound/zonefiles/allow.rpz
- rpz-action-override: passthru
- rpz-log: yes
- rpz-log-name: allow
- rpz-signal-nxdomain-ra: yes
diff --git a/config/rpz/block.rpz.conf b/config/rpz/block.rpz.conf new file mode 100644 index 000000000..605684257 --- /dev/null +++ b/config/rpz/block.rpz.conf @@ -0,0 +1,7 @@ +rpz:
- name: block.rpz
- zonefile: /etc/unbound/zonefiles/block.rpz
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: block
- rpz-signal-nxdomain-ra: yes
diff --git a/config/rpz/rpz-config b/config/rpz/rpz-config index a24a5c132..9278aa004 100644 --- a/config/rpz/rpz-config +++ b/config/rpz/rpz-config @@ -19,176 +19,186 @@ # # ###############################################################################
-# v23 - 2024-07-30 +version="2024-08-18" # v28
############### Functions ###############
msg_log () {
- /usr/bin/logger --tag "${tagName}" "$*"
- if tty --silent ; then
- echo "${tagName}:" "$*"
- fi
- logger --tag "${tagName}" "$*"
- if tty --silent ; then
echo "${tagName}:" "$*"
- fi
}
check_name () {
- local testName="${1}"
- # check for a valid name
- regex='^[a-zA-Z0-9_]+$'
- if [[ ! "${testName}" =~ $regex ]] ; then
- msg_log "error: rpz: the NAME is not valid: "${testName}". exit."
- exit 1
- fi
- local testName="${1}"
- # check for a valid name
- regex='^[a-zA-Z0-9_]+$'
- if [[ ! "${testName}" =~ $regex ]] || [[ "${testName}" == "allow" ]] || [[ "${testName}" == "block" ]]; then
msg_log "error: rpz: the NAME is not valid: \"${testName}\". exit."
exit 101
- fi
}
check_unbound_conf () {
- # check the above config files
- msg_log "info: rpz: check for errors with "unbound-checkconf""
- /usr/sbin/unbound-checkconf
- exit_code=$?
- if [[ "${exit_code}" -ne 0 ]] ; then
- msg_log "error: rpz: unbound-checkconf. exit."
- exit "${exit_code}"
- fi
- # check the above config files
- msg_log "info: rpz: check for errors with "unbound-checkconf""
- unbound-checkconf
- exit_code=$?
- if [[ "${exit_code}" -ne 0 ]] ; then
msg_log "error: rpz: unbound-checkconf found invalid configuration."
msg_log "error: rpz: In the Terminal run the command \
\"unbound-checkconf\" for more information. exit."
exit 102
- fi
}
make_rpz_file () {
- local theType="${1}" # allow or block
- theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains
- theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ
- theAction='.'
- if [[ "${theType}" =~ "allow" ]] ; then
- theAction='rpz-passthru.'
- fi
- # does a list exist?
- if [[ -s "${theList}" ]] ; then
- # drop any extra "blanks" and add "CNAME <RPZ action>." to each line
- actionList=$( /usr/bin/awk '{$1=$1};1' "${theList}" |
- /bin/sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" )
- msg_log "info: rpz: create zonefile for ${theList}"
- /bin/cat <<-EOF > "${theZoneFile}"
- ; Name: ${theType} list
- ; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z")
- ;
- ; domains with actions list
- ;
- ${actionList}
- EOF
- # reload the zone that was just updated
- zoneBase=$( basename "${theZoneFile}" )
- /usr/sbin/unbound-control auth_zone_reload -q "${zoneBase}"
- fi
- local theType="${1}" # allow or block
- theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains
- theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ
- # does a list exist?
- if ! [[ -s "${theList}" ]] ; then
msg_log "error: rpz: the ${theList} is empty. exit."
exit 103
- fi
- theAction='.'
- if [[ "${theType}" =~ "allow" ]] ; then
theAction='rpz-passthru.'
- fi
- # drop any extra "blanks" and add "CNAME <RPZ action>." to each line
- actionList=$( awk '{$1=$1};1' "${theList}" |
sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" )
- msg_log "info: rpz: create zonefile for ${theList}"
+echo " +; Name: ${theType} list +; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z") +; +; domains with actions list +; +${actionList} +" > "${theZoneFile}"
}
############### Main ###############
tagName="unbound"
-theAction="${1}" # input action -theName="${2}" # input RPZ name -theURL="${3}" # input RPZ URL
-check_name "${theName}" # is this a valid name? +theAction="${1}" # input action +theName="${2}" # input RPZ name +theURL="${3}" # input RPZ URL
-rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file -rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file +rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file +rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file
case "${theAction}" in
- # add new rpz list
- add )
- # does this config already exist? If yes, then exit
- if [[ -f "${rpzConfig}" ]] ; then
- msg_log "info: rpz: ${rpzConfig} already exists. exit"
- exit 1
- fi
- # is this a valid URL?
- regex='^https://%5B-%5B:alnum:%5D%5C+&@#/%?=~_%7C!:,.;%5D*%5B-%5B:alnum:%5D%5C+&...]'
- if ! [[ "${theURL}" =~ $regex ]] ; then
- msg_log "error: rpz: the URL is not valid: "${theURL}". exit."
- exit 1
- fi
- # create the zone config file
- msg_log "info: rpz: add config file "${theName}.rpz.conf""
- cat <<-EOF > "${rpzConfig}"
- rpz:
- name: ${theName}.rpz
- zonefile: /etc/unbound/zonefiles/${theName}.rpz
- url: ${theURL}
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: ${theName}
- rpz-signal-nxdomain-ra: yes
- EOF
- # set-up zone file
- /usr/bin/touch "${rpzFile}"
- # unbound requires these settings for rpz files
- /bin/chown nobody:nobody "${rpzFile}"
- /bin/chmod 644 "${rpzFile}"
- ;;
- # trash config file & rpz file
- remove )
- if ! [[ -f "${rpzConfig}" ]] ; then
- msg_log "info: rpz: ${rpzConfig} does not exist. exit"
- exit 1
- fi
- msg_log "info: rpz: remove config file & rpz file "${theName}""
- /bin/rm "${rpzConfig}"
- /bin/rm "${rpzFile}"
- check_unbound_conf
- ;;
- # make a new allow or block rpz file
- make )
- case "${theName}" in
- allow )
- make_rpz_file allow
- ;;
- block )
- make_rpz_file block
- ;;
- allowblock )
- make_rpz_file allow
- make_rpz_file block
- ;;
- )
- msg_log "error: rpz: the NAME is not valid: "${theName}". exit."
- exit 1
- ;;
- esac
- check_unbound_conf
- ;;
- *)
- msg_log "error: rpz: missing or incorrect parameter"
- /usr/bin/printf "Usage: rpzConfig.sh <ACTION> <NAME> <URL>\n"
- exit 1
- ;;
- # add new rpz list
- add )
- check_name "${theName}" # is this a valid name?
# does this config already exist? If yes, then exit
if [[ -f "${rpzConfig}" ]] ; then
msg_log "error: rpz: duplicate - ${rpzConfig} already exists. exit"
exit 104
fi
# is this a valid URL?
regex='^https://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
if ! [[ "${theURL}" =~ $regex ]] ; then
msg_log "error: rpz: the URL is not valid: \"${theURL}\". exit."
exit 105
fi
# create the zone config file
msg_log "info: rpz: add config file \"${theName}.rpz.conf\""
+echo "rpz:
- name: ${theName}.rpz
- zonefile: ${rpzFile}
- url: ${theURL}
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: ${theName}
- rpz-signal-nxdomain-ra: yes
+" > "${rpzConfig}"
# set-up zonefile
# create an empty rpz file
touch "${rpzFile}"
# unbound requires these settings for rpz files
chown nobody:nobody "${rpzFile}" "${rpzConfig}"
chmod 644 "${rpzFile}" "${rpzConfig}"
;;
- # trash config file & rpz file
- remove )
- check_name "${theName}" # is this a valid name?
if ! [[ -f "${rpzConfig}" ]] ; then
msg_log "error: rpz: cannot remove ${rpzConfig}, does not exist. exit"
exit 106
fi
msg_log "info: rpz: remove config file & rpz file \"${theName}\""
rm "${rpzConfig}"
rm "${rpzFile}"
check_unbound_conf
;;
- # make a new allow or block rpz file
- make )
case "${theName}" in
allow )
make_rpz_file allow
;;
block )
make_rpz_file block
;;
allowblock )
make_rpz_file allow
make_rpz_file block
;;
* )
msg_log \
"error: rpz: the NAME \"${theName}\" is not valid - \"allow\" or \"block\" only. exit."
exit 107
;;
esac
check_unbound_conf
;;
- list)
awk -F' ' '/^name:|\sname:/{ gsub(/.rpz/, "" ) ; printf $2} /\surl:|^url:/{print "="$2}' \
/etc/unbound/local.d/*.rpz.conf
exit
;;
- *)
msg_log "error: rpz: missing or incorrect parameter"
printf "Usage: rpzConfig <ACTION> <NAME> <URL>\n"
printf "Version: ${version}\n"
exit 108
;;
esac
-# reload due to the changes +# reload due to the changes msg_log "rpz: running "unbound-control reload"" -/usr/sbin/unbound-control reload +unbound-control reload exit_code=$? if [[ "${exit_code}" -ne 0 ]] ; then
- msg_log "error: rpz: unbound-control "${theName}". exit."
- exit "${exit_code}"
- msg_log "error: rpz: unbound-control "${theName}". exit."
- exit 109
fi
exit diff --git a/config/rpz/rpz-metrics b/config/rpz/rpz-metrics index 4d932726e..d154f70b9 100644 --- a/config/rpz/rpz-metrics +++ b/config/rpz/rpz-metrics @@ -19,62 +19,61 @@ # # ###############################################################################
-# v19 on 2024-07-30 +version="2024-08-16" # v20
############### Main ###############
-weeks="${1:-2}" # default to two message logs -sortBy="${2:-name}" # by name or by hits +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 message logs for N weeks +messageLogs=$( find /var/log/messages* -type f | sort --version-sort |
- head -"${weeks}" )
-# get the list of RPZ names & counts from the message log(s) +# 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 )
- zgrep --text --extended-regexp 'info: rpz: applied.* A IN$' "${logf}" |
awk '$10 ~ /\[\w*]/ { print $10 }' ;
- done | sort | uniq --count )
-# flip results and remove brackets `[` and `]` -rpzNameCount=$( /bin/echo "${rpzNameCount}" |
- /usr/bin/awk '{ print $2, $1 }' |
- /bin/sed --regexp-extended 's|^[(.*)]|\1|' )
+# flip results and remove brackets `[` and `]` +rpzNameCount=$( echo "${rpzNameCount}" |
- awk '{ print $2, $1 }' |
sed --regexp-extended 's|^\[(.*)\]|\1|' )
-# grab only names -rpzNames=$( /bin/echo "${rpzNameCount}" | /usr/bin/awk '{ print $1 }' ) +# grab only names +rpzNames=$( echo "${rpzNameCount}" | awk '{ print $1 }' )
-# get list of RPZ files -rpzFileList=$( /bin/find /etc/unbound/zonefiles -type f -iname "*.rpz" ) +# get list of RPZ files +rpzFileList=$( 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 ;' )
+# get basename of those files +rpzBaseNames=$( echo "${rpzFileList}" |
- sed 's|/etc/unbound/zonefiles/||g ; s|.rpz||g ;' )
-# add to rpzNames +# add to rpzNames rpzNames="${rpzNames}"$'\n'"${rpzBaseNames}"
-# drop duplicate names -rpzNames=$( echo "${rpzNames}" | /usr/bin/sort --unique ) +# drop duplicate names +rpzNames=$( echo "${rpzNames}" | sort --unique )
-# get line count for each RPZ -lineCount=$( /bin/echo "${rpzFileList}" | /usr/bin/xargs wc -l ) +# get line count for each RPZ +lineCount=$( echo "${rpzFileList}" | 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 comment line count and blank line count for each RPZ +commentCount=$( echo "${rpzFileList}" |
- xargs grep --count -e "^$" -e "^;" )
-# get modified date each RPZ -modDateList=$( /bin/echo "${rpzFileList}" | xargs stat -c '%.10y %n' ) +# get modified date each RPZ +modDateList=$( echo "${rpzFileList}" | xargs stat -c '%.10y %n' )
-ucListAuthZones=$( /usr/sbin/unbound-control list_auth_zones ) +ucListAuthZones=$( unbound-control list_auth_zones )
-# get width of RPZ names -pWidth=$( /bin/echo "${rpzNames}" | /usr/bin/awk '{ print $1" " }' | wc -L ) +# get width of RPZ names +pWidth=$( echo "${rpzNames}" | awk '{ print $1" " }' | wc -L ) pFormat="%-${pWidth}s %-8s %-8s %-8s %10s %12s\n"
-# print title line +# print title line printf "${pFormat}" "name" "hits" "active" "lines" "hits/line%" "last update" printf -- "--------------"
@@ -83,60 +82,60 @@ 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'
- printf -- "-" # pretend progress bar
- # get hit count
- theHits="0"
- if output=$( grep "^${theName}\s" <<< "${rpzNameCount}" ) ; then
theHits=$( echo "${output}" |
awk '{ print $2 }' )
totalHits=$(( totalHits + theHits ))
- fi
- # is this RPZ list active?
- theActive="disabled"
- if grep --quiet "^${theName}.rpz" <<< "${ucListAuthZones}"
- then
theActive="enabled"
- fi
- # get line count
- theLines="n/a"
- hitsPerLine="0"
- if output=$( grep --fixed-strings "/${theName}.rpz" <<< "${lineCount}" ) ; then
theLines=$( echo "${output}" | 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=$( grep --fixed-strings "/${theName}.rpz" <<< "${modDateList}" ) ; then
theModDate=$( echo "${output}" | 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"
- 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"
- 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"
- 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 }'
+# remove blank lines, sort, print as columns +echo "${theResults}" |
- awk '!/^[[:space:]]*$/' |
- sort "${sortArg[@]}" |
- 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}" "" "" diff --git a/config/rpz/rpz-sleep b/config/rpz/rpz-sleep index eeef1174a..dd3603599 100644 --- a/config/rpz/rpz-sleep +++ b/config/rpz/rpz-sleep @@ -19,38 +19,38 @@ # # ###############################################################################
-# v04 on 2024-07-05 +version="2024-08-16" # v05
############### Functions ###############
-# send message to message log +# send message to message log msg_log () {
- /usr/bin/logger --tag "${tagName}" "$*"
- if /usr/bin/tty --silent ; then
- echo "${tagName}:" "$*"
- fi
- logger --tag "${tagName}" "$*"
- if tty --silent ; then
echo "${tagName}:" "$*"
- fi
}
############### Main ###############
tagName="unbound"
-sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes) +sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes)
-zoneList=$( /usr/sbin/unbound-control list_auth_zones | /usr/bin/awk '{print $1}' ) +zoneList=$( unbound-control list_auth_zones | awk '{print $1}' )
for zone in ${zoneList} ; do
- /usr/bin/printf "disable ${zone}\t"
- /usr/sbin/unbound-control rpz_disable "${zone}"
- printf "disable ${zone}\t"
- unbound-control rpz_disable "${zone}"
done
msg_log "info: rpz: disabled all zones for ${sleepTime}"
-/bin/sleep "${sleepTime}" +sleep "${sleepTime}"
for zone in ${zoneList} ; do
- /usr/bin/printf "enable ${zone}\t"
- /usr/sbin/unbound-control rpz_enable "${zone}"
- printf "enable ${zone}\t"
- unbound-control rpz_enable "${zone}"
done
msg_log "info: rpz: enabled all zones" diff --git a/lfs/rpz b/lfs/rpz index 73f6f2b1b..16d1d0803 100644 --- a/lfs/rpz +++ b/lfs/rpz @@ -62,25 +62,31 @@ $(TARGET) : @$(PREBUILD) @rm -rf $(DIR_APP)
- # install RPZ scripts
- # install RPZ scripts
install -v -m 755 \ $(DIR_CONF)/rpz/{rpz-config,rpz-metrics,rpz-sleep} -t /usr/sbin
- # Add conf file to /etc directory
- cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d
- cp -vf $(DIR_CONF)/rpz/block.rpz.conf /etc/unbound/local.d
# Install settings folder and two empty files mkdir -pv /var/ipfire/dns/rpz touch /var/ipfire/dns/rpz/allowlist touch /var/ipfire/dns/rpz/blocklist
- # Add conf file to /etc directory
- cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d
- # create zonefiles directory for the RPZ files and add two empty RPZ
- # files to avoid a unbound config error
- # create zonefiles directory for the RPZ files and add two empty RPZ
- # files to avoid a unbound config error
mkdir -pv /etc/unbound/zonefiles
- chown -v nobody:nobody /etc/unbound/zonefiles
touch /etc/unbound/zonefiles/allow.rpz touch /etc/unbound/zonefiles/block.rpz
- # set owner for unbound related files
- chown -vR nobody:nobody \
- /var/ipfire/dns/rpz \
- /etc/unbound/zonefiles \
- /etc/unbound/local.d
# Install backup definition cp -vf $(DIR_CONF)/backup/includes/rpz /var/ipfire/backup/addons/includes/rpz
diff --git a/src/paks/rpz/uninstall.sh b/src/paks/rpz/uninstall.sh index 4fb20e127..51edaa176 100644 --- a/src/paks/rpz/uninstall.sh +++ b/src/paks/rpz/uninstall.sh @@ -27,5 +27,9 @@ make_backup ${NAME} remove_files
+# delete rpz config files. Otherwise unbound will throw error: +# "[1723428668] unbound-control[17117:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm -fv /etc/unbound/local.d/*.rpz.conf
# start unbound to load unbound config file /etc/init.d/unbound start diff --git a/src/paks/rpz/update.sh b/src/paks/rpz/update.sh index 938a93a40..fd46a185a 100644 --- a/src/paks/rpz/update.sh +++ b/src/paks/rpz/update.sh @@ -20,6 +20,24 @@ ############################################################################### # . /opt/pakfire/lib/functions.sh
+# from update.sh extract_backup_includes -./uninstall.sh -./install.sh
+# stop unbound to delete RPZ conf file +/etc/init.d/unbound stop
+# from uninstall.sh +make_backup ${NAME} +remove_files
+# delete rpz config files. Otherwise unbound will throw error: +# "unbound-control[nn:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm --verbose --force /etc/unbound/local.d/*.rpz.conf
+# from install.sh +extract_files +restore_backup ${NAME}
+# restart unbound to load config files
+/etc/init.d/unbound start
2.30.2
Jon
-- Jon Murphy jon.murphy@ipfire.org
Jon
Hello Jon,
I don’t think that we are at a point where I feel comfortable with approving this. I believe that the fundamental questions that I have raised about this have not been addressed.
As stated before I did not look much at the code and I am not a point where a code review is what I need. I am at a point right now where I want to figure out what this feature is going to be and value is it going to bring our users. I just once again went through the Hagezi lists to find any sense in them and I must say that this is not really what could replace the URL filter at all. It is just large lists that nobody knows where they are coming from and what they contain. I don’t have any time to invest into researching alternatives.
And for this reason alone I don’t see why this would be interesting for our users.
It would really help me if you can help me understand this and help answering the questions that I have asked in the past.
What do you mean by moving *forward*? What are the next steps?
-Michael
On 29 Sep 2024, at 16:53, jon jon.murphy@ipfire.org wrote:
To review and approve
See: https://lists.ipfire.org/hyperkitty/list/development@lists.ipfire.org/messag...
Jon
On Sep 29, 2024, at 6:31 AM, Michael Tremer michael.tremer@ipfire.org wrote:
What are you reminding us about?
On 28 Sep 2024, at 20:34, jon jon.murphy@ipfire.org wrote:
Gentle reminder…
On Aug 23, 2024, at 4:39 PM, Jon Murphy jon.murphy@ipfire.org wrote:
- feature: added "list" action
- update: changed "cat << heredocs" to "echo > file"
- update: remove path to executables
- update: reformatted code and comments (tabs to spaces)
- update: reworded some msg_log messages
- update: change exit codes from "1" to unique exit code numbers
- bug: added check for empty allow/block config file
- bug: removed auth_zone_reload (had double reload for allow/block)
- bug: change rpz config file to `chown nobody:nobody`
- bug: change rpz config file to `chmod 644`
Signed-off-by: Jon Murphy jon.murphy@ipfire.org
config/rootfiles/packages/rpz | 1 + config/rpz/00-rpz.conf | 22 +-- config/rpz/block.rpz.conf | 7 + config/rpz/rpz-config | 292 ++++++++++++++++++---------------- config/rpz/rpz-metrics | 163 ++++++++++--------- config/rpz/rpz-sleep | 26 +-- lfs/rpz | 20 ++- src/paks/rpz/uninstall.sh | 4 + src/paks/rpz/update.sh | 22 ++- 9 files changed, 297 insertions(+), 260 deletions(-) create mode 100644 config/rpz/block.rpz.conf
diff --git a/config/rootfiles/packages/rpz b/config/rootfiles/packages/rpz index 183825362..73c3efa06 100644 --- a/config/rootfiles/packages/rpz +++ b/config/rootfiles/packages/rpz @@ -1,4 +1,5 @@ etc/unbound/local.d/00-rpz.conf +etc/unbound/local.d/block.rpz.conf etc/unbound/zonefiles etc/unbound/zonefiles/allow.rpz etc/unbound/zonefiles/block.rpz diff --git a/config/rpz/00-rpz.conf b/config/rpz/00-rpz.conf index 72c1d12e5..f005a4f2e 100644 --- a/config/rpz/00-rpz.conf +++ b/config/rpz/00-rpz.conf @@ -1,18 +1,10 @@ server:
- module-config: "respip validator iterator"
- module-config: "respip validator iterator"
rpz:
- name: allow.rpz
- zonefile: /etc/unbound/zonefiles/allow.rpz
- rpz-action-override: passthru
- rpz-log: yes
- rpz-log-name: allow
- rpz-signal-nxdomain-ra: yes
-rpz:
- name: block.rpz
- zonefile: /etc/unbound/zonefiles/block.rpz
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: block
- rpz-signal-nxdomain-ra: yes
- name: allow.rpz
- zonefile: /etc/unbound/zonefiles/allow.rpz
- rpz-action-override: passthru
- rpz-log: yes
- rpz-log-name: allow
- rpz-signal-nxdomain-ra: yes
diff --git a/config/rpz/block.rpz.conf b/config/rpz/block.rpz.conf new file mode 100644 index 000000000..605684257 --- /dev/null +++ b/config/rpz/block.rpz.conf @@ -0,0 +1,7 @@ +rpz:
- name: block.rpz
- zonefile: /etc/unbound/zonefiles/block.rpz
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: block
- rpz-signal-nxdomain-ra: yes
diff --git a/config/rpz/rpz-config b/config/rpz/rpz-config index a24a5c132..9278aa004 100644 --- a/config/rpz/rpz-config +++ b/config/rpz/rpz-config @@ -19,176 +19,186 @@ # # ###############################################################################
-# v23 - 2024-07-30 +version="2024-08-18" # v28
############### Functions ###############
msg_log () {
- /usr/bin/logger --tag "${tagName}" "$*"
- if tty --silent ; then
- echo "${tagName}:" "$*"
- fi
- logger --tag "${tagName}" "$*"
- if tty --silent ; then
echo "${tagName}:" "$*"
- fi
}
check_name () {
- local testName="${1}"
- # check for a valid name
- regex='^[a-zA-Z0-9_]+$'
- if [[ ! "${testName}" =~ $regex ]] ; then
- msg_log "error: rpz: the NAME is not valid: "${testName}". exit."
- exit 1
- fi
- local testName="${1}"
- # check for a valid name
- regex='^[a-zA-Z0-9_]+$'
- if [[ ! "${testName}" =~ $regex ]] || [[ "${testName}" == "allow" ]] || [[ "${testName}" == "block" ]]; then
msg_log "error: rpz: the NAME is not valid: \"${testName}\". exit."
exit 101
- fi
}
check_unbound_conf () {
- # check the above config files
- msg_log "info: rpz: check for errors with "unbound-checkconf""
- /usr/sbin/unbound-checkconf
- exit_code=$?
- if [[ "${exit_code}" -ne 0 ]] ; then
- msg_log "error: rpz: unbound-checkconf. exit."
- exit "${exit_code}"
- fi
- # check the above config files
- msg_log "info: rpz: check for errors with "unbound-checkconf""
- unbound-checkconf
- exit_code=$?
- if [[ "${exit_code}" -ne 0 ]] ; then
msg_log "error: rpz: unbound-checkconf found invalid configuration."
msg_log "error: rpz: In the Terminal run the command \
\"unbound-checkconf\" for more information. exit."
exit 102
- fi
}
make_rpz_file () {
- local theType="${1}" # allow or block
- theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains
- theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ
- theAction='.'
- if [[ "${theType}" =~ "allow" ]] ; then
- theAction='rpz-passthru.'
- fi
- # does a list exist?
- if [[ -s "${theList}" ]] ; then
- # drop any extra "blanks" and add "CNAME <RPZ action>." to each line
- actionList=$( /usr/bin/awk '{$1=$1};1' "${theList}" |
- /bin/sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" )
- msg_log "info: rpz: create zonefile for ${theList}"
- /bin/cat <<-EOF > "${theZoneFile}"
- ; Name: ${theType} list
- ; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z")
- ;
- ; domains with actions list
- ;
- ${actionList}
- EOF
- # reload the zone that was just updated
- zoneBase=$( basename "${theZoneFile}" )
- /usr/sbin/unbound-control auth_zone_reload -q "${zoneBase}"
- fi
- local theType="${1}" # allow or block
- theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains
- theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ
- # does a list exist?
- if ! [[ -s "${theList}" ]] ; then
msg_log "error: rpz: the ${theList} is empty. exit."
exit 103
- fi
- theAction='.'
- if [[ "${theType}" =~ "allow" ]] ; then
theAction='rpz-passthru.'
- fi
- # drop any extra "blanks" and add "CNAME <RPZ action>." to each line
- actionList=$( awk '{$1=$1};1' "${theList}" |
sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" )
- msg_log "info: rpz: create zonefile for ${theList}"
+echo " +; Name: ${theType} list +; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z") +; +; domains with actions list +; +${actionList} +" > "${theZoneFile}"
}
############### Main ###############
tagName="unbound"
-theAction="${1}" # input action -theName="${2}" # input RPZ name -theURL="${3}" # input RPZ URL
-check_name "${theName}" # is this a valid name? +theAction="${1}" # input action +theName="${2}" # input RPZ name +theURL="${3}" # input RPZ URL
-rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file -rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file +rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file +rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file
case "${theAction}" in
- # add new rpz list
- add )
- # does this config already exist? If yes, then exit
- if [[ -f "${rpzConfig}" ]] ; then
- msg_log "info: rpz: ${rpzConfig} already exists. exit"
- exit 1
- fi
- # is this a valid URL?
- regex='^https://%5B-%5B:alnum:%5D%5C+&@#/%?=~_%7C!:,.;%5D*%5B-%5B:alnum:%5D%5C+&...]'
- if ! [[ "${theURL}" =~ $regex ]] ; then
- msg_log "error: rpz: the URL is not valid: "${theURL}". exit."
- exit 1
- fi
- # create the zone config file
- msg_log "info: rpz: add config file "${theName}.rpz.conf""
- cat <<-EOF > "${rpzConfig}"
- rpz:
- name: ${theName}.rpz
- zonefile: /etc/unbound/zonefiles/${theName}.rpz
- url: ${theURL}
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: ${theName}
- rpz-signal-nxdomain-ra: yes
- EOF
- # set-up zone file
- /usr/bin/touch "${rpzFile}"
- # unbound requires these settings for rpz files
- /bin/chown nobody:nobody "${rpzFile}"
- /bin/chmod 644 "${rpzFile}"
- ;;
- # trash config file & rpz file
- remove )
- if ! [[ -f "${rpzConfig}" ]] ; then
- msg_log "info: rpz: ${rpzConfig} does not exist. exit"
- exit 1
- fi
- msg_log "info: rpz: remove config file & rpz file "${theName}""
- /bin/rm "${rpzConfig}"
- /bin/rm "${rpzFile}"
- check_unbound_conf
- ;;
- # make a new allow or block rpz file
- make )
- case "${theName}" in
- allow )
- make_rpz_file allow
- ;;
- block )
- make_rpz_file block
- ;;
- allowblock )
- make_rpz_file allow
- make_rpz_file block
- ;;
- )
- msg_log "error: rpz: the NAME is not valid: "${theName}". exit."
- exit 1
- ;;
- esac
- check_unbound_conf
- ;;
- *)
- msg_log "error: rpz: missing or incorrect parameter"
- /usr/bin/printf "Usage: rpzConfig.sh <ACTION> <NAME> <URL>\n"
- exit 1
- ;;
- # add new rpz list
- add )
- check_name "${theName}" # is this a valid name?
# does this config already exist? If yes, then exit
if [[ -f "${rpzConfig}" ]] ; then
msg_log "error: rpz: duplicate - ${rpzConfig} already exists. exit"
exit 104
fi
# is this a valid URL?
regex='^https://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
if ! [[ "${theURL}" =~ $regex ]] ; then
msg_log "error: rpz: the URL is not valid: \"${theURL}\". exit."
exit 105
fi
# create the zone config file
msg_log "info: rpz: add config file \"${theName}.rpz.conf\""
+echo "rpz:
- name: ${theName}.rpz
- zonefile: ${rpzFile}
- url: ${theURL}
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: ${theName}
- rpz-signal-nxdomain-ra: yes
+" > "${rpzConfig}"
# set-up zonefile
# create an empty rpz file
touch "${rpzFile}"
# unbound requires these settings for rpz files
chown nobody:nobody "${rpzFile}" "${rpzConfig}"
chmod 644 "${rpzFile}" "${rpzConfig}"
;;
- # trash config file & rpz file
- remove )
- check_name "${theName}" # is this a valid name?
if ! [[ -f "${rpzConfig}" ]] ; then
msg_log "error: rpz: cannot remove ${rpzConfig}, does not exist. exit"
exit 106
fi
msg_log "info: rpz: remove config file & rpz file \"${theName}\""
rm "${rpzConfig}"
rm "${rpzFile}"
check_unbound_conf
;;
- # make a new allow or block rpz file
- make )
case "${theName}" in
allow )
make_rpz_file allow
;;
block )
make_rpz_file block
;;
allowblock )
make_rpz_file allow
make_rpz_file block
;;
* )
msg_log \
"error: rpz: the NAME \"${theName}\" is not valid - \"allow\" or \"block\" only. exit."
exit 107
;;
esac
check_unbound_conf
;;
- list)
awk -F' ' '/^name:|\sname:/{ gsub(/.rpz/, "" ) ; printf $2} /\surl:|^url:/{print "="$2}' \
/etc/unbound/local.d/*.rpz.conf
exit
;;
- *)
msg_log "error: rpz: missing or incorrect parameter"
printf "Usage: rpzConfig <ACTION> <NAME> <URL>\n"
printf "Version: ${version}\n"
exit 108
;;
esac
-# reload due to the changes +# reload due to the changes msg_log "rpz: running "unbound-control reload"" -/usr/sbin/unbound-control reload +unbound-control reload exit_code=$? if [[ "${exit_code}" -ne 0 ]] ; then
- msg_log "error: rpz: unbound-control "${theName}". exit."
- exit "${exit_code}"
- msg_log "error: rpz: unbound-control "${theName}". exit."
- exit 109
fi
exit diff --git a/config/rpz/rpz-metrics b/config/rpz/rpz-metrics index 4d932726e..d154f70b9 100644 --- a/config/rpz/rpz-metrics +++ b/config/rpz/rpz-metrics @@ -19,62 +19,61 @@ # # ###############################################################################
-# v19 on 2024-07-30 +version="2024-08-16" # v20
############### Main ###############
-weeks="${1:-2}" # default to two message logs -sortBy="${2:-name}" # by name or by hits +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 message logs for N weeks +messageLogs=$( find /var/log/messages* -type f | sort --version-sort |
- head -"${weeks}" )
-# get the list of RPZ names & counts from the message log(s) +# 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 )
- zgrep --text --extended-regexp 'info: rpz: applied.* A IN$' "${logf}" |
awk '$10 ~ /\[\w*]/ { print $10 }' ;
- done | sort | uniq --count )
-# flip results and remove brackets `[` and `]` -rpzNameCount=$( /bin/echo "${rpzNameCount}" |
- /usr/bin/awk '{ print $2, $1 }' |
- /bin/sed --regexp-extended 's|^[(.*)]|\1|' )
+# flip results and remove brackets `[` and `]` +rpzNameCount=$( echo "${rpzNameCount}" |
- awk '{ print $2, $1 }' |
sed --regexp-extended 's|^\[(.*)\]|\1|' )
-# grab only names -rpzNames=$( /bin/echo "${rpzNameCount}" | /usr/bin/awk '{ print $1 }' ) +# grab only names +rpzNames=$( echo "${rpzNameCount}" | awk '{ print $1 }' )
-# get list of RPZ files -rpzFileList=$( /bin/find /etc/unbound/zonefiles -type f -iname "*.rpz" ) +# get list of RPZ files +rpzFileList=$( 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 ;' )
+# get basename of those files +rpzBaseNames=$( echo "${rpzFileList}" |
- sed 's|/etc/unbound/zonefiles/||g ; s|.rpz||g ;' )
-# add to rpzNames +# add to rpzNames rpzNames="${rpzNames}"$'\n'"${rpzBaseNames}"
-# drop duplicate names -rpzNames=$( echo "${rpzNames}" | /usr/bin/sort --unique ) +# drop duplicate names +rpzNames=$( echo "${rpzNames}" | sort --unique )
-# get line count for each RPZ -lineCount=$( /bin/echo "${rpzFileList}" | /usr/bin/xargs wc -l ) +# get line count for each RPZ +lineCount=$( echo "${rpzFileList}" | 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 comment line count and blank line count for each RPZ +commentCount=$( echo "${rpzFileList}" |
- xargs grep --count -e "^$" -e "^;" )
-# get modified date each RPZ -modDateList=$( /bin/echo "${rpzFileList}" | xargs stat -c '%.10y %n' ) +# get modified date each RPZ +modDateList=$( echo "${rpzFileList}" | xargs stat -c '%.10y %n' )
-ucListAuthZones=$( /usr/sbin/unbound-control list_auth_zones ) +ucListAuthZones=$( unbound-control list_auth_zones )
-# get width of RPZ names -pWidth=$( /bin/echo "${rpzNames}" | /usr/bin/awk '{ print $1" " }' | wc -L ) +# get width of RPZ names +pWidth=$( echo "${rpzNames}" | awk '{ print $1" " }' | wc -L ) pFormat="%-${pWidth}s %-8s %-8s %-8s %10s %12s\n"
-# print title line +# print title line printf "${pFormat}" "name" "hits" "active" "lines" "hits/line%" "last update" printf -- "--------------"
@@ -83,60 +82,60 @@ 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'
- printf -- "-" # pretend progress bar
- # get hit count
- theHits="0"
- if output=$( grep "^${theName}\s" <<< "${rpzNameCount}" ) ; then
theHits=$( echo "${output}" |
awk '{ print $2 }' )
totalHits=$(( totalHits + theHits ))
- fi
- # is this RPZ list active?
- theActive="disabled"
- if grep --quiet "^${theName}.rpz" <<< "${ucListAuthZones}"
- then
theActive="enabled"
- fi
- # get line count
- theLines="n/a"
- hitsPerLine="0"
- if output=$( grep --fixed-strings "/${theName}.rpz" <<< "${lineCount}" ) ; then
theLines=$( echo "${output}" | 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=$( grep --fixed-strings "/${theName}.rpz" <<< "${modDateList}" ) ; then
theModDate=$( echo "${output}" | 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"
- 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"
- 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"
- 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 }'
+# remove blank lines, sort, print as columns +echo "${theResults}" |
- awk '!/^[[:space:]]*$/' |
- sort "${sortArg[@]}" |
- 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}" "" "" diff --git a/config/rpz/rpz-sleep b/config/rpz/rpz-sleep index eeef1174a..dd3603599 100644 --- a/config/rpz/rpz-sleep +++ b/config/rpz/rpz-sleep @@ -19,38 +19,38 @@ # # ###############################################################################
-# v04 on 2024-07-05 +version="2024-08-16" # v05
############### Functions ###############
-# send message to message log +# send message to message log msg_log () {
- /usr/bin/logger --tag "${tagName}" "$*"
- if /usr/bin/tty --silent ; then
- echo "${tagName}:" "$*"
- fi
- logger --tag "${tagName}" "$*"
- if tty --silent ; then
echo "${tagName}:" "$*"
- fi
}
############### Main ###############
tagName="unbound"
-sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes) +sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes)
-zoneList=$( /usr/sbin/unbound-control list_auth_zones | /usr/bin/awk '{print $1}' ) +zoneList=$( unbound-control list_auth_zones | awk '{print $1}' )
for zone in ${zoneList} ; do
- /usr/bin/printf "disable ${zone}\t"
- /usr/sbin/unbound-control rpz_disable "${zone}"
- printf "disable ${zone}\t"
- unbound-control rpz_disable "${zone}"
done
msg_log "info: rpz: disabled all zones for ${sleepTime}"
-/bin/sleep "${sleepTime}" +sleep "${sleepTime}"
for zone in ${zoneList} ; do
- /usr/bin/printf "enable ${zone}\t"
- /usr/sbin/unbound-control rpz_enable "${zone}"
- printf "enable ${zone}\t"
- unbound-control rpz_enable "${zone}"
done
msg_log "info: rpz: enabled all zones" diff --git a/lfs/rpz b/lfs/rpz index 73f6f2b1b..16d1d0803 100644 --- a/lfs/rpz +++ b/lfs/rpz @@ -62,25 +62,31 @@ $(TARGET) : @$(PREBUILD) @rm -rf $(DIR_APP)
- # install RPZ scripts
- # install RPZ scripts
install -v -m 755 \ $(DIR_CONF)/rpz/{rpz-config,rpz-metrics,rpz-sleep} -t /usr/sbin
- # Add conf file to /etc directory
- cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d
- cp -vf $(DIR_CONF)/rpz/block.rpz.conf /etc/unbound/local.d
# Install settings folder and two empty files mkdir -pv /var/ipfire/dns/rpz touch /var/ipfire/dns/rpz/allowlist touch /var/ipfire/dns/rpz/blocklist
- # Add conf file to /etc directory
- cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d
- # create zonefiles directory for the RPZ files and add two empty RPZ
- # files to avoid a unbound config error
- # create zonefiles directory for the RPZ files and add two empty RPZ
- # files to avoid a unbound config error
mkdir -pv /etc/unbound/zonefiles
- chown -v nobody:nobody /etc/unbound/zonefiles
touch /etc/unbound/zonefiles/allow.rpz touch /etc/unbound/zonefiles/block.rpz
- # set owner for unbound related files
- chown -vR nobody:nobody \
- /var/ipfire/dns/rpz \
- /etc/unbound/zonefiles \
- /etc/unbound/local.d
# Install backup definition cp -vf $(DIR_CONF)/backup/includes/rpz /var/ipfire/backup/addons/includes/rpz
diff --git a/src/paks/rpz/uninstall.sh b/src/paks/rpz/uninstall.sh index 4fb20e127..51edaa176 100644 --- a/src/paks/rpz/uninstall.sh +++ b/src/paks/rpz/uninstall.sh @@ -27,5 +27,9 @@ make_backup ${NAME} remove_files
+# delete rpz config files. Otherwise unbound will throw error: +# "[1723428668] unbound-control[17117:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm -fv /etc/unbound/local.d/*.rpz.conf
# start unbound to load unbound config file /etc/init.d/unbound start diff --git a/src/paks/rpz/update.sh b/src/paks/rpz/update.sh index 938a93a40..fd46a185a 100644 --- a/src/paks/rpz/update.sh +++ b/src/paks/rpz/update.sh @@ -20,6 +20,24 @@ ############################################################################### # . /opt/pakfire/lib/functions.sh
+# from update.sh extract_backup_includes -./uninstall.sh -./install.sh
+# stop unbound to delete RPZ conf file +/etc/init.d/unbound stop
+# from uninstall.sh +make_backup ${NAME} +remove_files
+# delete rpz config files. Otherwise unbound will throw error: +# "unbound-control[nn:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm --verbose --force /etc/unbound/local.d/*.rpz.conf
+# from install.sh +extract_files +restore_backup ${NAME}
+# restart unbound to load config files
+/etc/init.d/unbound start
2.30.2
Jon
-- Jon Murphy jon.murphy@ipfire.org
Jon
-- Jon Murphy jon.murphy@ipfire.org
On Sep 30, 2024, at 11:27 AM, Michael Tremer michael.tremer@ipfire.org wrote:
Hello Jon,
I don’t think that we are at a point where I feel comfortable with approving this. I believe that the fundamental questions that I have raised about this have not been addressed.
I did answer all of your questions on Aug 23 except for the one concerning adding RPZ to a "global DNS system". If I missed something else I’d be happy to correct.
As stated before I did not look much at the code and I am not a point where a code review is what I need. I am at a point right now where I want to figure out what this feature is going to be and value is it going to bring our users.
This is what I am trying to do also. And this is the point of the current release: "does RPZ have value to users?"
I just once again went through the Hagezi lists to find any sense in them and I must say that this is not really what could replace the URL filter at all. It is just large lists that nobody knows where they are coming from and what they contain. I don’t have any time to invest into researching alternatives.
I understand, that is why I am trying to help.
There are multi lists that contain many items and there are individual lists that contain one category:
• Fake - Protects against internet scams, traps & fakes! • Pop-Up Ads - Protects against annoying and malicious pop-up ads! • Threat Intelligence Feeds - Increases security significantly! (Recommended) : Full - Medium - Mini - IPs • Newly Registered Domains - Favoured by threat actors to launch malicious campaigns! : 14 days - 30 days • DoH/VPN/TOR/Proxy Bypass - Prevent methods to bypass your DNS! : Full - DoH only - DoH IPs • Safesearch not supported - Prevent the use of search engines that do not support Safesearch! • Dynamic DNS - Protects against the malicious use of dynamic DNS services! • Badware Hoster - Protects against the malicious use of free host services! • Most Abused TLDs - Protects against known malicious Top Level Domains! • Anti Piracy - Protects against piracy! • Gambling - Protects against gambling content! : Full - Medium - Mini • NSFW (external) - oisd NSFW - Protects against adult content! • Native Tracker - Broadband tracker of devices, services and operating systems
And for this reason alone I don’t see why this would be interesting for our users.
There is interest. Please read the Community post when you have a moment. https://community.ipfire.org/t/i-created-a-test-version-of-a-rpz-add-on-and-...
It would really help me if you can help me understand this and help answering the questions that I have asked in the past.
What do you mean by moving *forward*? What are the next steps?
This is what I had answered on Aug 23:
What do you want to move forward with?
To implement the first phase: An RPZ add-on that is currently shell based.
The release will be similar to the Patch way below but with the fixes you suggested. Plus a few bug fixes! I’ll make the current changes and send a new Patch.
The main goal of this Phase is to measure user interest in RPZ. The metrics will be feedback within the Community.
What are the next steps?
If there is interest from the user Community, then:
• Phase 2: Input WebGUI (image shown in previous post)
• Phase 3: RPZ logs / metrics via WebGUI
Does this help answer your questions?
I’d really like to continue with this project. But it needs your blessing to keep going forward.
Jon
-Michael
On 29 Sep 2024, at 16:53, jon jon.murphy@ipfire.org wrote:
To review and approve
See: https://lists.ipfire.org/hyperkitty/list/development@lists.ipfire.org/messag...
Jon
On Sep 29, 2024, at 6:31 AM, Michael Tremer michael.tremer@ipfire.org wrote:
What are you reminding us about?
On 28 Sep 2024, at 20:34, jon jon.murphy@ipfire.org wrote:
Gentle reminder…
On Aug 23, 2024, at 4:39 PM, Jon Murphy jon.murphy@ipfire.org wrote:
- feature: added "list" action
- update: changed "cat << heredocs" to "echo > file"
- update: remove path to executables
- update: reformatted code and comments (tabs to spaces)
- update: reworded some msg_log messages
- update: change exit codes from "1" to unique exit code numbers
- bug: added check for empty allow/block config file
- bug: removed auth_zone_reload (had double reload for allow/block)
- bug: change rpz config file to `chown nobody:nobody`
- bug: change rpz config file to `chmod 644`
Signed-off-by: Jon Murphy jon.murphy@ipfire.org
config/rootfiles/packages/rpz | 1 + config/rpz/00-rpz.conf | 22 +-- config/rpz/block.rpz.conf | 7 + config/rpz/rpz-config | 292 ++++++++++++++++++---------------- config/rpz/rpz-metrics | 163 ++++++++++--------- config/rpz/rpz-sleep | 26 +-- lfs/rpz | 20 ++- src/paks/rpz/uninstall.sh | 4 + src/paks/rpz/update.sh | 22 ++- 9 files changed, 297 insertions(+), 260 deletions(-) create mode 100644 config/rpz/block.rpz.conf
diff --git a/config/rootfiles/packages/rpz b/config/rootfiles/packages/rpz index 183825362..73c3efa06 100644 --- a/config/rootfiles/packages/rpz +++ b/config/rootfiles/packages/rpz @@ -1,4 +1,5 @@ etc/unbound/local.d/00-rpz.conf +etc/unbound/local.d/block.rpz.conf etc/unbound/zonefiles etc/unbound/zonefiles/allow.rpz etc/unbound/zonefiles/block.rpz diff --git a/config/rpz/00-rpz.conf b/config/rpz/00-rpz.conf index 72c1d12e5..f005a4f2e 100644 --- a/config/rpz/00-rpz.conf +++ b/config/rpz/00-rpz.conf @@ -1,18 +1,10 @@ server:
- module-config: "respip validator iterator"
- module-config: "respip validator iterator"
rpz:
- name: allow.rpz
- zonefile: /etc/unbound/zonefiles/allow.rpz
- rpz-action-override: passthru
- rpz-log: yes
- rpz-log-name: allow
- rpz-signal-nxdomain-ra: yes
-rpz:
- name: block.rpz
- zonefile: /etc/unbound/zonefiles/block.rpz
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: block
- rpz-signal-nxdomain-ra: yes
- name: allow.rpz
- zonefile: /etc/unbound/zonefiles/allow.rpz
- rpz-action-override: passthru
- rpz-log: yes
- rpz-log-name: allow
- rpz-signal-nxdomain-ra: yes
diff --git a/config/rpz/block.rpz.conf b/config/rpz/block.rpz.conf new file mode 100644 index 000000000..605684257 --- /dev/null +++ b/config/rpz/block.rpz.conf @@ -0,0 +1,7 @@ +rpz:
- name: block.rpz
- zonefile: /etc/unbound/zonefiles/block.rpz
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: block
- rpz-signal-nxdomain-ra: yes
diff --git a/config/rpz/rpz-config b/config/rpz/rpz-config index a24a5c132..9278aa004 100644 --- a/config/rpz/rpz-config +++ b/config/rpz/rpz-config @@ -19,176 +19,186 @@ # # ###############################################################################
-# v23 - 2024-07-30 +version="2024-08-18" # v28
############### Functions ###############
msg_log () {
- /usr/bin/logger --tag "${tagName}" "$*"
- if tty --silent ; then
- echo "${tagName}:" "$*"
- fi
- logger --tag "${tagName}" "$*"
- if tty --silent ; then
echo "${tagName}:" "$*"
- fi
}
check_name () {
- local testName="${1}"
- # check for a valid name
- regex='^[a-zA-Z0-9_]+$'
- if [[ ! "${testName}" =~ $regex ]] ; then
- msg_log "error: rpz: the NAME is not valid: "${testName}". exit."
- exit 1
- fi
- local testName="${1}"
- # check for a valid name
- regex='^[a-zA-Z0-9_]+$'
- if [[ ! "${testName}" =~ $regex ]] || [[ "${testName}" == "allow" ]] || [[ "${testName}" == "block" ]]; then
msg_log "error: rpz: the NAME is not valid: \"${testName}\". exit."
exit 101
- fi
}
check_unbound_conf () {
- # check the above config files
- msg_log "info: rpz: check for errors with "unbound-checkconf""
- /usr/sbin/unbound-checkconf
- exit_code=$?
- if [[ "${exit_code}" -ne 0 ]] ; then
- msg_log "error: rpz: unbound-checkconf. exit."
- exit "${exit_code}"
- fi
- # check the above config files
- msg_log "info: rpz: check for errors with "unbound-checkconf""
- unbound-checkconf
- exit_code=$?
- if [[ "${exit_code}" -ne 0 ]] ; then
msg_log "error: rpz: unbound-checkconf found invalid configuration."
msg_log "error: rpz: In the Terminal run the command \
\"unbound-checkconf\" for more information. exit."
exit 102
- fi
}
make_rpz_file () {
- local theType="${1}" # allow or block
- theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains
- theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ
- theAction='.'
- if [[ "${theType}" =~ "allow" ]] ; then
- theAction='rpz-passthru.'
- fi
- # does a list exist?
- if [[ -s "${theList}" ]] ; then
- # drop any extra "blanks" and add "CNAME <RPZ action>." to each line
- actionList=$( /usr/bin/awk '{$1=$1};1' "${theList}" |
- /bin/sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" )
- msg_log "info: rpz: create zonefile for ${theList}"
- /bin/cat <<-EOF > "${theZoneFile}"
- ; Name: ${theType} list
- ; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z")
- ;
- ; domains with actions list
- ;
- ${actionList}
- EOF
- # reload the zone that was just updated
- zoneBase=$( basename "${theZoneFile}" )
- /usr/sbin/unbound-control auth_zone_reload -q "${zoneBase}"
- fi
- local theType="${1}" # allow or block
- theList="/var/ipfire/dns/rpz/${theType}list" # input custom list of domains
- theZoneFile="/etc/unbound/zonefiles/${theType}.rpz" # output file for RPZ
- # does a list exist?
- if ! [[ -s "${theList}" ]] ; then
msg_log "error: rpz: the ${theList} is empty. exit."
exit 103
- fi
- theAction='.'
- if [[ "${theType}" =~ "allow" ]] ; then
theAction='rpz-passthru.'
- fi
- # drop any extra "blanks" and add "CNAME <RPZ action>." to each line
- actionList=$( awk '{$1=$1};1' "${theList}" |
sed "/^[^;].*[[:alnum:]]/ s|$| CNAME ${theAction}|" )
- msg_log "info: rpz: create zonefile for ${theList}"
+echo " +; Name: ${theType} list +; Last modified: $(date "+%Y-%m-%d at %H.%M.%S %Z") +; +; domains with actions list +; +${actionList} +" > "${theZoneFile}"
}
############### Main ###############
tagName="unbound"
-theAction="${1}" # input action -theName="${2}" # input RPZ name -theURL="${3}" # input RPZ URL
-check_name "${theName}" # is this a valid name? +theAction="${1}" # input action +theName="${2}" # input RPZ name +theURL="${3}" # input RPZ URL
-rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file -rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file +rpzConfig="/etc/unbound/local.d/${theName}.rpz.conf" # output zone conf file +rpzFile="/etc/unbound/zonefiles/${theName}.rpz" # output for RPZ file
case "${theAction}" in
- # add new rpz list
- add )
- # does this config already exist? If yes, then exit
- if [[ -f "${rpzConfig}" ]] ; then
- msg_log "info: rpz: ${rpzConfig} already exists. exit"
- exit 1
- fi
- # is this a valid URL?
- regex='^https://%5B-%5B:alnum:%5D%5C+&@#/%?=~_%7C!:,.;%5D*%5B-%5B:alnum:%5D%5C+&...]'
- if ! [[ "${theURL}" =~ $regex ]] ; then
- msg_log "error: rpz: the URL is not valid: "${theURL}". exit."
- exit 1
- fi
- # create the zone config file
- msg_log "info: rpz: add config file "${theName}.rpz.conf""
- cat <<-EOF > "${rpzConfig}"
- rpz:
- name: ${theName}.rpz
- zonefile: /etc/unbound/zonefiles/${theName}.rpz
- url: ${theURL}
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: ${theName}
- rpz-signal-nxdomain-ra: yes
- EOF
- # set-up zone file
- /usr/bin/touch "${rpzFile}"
- # unbound requires these settings for rpz files
- /bin/chown nobody:nobody "${rpzFile}"
- /bin/chmod 644 "${rpzFile}"
- ;;
- # trash config file & rpz file
- remove )
- if ! [[ -f "${rpzConfig}" ]] ; then
- msg_log "info: rpz: ${rpzConfig} does not exist. exit"
- exit 1
- fi
- msg_log "info: rpz: remove config file & rpz file "${theName}""
- /bin/rm "${rpzConfig}"
- /bin/rm "${rpzFile}"
- check_unbound_conf
- ;;
- # make a new allow or block rpz file
- make )
- case "${theName}" in
- allow )
- make_rpz_file allow
- ;;
- block )
- make_rpz_file block
- ;;
- allowblock )
- make_rpz_file allow
- make_rpz_file block
- ;;
- )
- msg_log "error: rpz: the NAME is not valid: "${theName}". exit."
- exit 1
- ;;
- esac
- check_unbound_conf
- ;;
- *)
- msg_log "error: rpz: missing or incorrect parameter"
- /usr/bin/printf "Usage: rpzConfig.sh <ACTION> <NAME> <URL>\n"
- exit 1
- ;;
- # add new rpz list
- add )
- check_name "${theName}" # is this a valid name?
# does this config already exist? If yes, then exit
if [[ -f "${rpzConfig}" ]] ; then
msg_log "error: rpz: duplicate - ${rpzConfig} already exists. exit"
exit 104
fi
# is this a valid URL?
regex='^https://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
if ! [[ "${theURL}" =~ $regex ]] ; then
msg_log "error: rpz: the URL is not valid: \"${theURL}\". exit."
exit 105
fi
# create the zone config file
msg_log "info: rpz: add config file \"${theName}.rpz.conf\""
+echo "rpz:
- name: ${theName}.rpz
- zonefile: ${rpzFile}
- url: ${theURL}
- rpz-action-override: nxdomain
- rpz-log: yes
- rpz-log-name: ${theName}
- rpz-signal-nxdomain-ra: yes
+" > "${rpzConfig}"
# set-up zonefile
# create an empty rpz file
touch "${rpzFile}"
# unbound requires these settings for rpz files
chown nobody:nobody "${rpzFile}" "${rpzConfig}"
chmod 644 "${rpzFile}" "${rpzConfig}"
;;
- # trash config file & rpz file
- remove )
- check_name "${theName}" # is this a valid name?
if ! [[ -f "${rpzConfig}" ]] ; then
msg_log "error: rpz: cannot remove ${rpzConfig}, does not exist. exit"
exit 106
fi
msg_log "info: rpz: remove config file & rpz file \"${theName}\""
rm "${rpzConfig}"
rm "${rpzFile}"
check_unbound_conf
;;
- # make a new allow or block rpz file
- make )
case "${theName}" in
allow )
make_rpz_file allow
;;
block )
make_rpz_file block
;;
allowblock )
make_rpz_file allow
make_rpz_file block
;;
* )
msg_log \
"error: rpz: the NAME \"${theName}\" is not valid - \"allow\" or \"block\" only. exit."
exit 107
;;
esac
check_unbound_conf
;;
- list)
awk -F' ' '/^name:|\sname:/{ gsub(/.rpz/, "" ) ; printf $2} /\surl:|^url:/{print "="$2}' \
/etc/unbound/local.d/*.rpz.conf
exit
;;
- *)
msg_log "error: rpz: missing or incorrect parameter"
printf "Usage: rpzConfig <ACTION> <NAME> <URL>\n"
printf "Version: ${version}\n"
exit 108
;;
esac
-# reload due to the changes +# reload due to the changes msg_log "rpz: running "unbound-control reload"" -/usr/sbin/unbound-control reload +unbound-control reload exit_code=$? if [[ "${exit_code}" -ne 0 ]] ; then
- msg_log "error: rpz: unbound-control "${theName}". exit."
- exit "${exit_code}"
- msg_log "error: rpz: unbound-control "${theName}". exit."
- exit 109
fi
exit diff --git a/config/rpz/rpz-metrics b/config/rpz/rpz-metrics index 4d932726e..d154f70b9 100644 --- a/config/rpz/rpz-metrics +++ b/config/rpz/rpz-metrics @@ -19,62 +19,61 @@ # # ###############################################################################
-# v19 on 2024-07-30 +version="2024-08-16" # v20
############### Main ###############
-weeks="${1:-2}" # default to two message logs -sortBy="${2:-name}" # by name or by hits +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 message logs for N weeks +messageLogs=$( find /var/log/messages* -type f | sort --version-sort |
- head -"${weeks}" )
-# get the list of RPZ names & counts from the message log(s) +# 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 )
- zgrep --text --extended-regexp 'info: rpz: applied.* A IN$' "${logf}" |
awk '$10 ~ /\[\w*]/ { print $10 }' ;
- done | sort | uniq --count )
-# flip results and remove brackets `[` and `]` -rpzNameCount=$( /bin/echo "${rpzNameCount}" |
- /usr/bin/awk '{ print $2, $1 }' |
- /bin/sed --regexp-extended 's|^[(.*)]|\1|' )
+# flip results and remove brackets `[` and `]` +rpzNameCount=$( echo "${rpzNameCount}" |
- awk '{ print $2, $1 }' |
sed --regexp-extended 's|^\[(.*)\]|\1|' )
-# grab only names -rpzNames=$( /bin/echo "${rpzNameCount}" | /usr/bin/awk '{ print $1 }' ) +# grab only names +rpzNames=$( echo "${rpzNameCount}" | awk '{ print $1 }' )
-# get list of RPZ files -rpzFileList=$( /bin/find /etc/unbound/zonefiles -type f -iname "*.rpz" ) +# get list of RPZ files +rpzFileList=$( 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 ;' )
+# get basename of those files +rpzBaseNames=$( echo "${rpzFileList}" |
- sed 's|/etc/unbound/zonefiles/||g ; s|.rpz||g ;' )
-# add to rpzNames +# add to rpzNames rpzNames="${rpzNames}"$'\n'"${rpzBaseNames}"
-# drop duplicate names -rpzNames=$( echo "${rpzNames}" | /usr/bin/sort --unique ) +# drop duplicate names +rpzNames=$( echo "${rpzNames}" | sort --unique )
-# get line count for each RPZ -lineCount=$( /bin/echo "${rpzFileList}" | /usr/bin/xargs wc -l ) +# get line count for each RPZ +lineCount=$( echo "${rpzFileList}" | 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 comment line count and blank line count for each RPZ +commentCount=$( echo "${rpzFileList}" |
- xargs grep --count -e "^$" -e "^;" )
-# get modified date each RPZ -modDateList=$( /bin/echo "${rpzFileList}" | xargs stat -c '%.10y %n' ) +# get modified date each RPZ +modDateList=$( echo "${rpzFileList}" | xargs stat -c '%.10y %n' )
-ucListAuthZones=$( /usr/sbin/unbound-control list_auth_zones ) +ucListAuthZones=$( unbound-control list_auth_zones )
-# get width of RPZ names -pWidth=$( /bin/echo "${rpzNames}" | /usr/bin/awk '{ print $1" " }' | wc -L ) +# get width of RPZ names +pWidth=$( echo "${rpzNames}" | awk '{ print $1" " }' | wc -L ) pFormat="%-${pWidth}s %-8s %-8s %-8s %10s %12s\n"
-# print title line +# print title line printf "${pFormat}" "name" "hits" "active" "lines" "hits/line%" "last update" printf -- "--------------"
@@ -83,60 +82,60 @@ 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'
- printf -- "-" # pretend progress bar
- # get hit count
- theHits="0"
- if output=$( grep "^${theName}\s" <<< "${rpzNameCount}" ) ; then
theHits=$( echo "${output}" |
awk '{ print $2 }' )
totalHits=$(( totalHits + theHits ))
- fi
- # is this RPZ list active?
- theActive="disabled"
- if grep --quiet "^${theName}.rpz" <<< "${ucListAuthZones}"
- then
theActive="enabled"
- fi
- # get line count
- theLines="n/a"
- hitsPerLine="0"
- if output=$( grep --fixed-strings "/${theName}.rpz" <<< "${lineCount}" ) ; then
theLines=$( echo "${output}" | 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=$( grep --fixed-strings "/${theName}.rpz" <<< "${modDateList}" ) ; then
theModDate=$( echo "${output}" | 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"
- 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"
- 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"
- 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 }'
+# remove blank lines, sort, print as columns +echo "${theResults}" |
- awk '!/^[[:space:]]*$/' |
- sort "${sortArg[@]}" |
- 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}" "" "" diff --git a/config/rpz/rpz-sleep b/config/rpz/rpz-sleep index eeef1174a..dd3603599 100644 --- a/config/rpz/rpz-sleep +++ b/config/rpz/rpz-sleep @@ -19,38 +19,38 @@ # # ###############################################################################
-# v04 on 2024-07-05 +version="2024-08-16" # v05
############### Functions ###############
-# send message to message log +# send message to message log msg_log () {
- /usr/bin/logger --tag "${tagName}" "$*"
- if /usr/bin/tty --silent ; then
- echo "${tagName}:" "$*"
- fi
- logger --tag "${tagName}" "$*"
- if tty --silent ; then
echo "${tagName}:" "$*"
- fi
}
############### Main ###############
tagName="unbound"
-sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes) +sleepTime="${1:-5m}" # default to sleep for 5m (5 minutes)
-zoneList=$( /usr/sbin/unbound-control list_auth_zones | /usr/bin/awk '{print $1}' ) +zoneList=$( unbound-control list_auth_zones | awk '{print $1}' )
for zone in ${zoneList} ; do
- /usr/bin/printf "disable ${zone}\t"
- /usr/sbin/unbound-control rpz_disable "${zone}"
- printf "disable ${zone}\t"
- unbound-control rpz_disable "${zone}"
done
msg_log "info: rpz: disabled all zones for ${sleepTime}"
-/bin/sleep "${sleepTime}" +sleep "${sleepTime}"
for zone in ${zoneList} ; do
- /usr/bin/printf "enable ${zone}\t"
- /usr/sbin/unbound-control rpz_enable "${zone}"
- printf "enable ${zone}\t"
- unbound-control rpz_enable "${zone}"
done
msg_log "info: rpz: enabled all zones" diff --git a/lfs/rpz b/lfs/rpz index 73f6f2b1b..16d1d0803 100644 --- a/lfs/rpz +++ b/lfs/rpz @@ -62,25 +62,31 @@ $(TARGET) : @$(PREBUILD) @rm -rf $(DIR_APP)
- # install RPZ scripts
- # install RPZ scripts
install -v -m 755 \ $(DIR_CONF)/rpz/{rpz-config,rpz-metrics,rpz-sleep} -t /usr/sbin
- # Add conf file to /etc directory
- cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d
- cp -vf $(DIR_CONF)/rpz/block.rpz.conf /etc/unbound/local.d
# Install settings folder and two empty files mkdir -pv /var/ipfire/dns/rpz touch /var/ipfire/dns/rpz/allowlist touch /var/ipfire/dns/rpz/blocklist
- # Add conf file to /etc directory
- cp -vf $(DIR_CONF)/rpz/00-rpz.conf /etc/unbound/local.d
- # create zonefiles directory for the RPZ files and add two empty RPZ
- # files to avoid a unbound config error
- # create zonefiles directory for the RPZ files and add two empty RPZ
- # files to avoid a unbound config error
mkdir -pv /etc/unbound/zonefiles
- chown -v nobody:nobody /etc/unbound/zonefiles
touch /etc/unbound/zonefiles/allow.rpz touch /etc/unbound/zonefiles/block.rpz
- # set owner for unbound related files
- chown -vR nobody:nobody \
- /var/ipfire/dns/rpz \
- /etc/unbound/zonefiles \
- /etc/unbound/local.d
# Install backup definition cp -vf $(DIR_CONF)/backup/includes/rpz /var/ipfire/backup/addons/includes/rpz
diff --git a/src/paks/rpz/uninstall.sh b/src/paks/rpz/uninstall.sh index 4fb20e127..51edaa176 100644 --- a/src/paks/rpz/uninstall.sh +++ b/src/paks/rpz/uninstall.sh @@ -27,5 +27,9 @@ make_backup ${NAME} remove_files
+# delete rpz config files. Otherwise unbound will throw error: +# "[1723428668] unbound-control[17117:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm -fv /etc/unbound/local.d/*.rpz.conf
# start unbound to load unbound config file /etc/init.d/unbound start diff --git a/src/paks/rpz/update.sh b/src/paks/rpz/update.sh index 938a93a40..fd46a185a 100644 --- a/src/paks/rpz/update.sh +++ b/src/paks/rpz/update.sh @@ -20,6 +20,24 @@ ############################################################################### # . /opt/pakfire/lib/functions.sh
+# from update.sh extract_backup_includes -./uninstall.sh -./install.sh
+# stop unbound to delete RPZ conf file +/etc/init.d/unbound stop
+# from uninstall.sh +make_backup ${NAME} +remove_files
+# delete rpz config files. Otherwise unbound will throw error: +# "unbound-control[nn:0] error: connect: Connection refused for 127.0.0.1 port 8953" +/bin/rm --verbose --force /etc/unbound/local.d/*.rpz.conf
+# from install.sh +extract_files +restore_backup ${NAME}
+# restart unbound to load config files
+/etc/init.d/unbound start
2.30.2
Jon
-- Jon Murphy jon.murphy@ipfire.org
Jon
-- Jon Murphy jon.murphy@ipfire.org
Jon