Skip to content

Commit 9ebcaa1

Browse files
committed
Speed up restore, allow IPv6 chains to have different name
- When writing restore script from save, group 16/line for restore speed - Save now only includes the selected address family (-4 or -6) - Add raw format to save (e.g. to feed to BlockCountries for permanence) - Don't install rule if action is flush, list, remove, or save (NOP) - Optimize list, slightly - Yet another stab at detecting dirty working directory - Install .conf as .conf.new if one exists (instead of not installing)
1 parent 81d91e5 commit 9ebcaa1

7 files changed

Lines changed: 143 additions & 62 deletions

File tree

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.git* export-ignore
2+
Makefile export-subst ident
23
ipblock export-subst ident

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
*.sig
88
ipblock-*
99
*.tar *.tar.gz *.tar.xz *tar.lzop *.tar.lzma *.tar.Z *.tar.zst *.tar.bz *.tar.bz2
10+
.tagged

Makefile

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Copyright (C) 2023 Timothe Litt litt at acm ddot org
22

3+
# $Id$
4+
35
# Install targets - can override on command line
46

57
# Note that DESTDIR is supported for staging environments
@@ -74,6 +76,14 @@ ipblock$(man1ext) : README.md ipblock Makefile
7476
$(SED) -e's,^`ipblock -h` for complete help$$,./ipblock -h,e' $< | \
7577
$(LOWDOWN) -s -t man --parse-codeindent -M "title=ipblock" -M "date=$$(date -r ipblock +%d-%b-%Y)" -Msection=8 -o $@ -
7678

79+
.PHONY : viewreadme viewman
80+
81+
viewreadme : README.md
82+
@LANG=C $(LOWDOWN) -s -t term --parse-codeindent $< | less
83+
84+
viewman : ipblock$(man1ext)
85+
@LANG=C less $<
86+
7787
# Make tarball kits - various compressions
7888

7989
.PHONY : dist unsigned-dist signed-dist
@@ -112,7 +122,7 @@ install_dirs := $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) $(DESTDIR)$(confdir)
112122
install : ipblock ipblock$(man1ext) config/ipblock.conf installdirs
113123
$(INSTALL_PROGRAM) ipblock $(DESTDIR)$(bindir)/ipblock
114124
$(INSTALL_DATA) ipblock$(man1ext) $(DESTDIR)$(man1dir)/ipblock$(man1ext)
115-
-if [ -f "$(confdir)/ipblock.conf" ]; then true ; else $(INSTALL_DATA) config/ipblock.conf $(DESTDIR)$(confdir)/ipblock.conf; fi
125+
-if [ -f "$(confdir)/ipblock.conf" ]; then $(INSTALL_DATA) config/ipblock.conf $(DESTDIR)$(confdir)/ipblock.conf.new ; else $(INSTALL_DATA) config/ipblock.conf $(DESTDIR)$(confdir)/ipblock.conf; fi
116126
@echo ""
117127
@echo "Please read 'man 1 ipblock' before using the command'"
118128

@@ -166,7 +176,7 @@ tag : .tagged
166176

167177
.tagged : $(shell git ls-tree --full-tree --name-only -r HEAD) unsigned-dist
168178
@if git ls-files --others --exclude-standard --directory --no-empty-directory --error-unmatch -- ':/*' >/dev/null 2>/dev/null || \
169-
[ -n "$$(git diff --stat)" ]; then \
179+
[ -n "$$(git diff --name-only)$$(git diff --name-only --staged)" ]; then \
170180
echo " *** Not tagging V$(kitversion) because working directory is dirty"; echo ""; false ;\
171181
elif [ "$(strip $(gittag))" == "V$(kitversion)" ]; then \
172182
echo " *** Not tagging because V$(kitversion) already exists"; \

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@ Options, including the desired chain, should be specified in the configuration f
3333
`ipblock -h` for complete help
3434

3535
## Installation
36-
Download the latest `Vn.m-Release` tarball using the `tar.gz` link at [GitHub](https://github.com/tlhackque/ipblock/releases).
36+
Download the latest `ipblock-n.m.o-Release` tarball and signature using
37+
the `tar.gz` or `tar.xz` and `.sig` links at
38+
[GitHub](https://github.com/tlhackque/ipblock/releases).
3739

38-
- Do **not** select the `.zip` file, as it does not preserve file permissions.
39-
- Do **NOT** use the **Clone or download** link on the main `ipblock` page, as it provides a `.zip` file.
40+
- Do **NOT** use the **Clone or download** link on the main `ipblock` page.
41+
- Building or installing from source requires `lowdown`
4042

41-
Unpack the `tar.gz`:
42-
tar -xzf ipblock&lt;n&gt;.&lt;m&gt;-Release.tar.gz
43+
Verify and npack the `tar.gz`:
44+
gpg --verify ipblock&lt;n&gt;.&lt;m&gt;-Release.tar.gz.sig && \\
45+
tar -xzf ipblock&lt;n&gt;.&lt;m&gt;-Release.tar.gz
4346

4447
This will create a subdirectory named ipblock-&lt;version&gt;.
4548

config/ipblock.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
# If you leave -C at the default, "INPUT", the ipblock rule will
2222
# supersede any protection that you hav established, so don't.
2323
#
24+
# The name of the IPv6 chain is defaulted to be the same as the IPv4 chain's.
25+
# If they differ, specify the IPv6 chain name with -c (lowercase).
26+
# Otherwise, -C will be used for both.
27+
#
2428
# See ipblock -h for more information.
2529

2630
#OPTIONS="-C mychain"

ipblock

Lines changed: 95 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
VERSION='$Id$'
99

1010
# shellcheck disable=SC2034 # used by Makefile
11-
RELEASE='1.6.0'
11+
RELEASE='1.7.0'
1212

1313
SELF="$(basename "$0")"
1414

1515
function 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
@@ -39,6 +39,7 @@ fi
3939

4040
BlackList="BlackList"
4141
Chain="INPUT"
42+
Chain6=
4243
DateFormat="+%a %d-%b-%Y %T %Z"
4344

4445
# NOTE: The help text below is automagically inserted into README.md
@@ -68,25 +69,33 @@ EOF
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
```
8285
EOF
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+
8594
If 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
91100
Option -T is only required when the kernel configuration file is not mounted on /boot, as
92101
happens with some VPS providers. The value is the jiffies (ticks) per second of
@@ -139,6 +148,7 @@ V=
139148
APPEND=
140149
TICKS=
141150
NOHOST=
151+
RAW=
142152

143153
if [ -f "/sys/module/ipt_recent/parameters/ip_list_tot" ]; then
144154
MAXENT="$(cat /sys/module/ipt_recent/parameters/ip_list_tot)"
@@ -148,8 +158,7 @@ else
148158
MAXENT=100
149159
fi
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
256273
fi
257-
if [ "$IPV" == '4' ]; then
258-
ProcMatch="/proc/net/ip_tables_matches"
259-
else
260-
ProcMatch="/proc/net/ip6_tables_matches"
261-
fi
262274

263275
IPT="iptables"
264276
BlackBase="$BlackList"
265277
if [ "$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"
268284
fi
269285

270286
if ! command -v "$IPT" >/dev/null 2>&1 ; then
@@ -288,7 +304,10 @@ fi
288304

289305
# shellcheck disable=SC2086 # RULE needs word splitting
290306
if ! $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
@@ -351,61 +370,90 @@ fi
351370
if [ "$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
360406
EOF
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

Comments
 (0)