Hi Yaroslav,

I've prepared an updated patch. Most changes are in comments. The
iptables rule which I previously proposed was unnecessarily
complicated. Just one line is enough. I've added it as an
'actionstart' rule in the action file. It can be used directly if
fail2ban runs as root. If fail2ban runs as non-root, then it won't be
able to execute the rule, but anyway it serves as documentation.  Also
the special rsyslog setup is not necessary -- /var/log/auth.log is
owned by group 'adm' by default, so it is enough to add the fail2ban
user to this group. OTOH, some more setup for logrotate is necessary.

As you suggested, the fail2ban user is not created automatically, but
it is now documented how to add one in the action file comments.

An updated introductory blurb and changes to files follow:
-------------------------------------------------------------------

Fail2ban currently requires root priviledges to insert iptables rules
through calls to /sbin/iptables and also to read the
logfiles. Fail2ban can run as an unpriviledged user provided that
those two capabilites are preserved. The idea is to run fail2ban as a
normal user (e.g. fail2ban) who belongs to a group which is allowed to
read logfiles. The user should also be allowed to write to
/proc/net/xt_recent/fail2ban-whatever (the name of the file depends on
the iptables rules used to create it).

/proc/net/xt_recent/* is created by the xt_recent kernel module when
an iptables rule with '-m limit' is inserted. This file contains a
dynamic list of IP addresses which can than be used in iptables
rules. Addresses can be matched against this list, with an optional
timeout. One way to use xt_recent is to insert IPs into this list from
an iptables rule, e.g. after connecting to the SSH port three times in
a minute. This is the standard usage described in iptables(3).

Another way to use xt_recent is by inserting the rules by writing to
/proc/net/xt_recent/whatever. This can be performed by a fail2ban
action. Files in /proc/net/xt_recent/ are protected by normal
filesystem rules, so can be chown'ed and chmod'ed to be writable by a
certain user. After the necessary iptables rules are inserted (which
requires root priviledges), blacklisting can be perfomed by an
unpriviledged user.

Using fail2ban with xt_recent allows smarter filtering
than normal iptables rules with the xt_recent module can provide.

The disadvantage is that fail2ban cannot perform the setup by itself,
which would require the priviledge to call /sbin/iptables, and it must
be done through other means.

The primary advantage is obvious: it's generally better to run
services not as root. This setup is more robust, because xt_recent has
it's own memory management and should behave smartly in case a very
large amount of IPs is blocked. Also in case the fail2ban process dies
the rules expire automatically.  In case of a large amount of blocked
IPs, traversing rules linearly for each SYN packet as fail2ban
normally inserts them will be slow, but xt_recent with the same number
of IPs would be much faster. (Didn't test this, so this is pure
handwaving, but it should really be this way ;)) From the
administrators point of view, a setup with xt_recent might also be
easier, because it's very simple to modify the permissions on
/proc/net/xt_recent/fail2ban-whatever to be readable or writable by
some user and thus allow delisting IPs by helper administrators
without the ability to mess up other iptables rules.

The setup is simple:
- add user fail2ban who can read /var/log/auth.log and other
  necessary log files. Log files are owned by group 'adm', so
  it is enough if this user belongs to this group.

- put a rule to check the xt_recent list in the static firewall
  initialization script, with a name like fail2ban-ssh. The
  necessary invocation is documented in the action file.

- set FAIL2BAN_USER in /etc/default/fail2ban.

- make sure that logfiles of fail2ban itself are writable by the
  fail2ban user. /etc/init.d/fail2ban will change the ownership at
  startup, but it is also necessary to modify
  /etc/logrotate.d/fail2ban. Necessary changes are documented in that
  file.

--- fail2ban-0.8.4/debian/fail2ban.default      2011-03-23 11:06:35.000000000 
+0100
+++ /etc/default/fail2ban       2011-03-23 12:53:41.000000000 +0100
@@ -21,3 +21,19 @@
 # Command line options for Fail2Ban. Refer to "fail2ban-client -h" for
 # valid options.
 FAIL2BAN_OPTS=""
+
+# Run fail2ban as a different user. If not set, fail2ban
+# will run as root.
+#
+# The user is not created automatically.
+# The user can be created e.g. with
+#    useradd --system --no-create-home --home-dir / --groups adm fail2ban
+# Log files are readable by group adm by default. Adding the fail2ban
+# user to this group allows it to read the logfiles.
+#
+# Another manual step that needs to be taken is to allow write access
+# for fail2ban user to fail2ban log files. The /etc/init.d/fail2ban
+# script will change the ownership when starting fail2ban. Logrotate
+# needs to be configured seperately, see /etc/logrotate.d/fail2ban.
+
+FAIL2BAN_USER="fail2ban"
--- fail2ban-0.8.4/debian/fail2ban.init 2011-03-23 11:06:35.000000000 +0100
+++ /etc/init.d/fail2ban        2011-03-23 12:52:19.000000000 +0100
@@ -33,6 +33,9 @@
 # Exit if the package is not installed
 [ -x "$DAEMON" ] || exit 0
 
+# Run as root by default.
+FAIL2BAN_USER=root
+
 # Read configuration variable file if it is present
 [ -r /etc/default/$NAME ] && . /etc/default/$NAME
 DAEMON_ARGS="$FAIL2BAN_OPTS"
@@ -103,7 +106,17 @@
        # Assure that /var/run/fail2ban exists
        [ -d /var/run/fail2ban ] || mkdir -p /var/run/fail2ban
 
-       start-stop-daemon --start --quiet --chuid root --exec $DAEMON -- \
+       if [ "$FAIL2BAN_USER" != "root" ]; then
+               # Make the socket directory, IP lists and fail2ban log
+               # files writable by fail2ban
+               chown "$FAIL2BAN_USER" /var/run/fail2ban
+               # Create the logfile if it doesn't exist
+               touch /var/log/fail2ban.log
+               chown "$FAIL2BAN_USER" /var/log/fail2ban.log
+               find /proc/net/xt_recent -name 'fail2ban-*' -exec chown 
"$FAIL2BAN_USER" {} \;
+       fi
+
+       start-stop-daemon --start --quiet --chuid "$FAIL2BAN_USER" --exec 
$DAEMON -- \
                $DAEMON_ARGS start > /dev/null\
                || return 2
 
--- /dev/null   2011-03-01 12:22:44.452629464 +0100
+++ /etc/fail2ban/action.d/iptables-xt_recent-echo.conf 2011-03-23 
11:35:29.000000000 +0100
@@ -0,0 +1,77 @@
+# Fail2Ban configuration file
+#
+# Author: Zbigniew Jędrzejewski-Szmek <zbys...@in.waw.pl>
+#
+# $Revision: 1 $
+#
+
+[Definition]
+
+# Option:  actionstart
+# Notes.:  command executed once at the start of Fail2Ban.
+# Values:  CMD
+#
+# Changing iptables rules requires root priviledges. If fail2ban is
+# configured to run as root, firewall setup can be performed by
+# fail2ban automatically. However, if fail2ban is configured to run as
+# a normal user, the configuration must be done by some other means
+# (e.g. using static firewall configuration with the
+# iptables-persistent package).
+# 
+# Explanation of the rule below:
+#    Check if any packets coming from an IP on the fail2ban-<name>
+#    list have been seen in the last 3600 seconds. If yes, update the
+#    timestamp for this IP and drop the packet. If not, let the packet
+#    through.
+#
+#    Fail2ban inserts blacklisted hosts into the fail2ban-<name> list
+#    and removes them from the list after some time, according to its
+#    own rules. The 3600 second timeout is independent and acts as a
+#    safeguard in case the fail2ban process dies unexpectedly. The
+#    shorter of the two timeouts actually matters.
+# actionstart = iptables -I INPUT -m recent --update --seconds 3600 --name 
fail2ban-<name> -j DROP
+actionstart = 
+
+# Option:  actionstop
+# Notes.:  command executed once at the end of Fail2Ban
+# Values:  CMD
+#
+actionstop = echo / > /proc/net/xt_recent/fail2ban-<name>
+
+# Option:  actioncheck
+# Notes.:  command executed once before each actionban command
+# Values:  CMD
+#
+actioncheck = test -e /proc/net/xt_recent/fail2ban-<name>
+
+# Option:  actionban
+# Notes.:  command executed when banning an IP. Take care that the
+#          command is executed with Fail2Ban user rights.
+# Tags:    <ip>  IP address
+#          <failures>  number of failures
+#          <time>  unix timestamp of the ban time
+# Values:  CMD
+#
+actionban = echo +<ip> > /proc/net/xt_recent/fail2ban-<name>
+
+# Option:  actionunban
+# Notes.:  command executed when unbanning an IP. Take care that the
+#          command is executed with Fail2Ban user rights.
+# Tags:    <ip>  IP address
+#          <failures>  number of failures
+#          <time>  unix timestamp of the ban time
+# Values:  CMD
+#
+actionunban = echo -<ip> > /proc/net/xt_recent/fail2ban-<name>
+
+[Init]
+
+# Defaut name of the chain
+#
+name = default
+
+# Option:  protocol
+# Notes.:  internally used by config reader for interpolations.
+# Values:  [ tcp | udp | icmp | all ] Default: tcp
+#
+protocol = tcp
--- fail2ban-0.8.4/debian/fail2ban.logrotate    2011-03-23 11:06:35.000000000 
+0100
+++ /etc/logrotate.d/fail2ban   2011-03-23 12:55:56.000000000 +0100
@@ -9,5 +9,8 @@
     postrotate
        fail2ban-client set logtarget /var/log/fail2ban.log >/dev/null
     endscript
+
+    # If fail2ban runs as non-root it still needs to have write access
+    # to logfiles.
+    # create 640 fail2ban adm
     create 640 root adm
 }



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to