fail2ban
In this laboratory, we will explore the security implications of network
connected devices and how to protect them from external attacks.
You have a NanoPi device with a buildroot Linux system installed that we
will modify to have the relevant tools installed. That is: netfilter and
iptables.
Preparation tasks
The goal of this part of the lab is to setup your NanoPi with a newly modified configuration to that you can make use of the said tools.
For this you will need to:
- Ensure
glibcis configured and with the correct other settingsToolchain ---> Toolchain type → Buildroot toolchain C library → glibc

-
Install
pythonTarget packages ---> Interpreter languages and scripting ---> python3 → enable
-
Install a second user
-
create a users’ file (e.g.
users.conf) whose location should beboard/friendlyarm/nanopi-neo-plus2/users.confTip
Buildroot user manual for users support: https://buildroot.org/downloads/manual/manual.html#customize-users. Syntax for user creation: https://buildroot.org/downloads/manual/makeusers-syntax.txt.
-
add it to the configuration
System configuration ---> (board/friendlyarm/nanopi-neo-plus2/users.conf) Path to the users tables
-
add the desired user(s) configuration - here the exemple for a
foouserfoo -1 bar -1 !=blabla /home/foo /bin/sh wheel,adm Foo userWarning
Should you have any issue logging in with user
foo, use thepasswdcommand from therootaccountTip
The reason for having a second user is that in case you gets blocked out, there is a second user with
-
fail2ban installation
In order to achieve the installation of fail2ban, follow the steps described
below.
-
On the host
- Clone the repository https://github.com/fail2ban/fail2ban.git
- Create dedicated
SeSbranch -
As the
/etc/fail2ban/filter.d/sshd.conffilter is not working with the logging format we use, apply the following patch to itdiff --git a/config/filter.d/sshd.conf b/config/filter.d/sshd.conf index 80d0c349..3375aa4b 100644 --- a/config/filter.d/sshd.conf +++ b/config/filter.d/sshd.conf @@ -106,9 +106,13 @@ cmnfailre-failed-pub-ignore = cfooterre = ^<F-NOFAIL>Connection from</F-NOFAIL> <HOST> -failregex = %(cmnfailre)s - <mdre-<mode>> - %(cfooterre)s + +# --- BusyBox match --- +#failregex = ^.*sshd\[.*\]: Failed password for .* from <HOST> port \d+ ssh2$ +#failregex = ^Failed password for .* from <HOST> port \d+ ssh2$ +failregex = ^.*sshd(?:\[\d+\])?: Failed password for (?:invalid user )?.* from <HOST> + ^.*sshd(?:\[\d+\])?: Invalid user .* from <HOST> + ^.*sshd(?:\[\d+\])?: maximum authentication attempts exceeded for .* from <HOST> # Parameter "mode": normal (default), ddos, extra or aggressive (combines all) # Usage example (for jail.local):Warning
It may be that you need to adapt the patch containing
^.*sshd(?:\[\d+\])needs to be adapted to your installation. For instance, you may havesshd-session)and not simplysshd. -
Copy
fail2banon your target using (do change what is needed)#!/bin/bash ############################################# # Configuration ############################################# TARGET_IP="192.168.0.14" # <-- Set target device IP here TARGET_USER="root" TARGET_BASE="/usr/share/fail2ban" # runtime files directory TARGET_BIN="/usr/bin" # executables go here SOURCE_DIR="." # local clone of Fail2ban repo # Detect Python version on target PYVER=$(ssh ${TARGET_USER}@${TARGET_IP} "python3 -c 'import sys; print(f\"{sys.version_info.major}.{sys.version_info.minor}\")'") TARGET_SITEPKG="/usr/lib/python${PYVER}/site-packages" TARGET_ETC="/etc/fail2ban" TARGET_BIN="/usr/bin" echo "[+] Creating directory structure on target..." ssh ${TARGET_USER}@${TARGET_IP} " mkdir -p ${TARGET_SITEPKG} && mkdir -p ${TARGET_ETC} && mkdir -p ${TARGET_BIN} " echo "[+] Transferring Python package fail2ban -> ${TARGET_SITEPKG} ..." scp -r \ ${SOURCE_DIR}/fail2ban \ ${TARGET_USER}@${TARGET_IP}:${TARGET_SITEPKG}/ echo "[+] Transferring config directory -> ${TARGET_ETC} ..." scp -r \ ${SOURCE_DIR}/config/* \ ${TARGET_USER}@${TARGET_IP}:${TARGET_ETC}/ echo "[+] Transferring executables -> ${TARGET_BIN} ..." scp \ ${SOURCE_DIR}/bin/fail2ban-server \ ${SOURCE_DIR}/bin/fail2ban-client \ ${SOURCE_DIR}/bin/fail2ban-regex \ ${TARGET_USER}@${TARGET_IP}:${TARGET_BIN}/ ssh ${TARGET_USER}@${TARGET_IP} " chmod +x ${TARGET_BIN}/fail2ban-server chmod +x ${TARGET_BIN}/fail2ban-client chmod +x ${TARGET_BIN}/fail2ban-regex " echo "[+] Deployment complete!" echo "[+] To start fail2ban" echo " fail2ban-client start" echo "(Once you have configured the system ;-)))"
-
On the target
- Create a
jail.localwith the following content[ssh] enabled = true port = ssh filter = sshd logpath = /var/log/messages action = iptables[name=SSH, port=ssh, protocol=tcp] maxretry = 3 bantime = 600 - Make it permanent by creating a
S45fail2baninit script (to be located in/etc/init.d)#!/bin/sh # Fail2ban init script for BusyBox systems ### BEGIN INIT INFO # Provides: fail2ban # Required-Start: # Required-Stop: # Default-Start: 3 4 5 # Default-Stop: 0 1 2 6 # Short-Description: Start fail2ban ### END INIT INFO umask 077 LOGTAG="fail2ban-init" log() { # Print to console and syslog echo "$1" logger -t "$LOGTAG" "$1" } start() { log "Starting fail2ban..." [ -d /var/run/fail2ban ] || mkdir -p /var/run/fail2ban if /usr/bin/fail2ban-client start; then touch /var/lock/fail2ban log "Fail2ban started successfully." return 0 else log "Failed to start fail2ban." return 1 fi } stop() { log "Stopping fail2ban..." if /usr/bin/fail2ban-client stop; then rm -rf /var/run/fail2ban rm -f /var/lock/fail2ban log "Fail2ban stopped successfully." return 0 else log "Failed to stop fail2ban." return 1 fi } restart() { stop start } case "$1" in start) start ;; stop) stop ;; restart|reload) restart ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 esac exit $?
- Create a
-
Experiment with login attempts
- use
sshto login onto the NanoPi as userfoo - make sure you type the wrong password to see
fail2banin action - check
iptables -Lafter 3 failed attempts - try out other options - your imagination may be the sole limit 😉
- use
Questions
Tip
- In order to know how to check the validity of one’s configuration, issue :
PYTHONPATH=. python3 bin/fail2ban-regex messages config/filter.d/yourfilter.conf
Question
Warning
Before answering, make sure you add your ses_deconfig to your
repository with an appropriate tag.
-
Write down the content of
iptables- when no
useror machine has been banned - when at least one
useror machine has been banned
- when no
-
Assuming you have access to the NanoPi still, how could you remove the rules? Write down the command used for it.
-
If a target had the following configured in
jail.localwhat would be the difference(s) in[DEFAULT] protocol = all banaction = iptables-allports [ssh] enabled = true filter = sshd logpath = /var/log/messages action = iptables-allports[name=SSH] maxretry = 3 bantime = 600iptablescontent and behaviour? Try it out on your NanoPi and report the outcome.Note
You would need the following in
/etc/fail2ban/action.d/iptables-allports.local[Definition] # Override the jump insertion actionstart = iptables -N f2b-<name> iptables -I INPUT -p all -j f2b-<name> actionstop = iptables -D INPUT -p all -j f2b-<name> iptables -F f2b-<name> iptables -X f2b-<name> -
Patching
sshd.confas it is done in this description is against what is promoted by thefail2banproject. As a result, create a cleaner, dedicated configuration. Write down- what you did - including the used commands
- add the files that were modified or created to the report
-
OPTIONAL (may give a bonus)
Copying files around is not the best of solutions. A better one would be to create a dedicated package that does all the tedious manual work. So, how to create such a dedicated package? Write down all the steps and files that are needed for achieving this.