From 97bd5b000af1176d69223184cbf29a802b3dc6b3 Mon Sep 17 00:00:00 2001 From: sceox Date: Sun, 6 Sep 2020 15:20:12 -0700 Subject: [PATCH] run with least privilege, support pf * run the service as a low privilege user and use sudo/doas to add the block rules * add support for pf firewall * write documentation for the above * add abort function for handling error logging and exit cleanup --- README.md | 30 ++++++++++++++++++++++++-- forumspam.sh | 60 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index aef6620..8cdbea9 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,35 @@ To deploy: * modify the configuration variables in the scripts * copy the scripts to `/usr/local/bin` +* create the user + + useradd -s /sbin/nologin _forumspam + +* if using `pf`: + * create appropriate permissions for the file: + + install -m 640 -o _forumspam -g wheel /dev/null /etc/pf-forumspam.txt + + * add the following to `/etc/pf.conf`, preferably high up in the ruleset: + + table persist file "/etc/pf-forumspam.txt" + block in quick on egress from + block out quick on egress to + +* set up sudo or doas: + * for doas: + * add the following to `/etc/doas.conf`: + + permit nopass _forumspam cmd pfctl args -nf /etc/pf.conf + permit nopass _forumspam cmd pfctl args -t forumspam -T replace -f /etc/pf-forumspam.txt + + * for sudo: + * add to your sudo config file: + `Cmnd_Alias FIREWALL = /usr/sbin/ufw, /sbin/iptables` + and `_forumspam ALL = NOPASSWD: FIREWALL` + * register `q2a_usercheck.sh` as a systemd unit or rc script TODO: * also check against [botscout](http://botscout.com/api.htm) -* add support for pf -* add support for iptables +* give the scripts more sensible names diff --git a/forumspam.sh b/forumspam.sh index 75e4b68..56d868f 100755 --- a/forumspam.sh +++ b/forumspam.sh @@ -2,31 +2,53 @@ # API reference: https://www.stopforumspam.com/usage +# user configuration area - change as needed +ostype="bsd" # allowed options are bsd, linux +logf=/var/log/forumspam.log +limit=0 # number of violations allowed before blocking the ip + +case "$ostype" in + bsd) + getroot="doas" + fw_cmd="pfctl" + ;; + linux) + getroot="sudo" + fw_cmd="ufw" + ;; +esac + +abort() { + echo `date` 'error:' $* >> $logf + rm $repl + exit 1 +} +block_ip() { + case "$fw_cmd" in + ufw) + if [ "$getroot" ufw deny from $ip >/dev/null 2>>$logf ]; then + echo `date` blocked ip $ip with freq $freq >> $logf + else + abort "failed to block ip $ip" + fi + ;; + pfctl) + "$getroot" pfctl -nf /etc/pf.conf || abort "pf config check failed" # Ensure proposed changes are valid before reloading table + "$getroot" pfctl -t forumspam -T replace -f /etc/pf-forumspam.txt + ;; + esac +} + +# we ignore all arguments except the first ip=$1 repl=`mktemp` -logf=/var/log/forumspam.log - curl 'http://api.stopforumspam.org/api?ip='$ip 2>/dev/null > $repl if ! grep -q '' $repl; then - echo error failed to query stopforumspam api >> $logf - rm $repl - exit 1 -fi -if ! grep -q 'yes' $repl; then - rm $repl - exit 0 + abort 'error failed to query stopforumspam api' fi freq=`grep '' $repl | sed 's///; s!!!'` -if [ "$freq" -ge 1 ]; then - if ufw deny from $ip >/dev/null 2>>$logf; then - echo `date` blocked ip $ip with freq $freq >> $logf - rm $repl - exit 0 - else - echo `date` "error failed to block ip $ip" >> $logf - rm $repl - exit 2 - fi +if grep -q 'yes' $repl && [ "$freq" -gt "$limit" ]; then + block_ip "$ip" fi rm $repl