88VERSION=' $Id$'
99
1010# shellcheck disable=SC2034 # used by Makefile
11- RELEASE=' 1.6 .0'
11+ RELEASE=' 1.7 .0'
1212
1313SELF=" $( basename " $0 " ) "
1414
1515function displayVersion() {
1616 if [[ " $VERSION " =~ ^' $' ' Id: ' [[:xdigit:]]{24}([[:xdigit:]]{4})([[:xdigit:]]{4})([[:xdigit:]]{4})([[:xdigit:]]{4})' $' $ ]]; then
1717 printf " $SELF version %s-%s-%s-%s\n%*s release %s\n" \
1818 " ${BASH_REMATCH[-4]} " " ${BASH_REMATCH[-3]} " " ${BASH_REMATCH[-2]} " " ${BASH_REMATCH[-1]} " " ${# SELF} " " " " $RELEASE "
19- exit 0
19+ return 0
2020 fi
2121 echo " $SELF version '$VERSION ' - format error"
2222 exit 1
3939
4040BlackList=" BlackList"
4141Chain=" INPUT"
42+ Chain6=
4243DateFormat=" +%a %d-%b-%Y %T %Z"
4344
4445# NOTE: The help text below is automagically inserted into README.md
6869 -L List currently blocked IP addresses and last seen time (default)
6970 -S file Save current addresses as a script. (use - for stdout)
7071 -a With -S, add to existing output file
72+ -r With -S, save in raw format (just IP address list, e.g. for BlockCountries)
7173 -T tps Use tps as the jiffys/sec (only if /boot/config-<kernel> is not available.
7274 -t Estimate -T
73- -X Disable ipblock and remove its rule. Does not fluah list.
75+ -X Disable ipblock and remove its rule. May not fluah list.
7476 -V Display version
7577
7678 -D fmt Date format (strftime) (Default is '%a %d-%b-%Y %T %Z'), null for ctime
7779
7880 -C:chain Specify chain to hook (default is INPUT)
81+ -c:chain Specify chain for IPv6 hook (default is same name as IPv4)
7982 -N:table Recent table name that maintains list. (Default is BlackList)
8083 IPv6 adds '6' to the specified name (Thus, IPv6 default is BlackList6)
8184```
8285EOF
8386 cat << EOF
8487
88+ Most options should be placed in ${SELF} .conf, making use very simple.
89+
90+ The most common usage is
91+
92+ $SELF address
93+
8594If neither -4 nor -6 is specified:
8695 If a numeric address is specified, the address family is used.
8796 Otherwise, the default is -4
8897
89- Options -L and -S ignore - 4 & -6; they access all tables present.
98+ Option -L ignores - 4 & -6; it accesses all tables present.
9099
91100Option -T is only required when the kernel configuration file is not mounted on /boot, as
92101happens with some VPS providers. The value is the jiffies (ticks) per second of
139148APPEND=
140149TICKS=
141150NOHOST=
151+ RAW=
142152
143153if [ -f " /sys/module/ipt_recent/parameters/ip_list_tot" ]; then
144154 MAXENT=" $( cat /sys/module/ipt_recent/parameters/ip_list_tot) "
148158 MAXENT=100
149159fi
150160
151- DD=
152- while getopts " 46AC:dD:hFLN:nRaS:tT:vXV-:" opt; do
161+ while getopts " 46AC:c:dD:hFLN:nrRaS:tT:vXV-:" opt; do
153162 case $opt in
154163 4)
155164 IPV=" 4"
@@ -160,6 +169,9 @@ while getopts "46AC:dD:hFLN:nRaS:tT:vXV-:" opt; do
160169 C)
161170 Chain=" $OPTARG "
162171 ;;
172+ c)
173+ Chain6=" $OPTARG "
174+ ;;
163175 A)
164176 ACTION=" add"
165177 ;;
@@ -206,6 +218,9 @@ while getopts "46AC:dD:hFLN:nRaS:tT:vXV-:" opt; do
206218 a)
207219 APPEND=" y"
208220 ;;
221+ r)
222+ RAW=" y"
223+ ;;
209224 v)
210225 V=" y"
211226 ;;
@@ -214,10 +229,12 @@ while getopts "46AC:dD:hFLN:nRaS:tT:vXV-:" opt; do
214229 ;;
215230 V)
216231 displayVersion
232+ exit 0
217233 ;;
218234 -)
219235 if [ " $OPTARG " == " version" ]; then
220236 displayVersion
237+ exit 0
221238 elif [ " $OPTARG " == ' help' ]; then
222239 displayHelp
223240 else
@@ -254,17 +271,16 @@ if [ -z "$IPV" ]; then
254271 fi
255272 fi
256273fi
257- if [ " $IPV " == ' 4' ]; then
258- ProcMatch=" /proc/net/ip_tables_matches"
259- else
260- ProcMatch=" /proc/net/ip6_tables_matches"
261- fi
262274
263275IPT=" iptables"
264276BlackBase=" $BlackList "
265277if [ " $IPV " == " 6" ]; then
266278 IPT=" ip6tables"
267279 BlackList=" ${BlackList} 6"
280+ ProcMatch=" /proc/net/ip6_tables_matches"
281+ [ -n " $Chain6 " ] && Chain=" $Chain6 "
282+ else
283+ ProcMatch=" /proc/net/ip_tables_matches"
268284fi
269285
270286if ! command -v " $IPT " > /dev/null 2>&1 ; then
288304
289305# shellcheck disable=SC2086 # RULE needs word splitting
290306if ! $IPT -C $RULE > /dev/null 2>&1 ; then
291- if $IPT -I $RULE ; then
307+ if [[ " $ACTION " =~ ^(flush| list| remove| save)$ ]]; then
308+ [ -n " $V " ] && echo " Not installed for IPv$IPV "
309+ exit 0
310+ elif $IPT -I $RULE ; then
292311 [ -n " $V " ] && echo " Installed IPv$IPV input rule"
293312 [ -n " $DEBUG " ] && echo " $IPT -I $RULE "
294313 else
351370if [ " $ACTION " == " save" ]; then
352371 export LC_ALL=" C"
353372
354- function save () {
355- cat << EOF
373+ function savelines() {
374+ local v=" $1 " nohdr=" $2 " n=0
375+
376+ if [ -n " $RAW " ]; then
377+ while IFS= read -r IP; do
378+ echo " $IP "
379+ (( ++ n))
380+ done
381+ [ -z " $nohdr " ] && echo " # Count = $n "
382+ return 0;
383+ fi
384+
385+ while IFS= read -r IP; do
386+ if [[ $(( n++ % 16 )) == 0 ]]; then
387+ printf " \n%s %s %s" " $PROG " " $v " " $IP "
388+ else
389+ printf " %s" " $IP "
390+ fi
391+ done
392+ [[ $(( n % 16 )) != 0 ]] && printf " \n"
393+ [ -z " $nohdr " ] && echo " # Count = $n "
394+ return 0
395+ }
396+ function saveHdr () {
397+ if [ -z " $RAW " ]; then
398+ cat << EOF
356399#!/bin/bash
357400
358- # Auto-generated by $SELF V$VERSION
401+ EOF
402+ fi
403+ cat << EOF
404+ # Auto-generated by $SELF $( displayVersion | head -n1) on $( date ' +%d-%b-%Y %T' )
359405
360406EOF
407+ }
408+ function save () {
409+ local nohdr=" $1 "
410+ [ -z " $nohdr " ] && saveHdr
361411 PROG=" $( readlink -en " $0 " ) "
362- if [ -f " $ProcRecent /$BlackBase " ]; then
412+ if [ " $IPV " == " 4 " ] && [ -f " $ProcRecent /$BlackBase " ]; then
363413 # shellcheck disable=SC2002 # Redirecting input doesn't work here
364414 ( cat " $ProcRecent /$BlackBase " | while IFS= read -r LINE; do
365415 sed -e' s/^src=\([^ ]*\) .*$/\1/' <<< " $LINE"
366416 done ) |
367- sort -u -t . -k1,1n -k2,2n -k3,3n -k4,4n |
368- while IFS= read -r SRT; do
369- echo " $PROG -4 $SRT "
370- done
417+ sort -u -t . -k1,1n -k2,2n -k3,3n -k4,4n | savelines -4 " $nohdr "
371418 fi
372419
373- if [ -f " $ProcRecent /${BlackBase} 6" ]; then
420+ if [ " $IPV " == " 6 " ] && [ -f " $ProcRecent /${BlackBase} 6" ]; then
374421 # shellcheck disable=SC2002 # Redirecting input doesn't work here
375422 ( cat " $ProcRecent /${BlackBase} 6" | while IFS= read -r LINE; do
376423 sed -e' s/^src=\([^ ]*\) .*$/\1/' <<< " $LINE"
377424 done ) |
378- sort -u -t : -f -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 -k6,6 -k7,7 -k8,8 |
379- while IFS= read -r SRT; do
380- echo " $PROG -6 $SRT "
381- done
425+ sort -u -t : -f -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 -k6,6 -k7,7 -k8,8 | savelines -6 " $nohdr "
382426 fi
383- echo " # EOF"
427+ [ -z " $nohdr " ] && echo " # EOF"
384428 }
385- if [ " $SCRIPT " = ' -' ]; then
386- save
429+ if [ " ${ SCRIPT} " = ' -' ]; then
430+ save | grep -vP ' ^# Count = ([0-9]+).*$ '
387431 else
388- if [ -n " $APPEND " ] && [ -f " $SCRIPT " ]; then
389- rm -f " $SCRIPT " .tmp
390- mv " $SCRIPT " " $SCRIPT " .tmp
391- cat > " $SCRIPT " .tmph << EOF
392- #!/bin/bash
393-
394- # Auto-generated by $SELF V$VERSION
395-
396- EOF
397- save >> " $SCRIPT " .tmp
398- grep -vh ' ^#' " $SCRIPT " .tmp | sort -u | cat " $SCRIPT " .tmph - > " $SCRIPT "
399- echo " # EOF" >> " $SCRIPT "
400- rm -f " $SCRIPT " .tmp " $SCRIPT " .tmph
432+ if [ -n " $APPEND " ] && [ -f " ${SCRIPT} " ]; then
433+ rm -f " ${SCRIPT} .tmp"
434+ sed " ${SCRIPT} " -Ee" /^#/d;/^\$ /d;s,^[^ ]*/?${SELF} ( +-[46])? *,,;;s/ /\n/g;" > " ${SCRIPT} .tmp"
435+ saveHdr > " ${SCRIPT} "
436+ RAW=" y" save ' nohdr' >> " ${SCRIPT} .tmp"
437+ if [ " $IPV " == " 4" ]; then
438+ sort -u -t . -k1,1n -k2,2n -k3,3n -k4,4n " ${SCRIPT} .tmp" | savelines -4 >> " ${SCRIPT} "
439+ else
440+ sort -u -t : -f -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 -k6,6 -k7,7 -k8,8 " ${SCRIPT} .tmp" | savelines -6 >> " ${SCRIPT} "
441+ fi
442+ echo " # EOF" >> " ${SCRIPT} "
443+ rm -f " ${SCRIPT} .tmp"
444+ else
445+ save > " ${SCRIPT} "
446+ fi
447+ if [ -z " $RAW " ]; then
448+ chmod +x " ${SCRIPT} "
401449 else
402- save > " $ SCRIPT"
450+ chmod -x " ${ SCRIPT} "
403451 fi
404- chmod +x " $SCRIPT "
405- [ -n " $V " ] && echo " Wrote $( readlink -en " $SCRIPT " ) "
406- CNT= " $( grep -c -- ' -4 \| -6 ' " $SCRIPT " ) "
452+ [ -n " $V " ] && echo " Wrote $( readlink -en " ${ SCRIPT} " ) "
453+ CNT= " $( sed " ${SCRIPT} " -nEe ' s/^# Count = ([0-9]+).*$/\1/p ' ) "
454+ sed -i " ${SCRIPT} " -Ee ' /^# Count = ([0-9]+).*$/d '
407455 if [ " $CNT " -gt " $MAXENT " ]; then
408- echo " $( readlink -en " $SCRIPT " ) lists $CNT addresses, but only $MAXENT will be retained. See -h for more information."
456+ echo " $( readlink -en " ${ SCRIPT} " ) lists $CNT addresses, but only $MAXENT will be retained. See -h for more information."
409457 exit 2
410458 fi
411459 fi
@@ -490,7 +538,7 @@ if [ "$ACTION" == "list" ]; then
490538 fi
491539 [ -n " $DEBUG " ] && echo " IP: $IP NOW: $NOW UP: $UPT TICKS: $TICKS SEEN: $SEEN SSE: $SSE DATE: $DATE$HN "
492540
493- echo " $IP ${Dots: 0 : $(( ${ # Dots} - ${ # IP} )) } $DATE$HN "
541+ echo " $IP ${Dots: ${ # IP} } $DATE$HN "
494542 done
495543
496544 if [ -n " $V " ]; then
0 commit comments