Skip to content

Commit

Permalink
Cleanup, deal with VPS that don't expose kernel config in /boot
Browse files Browse the repository at this point in the history
Remove restriction that spaces in options must be underscores; let
them be single quoted instead.  (Keep underscore translation for
compatibility, but don't document.)

Make shellcheck happy (ier).
Allow CONFIG_HZ to be specified for systems that don't provide
the kernel config.

Provide an estimation function that can determine CONFIG_HZ.

Requires installation of 'bc' to overcome bash arithmetic limitations.

For some reason, the high nibble of timestamps seems to be non-zero,
which makes resolving timestamps impossible.  Mask those bits (though
systems with very long uptimes may legitimately use them...)

Try to diagnose failures installing the iptables rule.

Add -n to suppress hostname lookups for -L (speed)

If both /etc/default and /etc/sysconfig have .conf files,
only use /etc/default

Document how to avoid self-lockout.

Switch to auto-versioning.  Separate release from version.

Add a Makefile for install, man page, uninstall
  • Loading branch information
tlhackque committed Jan 17, 2023
1 parent 91a389a commit 417d14e
Show file tree
Hide file tree
Showing 7 changed files with 723 additions and 95 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.git* export-ignore
ipblock export-subst ident
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
*~
*#
.#*
*.swp
*.bak
*.orig
*.sig
ipblock-*
*.tar *.tar.gz *.tar.xz *tar.lzop *.tar.lzma *.tar.Z *.tar.zst *.tar.bz *.tar.bz2
171 changes: 171 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# Copyright (C) 2023 Timothe Litt litt at acm ddot org

# Install targets - can override on command line

# Note that DESTDIR is supported for staging environments

prefix := /usr/local
datarootdir := $(prefix)/share
mandir := $(datarootdir)/man
man1dir := $(mandir)/man1
manext := .1
man1ext := .1
exec_prefix := $(prefix)
bindir := $(exec_prefix)/bin
confdir := $(shell if [ -f "/etc/default/ipblock.conf" ]; then echo "/etc/default"; \
elif [ -f "/etc/sysconfig/ipblock.conf" ] || ! [ -d "/etc/default" ]; \
then echo "/etc/sysconfig"; \
else echo "/etc/default"; fi)
INSTALL := install
INSTALL_PROGRAM := $(INSTALL)
INSTALL_DATA := $(INSTALL) -m 644

# Specify key="deadbeef" or key="deadbeef beeffeed" on command line (else default)
GPG := gpg

SHELL := bash
SED := sed

# https://kristaps.bsd.lv/lowdown/ - used to build man page.
LOWDOWN := lowdown

# Usage:
# See INSTALL

# Extract version from ipblock source

kitversion := $(shell $(SED) -nEe"s/^RELEASE='([^']+)'.*$$/\1/p" ipblock)
kitname := ipblock-$(kitversion)
kitowner := 0:0

# location if command is installed

IPBLOCK := $(strip $(shell command -v ipblock))

# If in a Git working directory and the git command is available,
# get the last tag in case making a distribution.

ifneq "$(strip $(shell [ -d '.git' ] && echo 'true' ))" ""
gitcmd := $(shell command -v git)
ifneq "$(strip $(gitcmd))" ""
gittag := $(shell git tag | sort -t. -k 1.2,1n -k 2,2n -k 3,3n | tail -n1)
endif
endif

# file types from which tar can infer compression, if tool is installed

# kittypes = gz xz lzop lz lzma Z zst bz bz2

# kittypes to build

kittypes := gz xz

# Files to package

#kitfiles := INSTALL README.md LICENSE Makefile ipblock config/ipblock.conf ipblock$(manext)
kitfiles := README.md LICENSE Makefile ipblock config/ipblock.conf ipblock$(manext)

.PHONY : all

all : ipblock$(man1ext)

# Compilations: man page from README and help

ipblock$(man1ext) : README.md ipblock Makefile
$(SED) -e's,^`ipblock -h` for complete help$$,./ipblock -h,e' $< | \
$(LOWDOWN) -s -t man --parse-codeindent -M "title=ipblock" -M "date=$$(date -r ipblock +%d-%b-%Y)" -Msection=8 -o $@ -

# Make tarball kits - various compressions

.PHONY : dist unsigned-dist signed-dist

dist : signed-dist

signed-dist : unsigned-dist $(foreach type,$(kittypes),$(kitname).tar.$(type).sig)

unsigned-dist : $(foreach type,$(kittypes),$(kitname).tar.$(type))

# Tarball build directory

$(kitname)/% : %
@mkdir -p $(dir $@)
@-chown $(kitowner) $(dir $@)
cp -p $< $@
@-chown $(kitowner) $@

# Clean up after builds

.PHONY : clean

clean:
rm -rf $(kitname) $(foreach type,$(kittypes),$(kitname).tar.$(type){,.sig})

# Install program and doc

.PHONY : install

install_dirs := $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) $(DESTDIR)$(confdir)

install : ipblock ipblock$(man1ext) config/ipblock.conf installdirs
$(INSTALL_PROGRAM) ipblock $(DESTDIR)$(bindir)/ipblock
$(INSTALL_DATA) ipblock$(man1ext) $(DESTDIR)$(man1dir)/ipblock$(man1ext)
-if [ -f "$(confdir)/ipblock.conf" ]; then true ; else $(INSTALL_DATA) config/ipblock.conf $(DESTDIR)$(confdir)/ipblock.conf; fi
@echo ""
@echo "Please read 'man 1 ipblock' before using the command'"

# un-install

.PHONY : uninstall

# uninstall should have the command in $(bindir)...
# uninstall may encounter no IPvX rule, no chain. So flush and disable are best effort.
uninstall :
@-if ! [ -x "$(DESTDIR)$(bindir)/ipblock" ]; then \
echo "The ipblock command is not in '$(DESTDIR)$(bindir)'" >&2 ; \
echo "This uninstall will not find it and may not do what you expect." >&2 ; \
if [ -n "$(IPBLOCK)" ] && [ "$(IPBLOCK)" != "$(DESTDIR)$(bindir)/ipblock" ]; then \
echo "Did you forget to set 'prefix=$(dir $(IPBLOCK))'?" >&2 ; \
fi ; \
fi
-$(DESTDIR)$(bindir)/ipblock -4F >/dev/null 2>&1 || true
-$(DESTDIR)$(bindir)/ipblock -4X >/dev/null 2>&1 || true
-$(DESTDIR)$(bindir)/ipblock -6F >/dev/null 2>&1 || true
-$(DESTDIR)$(bindir)/ipblock -6X >/dev/null 2>&1 || true
-rm -f "$(DESTDIR)$(bindir)/ipblock"
-rm -f "$(DESTDIR)$(man1dir)/ipblock$(man1ext)"
@-[ -f "$(DESTDIR)$(confdir)/ipblock.conf" ] && echo "Not deleting $(DESTDIR)$(confdir)/ipblock.conf in case you want to reinstall later"

# create install directory tree (especially when staging)

installdirs : $(install_dirs)
$(INSTALL) -d $(install_dirs)

# rules for making tarballs - $1 is file type that implies compression

define make_tar =

%.tar.$(1) : $$(foreach f,$$(kitfiles), %/$$(f))
tar -caf $$@ $$^
@-chown $(kitowner) $$@
ifneq ($(strip $(gitcmd)),)
@if git ls-files --others --exclude-standard --directory --no-empty-directory --error-unmatch -- ':/*' >/dev/null 2>/dev/null || \
! git diff-index --quiet HEAD || [ -n "$$$$(git diff --stat)" ]; then \
echo " *** Not tagging V$(kitversion) because working directory is dirty"; echo ""; \
elif [ "$(strip $(gittag))" == "V$(kitversion)" ]; then \
echo " *** Not tagging because V$(kitversion) already exists"; \
echo ""; \
else \
git tag -f V$(kitversion) || true; \
fi
endif

endef

$(foreach type,$(kittypes),$(eval $(call make_tar,$(type))))

# create a detached signature for a file

%.sig : % Makefile
@-rm -f $<.sig
$(GPG) --output $@ --detach-sig $(foreach k,$(key), --local-user "$(k)") $(basename $@)
@-chown $(kitowner) $@
73 changes: 58 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Quickly (and temporarily) block an IP address

Copyright (C) 2017, 2018, 2019, 2020 Timothe Litt

When your machine is under attack from an unexpected source, the last thing that you want to do is remember the `iptables` syntax for adding an immediate blocking rule.
When your machine is under attack from an unexpected source, the last thing that you want to
do is remember the `iptables` syntax for adding an immediate blocking rule.

`ipblock` addresses this issue. Simply say

Expand All @@ -14,19 +15,20 @@ All packets from that address will be dropped.

`ipblock` only adds a single rule to your `iptables` and/or `ip6tables` rulesets, no
matter how many addresses (up to the ipt_recent limit) are blocked. This rule is
inserted at the top of the chain, thus taking precedence over any other exceptions.
inserted at the top of the specified chain, thus taking precedence over any other exceptions.

The rule is only added the first time that `ipblock` is run, so your `iptables` rules are not reloaded.

Additional command options allow you to:
- Remove an address from the block list
- Remove all addresses from the block list
- List currently blocked addresses and last seen time
- Save the current blocked address list as a script
- Disable the block list (removing the extra `iptables` rule
- Customize the table name and/or chain used

Options may be specified in an initialization file.
- Remove an address from the block list
- Remove all addresses from the block list
- List currently blocked addresses and last seen time
- Save the current blocked address list as a script
- Disable the block list (removing the extra `iptables` rule
- Customize the table name and/or chain used

Options, including the desired chain, should be specified in the configuration file.

`ipblock -h` for complete help

Expand All @@ -43,18 +45,59 @@ This will create a subdirectory named ipblock-&lt;version&gt;.

`cd` to that directory.

Copy files to your preferred local software directories, e.g.:
cp -p ipblock /usr/local/bin
cp -p config/ipblock.conf /etc/sysconfig/ipblock.conf
`make install`

This will install ipblock in `/usr/local/bin`, which should be in your `PATH`

A `man` page will be installed in `/usr/local/share/man`.

You can install elsewhere by specifying a prefix, as in:

`make prefix=/opt install`

See `Makefile` for other options.

Select an `iptables` chain and specify it in `ipblock.conf`, which will be in `/etc/default` or `/etc/sysconfig`

To avoid locking yourself out, specify a chain that INPUT calls AFTER guard rules
that protect your local network. E.g. in your standard rules, start with:

> iptables -N BLOCKED
> iptables -A -i lo -j ACCEPT
> iptables -A INPUT -s _mylan_,_trustedpublic_ -j ACCEPT
> iptables -A INPUT -j BLOCKED
and in `ipblock.conf`

Make sure that the directory containing `ipblock` is in your **PATH**
> OPTIONS="-C BLOCKED"
Read the disclaimer before running the `ipblock` command.

## De-installation

If you didn't save the unpacked tarball directory, re-create it following the
directions for Installation.

Then

`cd` to that directory.

`make uninstall`

If you selected a different installation directory, include the prefix, e.g.:

`make prefix=/opt uninstall`

If you are uninstalling due to a defect or concern, feel free to create a
bug report.

## License and Disclaimer
Copyright (c) 2017, 2018, 2019, 2020, 2021 Timothe Litt
Copyright (c) 2017, 2018, 2019, 2020, 2021, 2023 Timothe Litt

This is free software; the author disclaims all responsibility for its use, reliability and consequences.

This is free software; the author disclaims all responsibility for its use, reliability and consequences. The name of the author may not be used to endorse any product, but must be retained in the documentation and code. Any modifications must be clearly documented and attributed, and are the responsibility of their author.
The name of the author may not be used to endorse any product, but must be retained in the documentation and code.
Any modifications must be clearly documented and attributed, and are the responsibility of their author.

This notice and the copyright statements must be retained in all copies (complete or partial) of this software and documentation. See LICENSE for details.

Expand Down
27 changes: 24 additions & 3 deletions config/ipblock.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
# Default options for ipblock

# Restriction: option values (e.g. to -D) can't contain a space.
# For -D, use '_' instead
# Restriction: option values (e.g. to -D) that contain a space
# must be in single quotes.

#OPTIONS="-D %d-%b-%Y_%T -L"
# Note: only OPTIONS= statements will be used. All will be evaluated.
#
# To avoid lockout, select a suitable chain. E.g.
# OPTIONS="-C mychain"
#
# iptables -A INPUT -p tcp -s mylan/masklen --dport 22 -J ACCEPT
# iptables -A INPUT -j mychain
# ...
# -N mychain
# (automatic RETURN to INPUT from the end)
#
# Since ipblock will add to the front of "mychain", this
# ensures that you will at least have ssh access in the event
# that you block your own access to your system.
#
# If you leave -C at the default, "INPUT", the ipblock rule will
# supersede any protection that you hav established, so don't.
#
# See ipblock -h for more information.

#OPTIONS="-C mychain"
#OPTIONS="$OPTIONS -D '%d-%b-%Y %T'"
Loading

0 comments on commit 417d14e

Please sign in to comment.