Commit 84dbdb9d authored by Sven Geuer's avatar Sven Geuer

Import Upstream version 2.0.1.f

parents
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# ------------------------------------------------------------------------------
# -= Arno's iptables firewall - Adaptive Ban plugin =-
#
PLUGIN_NAME="Adaptive Ban plugin"
PLUGIN_VERSION="1.04 BETA"
PLUGIN_CONF_FILE="adaptive-ban.conf"
#
# Last changed : November 20, 2011
# Requirements : AIF 2.0.0+
# Comments : Parse a log file for failed access with offending IP addresses
# Ban the IP address after multiple failed attempts
#
# Author : (C) Copyright 2010-2011 by Lonnie Abelbeck
# Homepage : http://www.astlinux.org/
# Credits : Fail2ban Project
# Homepage : http://www.fail2ban.org/
# Credits : Arno van Amersfoort
# Homepage : http://rocky.eld.leidenuniv.nl/
# Email : a r n o v a AT r o c k y DOT e l d DOT l e i d e n u n i v DOT n l
# (note: you must remove all spaces and substitute the @ and the .
# at the proper locations!)
# ------------------------------------------------------------------------------
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# version 2 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# ------------------------------------------------------------------------------
# Plugin start function
plugin_start()
{
local host net IFS
iptables -N ADAPTIVE_BAN_DROP_CHAIN 2>/dev/null
iptables -F ADAPTIVE_BAN_DROP_CHAIN
iptables -A ADAPTIVE_BAN_DROP_CHAIN -m limit --limit 1/hour --limit-burst 1 -j LOG --log-level $LOGLEVEL --log-prefix "AIF:Adaptive-Ban host: "
if [ "$ADAPTIVE_BAN_REJECT" = "1" ]; then
ip4tables -A ADAPTIVE_BAN_DROP_CHAIN -j REJECT --reject-with icmp-host-unreachable
if [ "$IPV6_SUPPORT" = "1" ]; then
ip6tables -A ADAPTIVE_BAN_DROP_CHAIN -j REJECT --reject-with icmp6-addr-unreachable
fi
else
iptables -A ADAPTIVE_BAN_DROP_CHAIN -j DROP
fi
iptables -N ADAPTIVE_BAN_CHAIN 2>/dev/null
iptables -F ADAPTIVE_BAN_CHAIN
if [ "$ADAPTIVE_BAN_WHITELIST_INTERNAL" != "0" ]; then
printf "${INDENT}Adaptive Ban - Whitelisting INTERNAL net(s): "
IFS=' ,'
for net in $INTERNAL_NET; do
printf "$net "
iptables -A ADAPTIVE_BAN_CHAIN -s $net -j RETURN
done
echo ""
fi
if [ -n "$ADAPTIVE_BAN_WHITELIST" ]; then
printf "${INDENT}Adaptive Ban - Whitelisting host(s): "
IFS=' ,'
for host in $ADAPTIVE_BAN_WHITELIST; do
printf "$host "
iptables -A ADAPTIVE_BAN_CHAIN -s $host -j RETURN
done
echo ""
fi
# Insert rule in the INPUT chain
iptables -I INPUT -j ADAPTIVE_BAN_CHAIN
# Insert rule in the FORWARD chain
iptables -I FORWARD -j ADAPTIVE_BAN_CHAIN
echo "${INDENT}File=$ADAPTIVE_BAN_FILE Time=$ADAPTIVE_BAN_TIME Count=$ADAPTIVE_BAN_COUNT Types=$ADAPTIVE_BAN_TYPES"
"$PLUGIN_BIN_PATH/adaptive-ban-helper" start "$IP4TABLES" "$IP6TABLES" "$IPV6_SUPPORT" \
"$ADAPTIVE_BAN_FILE" "$ADAPTIVE_BAN_TIME" "$ADAPTIVE_BAN_COUNT" $ADAPTIVE_BAN_TYPES >/dev/null 2>&1 &
return 0
}
# Plugin stop function
plugin_stop()
{
printf "${INDENT}Adaptive Ban - Stopping... "
# Stop helper script on next iteration
"$PLUGIN_BIN_PATH/adaptive-ban-helper" stop "$IP4TABLES" "$IP6TABLES" "$IPV6_SUPPORT"
echo "Stopped."
iptables -D INPUT -j ADAPTIVE_BAN_CHAIN
iptables -D FORWARD -j ADAPTIVE_BAN_CHAIN
iptables -F ADAPTIVE_BAN_CHAIN
iptables -X ADAPTIVE_BAN_CHAIN 2>/dev/null
iptables -F ADAPTIVE_BAN_DROP_CHAIN
iptables -X ADAPTIVE_BAN_DROP_CHAIN 2>/dev/null
return 0
}
# Plugin status function
plugin_status()
{
"$PLUGIN_BIN_PATH/adaptive-ban-helper" status "$IP4TABLES" "$IP6TABLES" "$IPV6_SUPPORT"
return 0
}
# Check sanity of eg. environment
plugin_sanity_check()
{
if [ ! -x "$PLUGIN_BIN_PATH/adaptive-ban-helper" ]; then
printf "\033[40m\033[1;31m${INDENT}ERROR: The adaptive-ban-helper script can not be found or is not executable!\033[0m\n" >&2
return 1
fi
if [ -z "$ADAPTIVE_BAN_FILE" -o -z "$ADAPTIVE_BAN_TIME" -o -z "$ADAPTIVE_BAN_COUNT" -o -z "$ADAPTIVE_BAN_TYPES" ]; then
printf "\033[40m\033[1;31m${INDENT}ERROR: The plugin config file is not properly set!\033[0m\n" >&2
return 1
fi
if [ "$PLUGIN_CMD" = "start" ] && [ ! -f "$ADAPTIVE_BAN_FILE" ]; then
printf "\033[40m\033[1;31m${INDENT}ERROR: Input log file $ADAPTIVE_BAN_FILE does not exist!\033[0m\n" >&2
return 1
fi
if ! check_command sort; then
printf "\033[40m\033[1;31m${INDENT}ERROR: Required command sort is not available!\033[0m\n" >&2
return 1
fi
if ! check_command uniq; then
printf "\033[40m\033[1;31m${INDENT}ERROR: Required command uniq is not available!\033[0m\n" >&2
return 1
fi
return 0
}
############
# Mainline #
############
# Check where to find the config file
CONF_FILE=""
if [ -n "$PLUGIN_CONF_PATH" ]; then
CONF_FILE="$PLUGIN_CONF_PATH/$PLUGIN_CONF_FILE"
fi
# Check if the config file exists
if [ ! -e "$CONF_FILE" ]; then
printf "NOTE: Config file \"$CONF_FILE\" not found!\n Plugin \"$PLUGIN_NAME v$PLUGIN_VERSION\" ignored!\n" >&2
PLUGIN_RET_VAL=0
else
# Source the plugin config file
. "$CONF_FILE"
if [ "$ENABLED" = "1" ] ||
[ -n "$PLUGIN_LOAD_FILE" -a "$PLUGIN_CMD" = "stop" ] ||
[ -n "$PLUGIN_LOAD_FILE" -a "$PLUGIN_CMD" = "status" ]; then
# Show who we are:
echo "${INDENT}$PLUGIN_NAME v$PLUGIN_VERSION"
# Increment indention
INDENT="$INDENT "
# Only proceed if environment ok
if plugin_sanity_check; then
case $PLUGIN_CMD in
start|'') plugin_start; PLUGIN_RET_VAL=$?;;
stop ) plugin_stop; PLUGIN_RET_VAL=$?;;
status ) plugin_status; PLUGIN_RET_VAL=$?;;
* ) PLUGIN_RET_VAL=1; printf "\033[40m\033[1;31m${INDENT}ERROR: Invalid plugin option \"$PLUGIN_CMD\"!\033[0m\n" >&2;;
esac
fi
else
PLUGIN_RET_VAL=0
fi
fi
AstLinux AIF Contributions
+========================+
| www.astlinux.org |
+========================+
1) Adaptive Ban Plugin
Parse a log file for failed access with offending IP addresses.
Ban the IP address after multiple failed attempts.
Simular in function to the Fail2ban project, www.fail2ban.org .
The latest is available via the AstLinux SVN:
http://astlinux.svn.sourceforge.net/viewvc/astlinux/branches/1.0/package/arnofw/adaptive-ban/
(Note: remove the SVN ".sh" suffixes to be used directly with generic AIF)
#!/bin/bash
LOCKFILE="/var/lock/aif_adaptive_ban.lock"
ARGSFILE="/var/tmp/aif_adaptive_ban.args"
TEMPFILE="/var/tmp/aif_adaptive_ban.temp"
start_run()
{
local num file time count arg args argstime=0 filetime=0 ARGS IFS
ARGS="$@"
# Robust 'bash' method of creating/testing for a lockfile
if ! ( set -o noclobber; echo "$$" > "$LOCKFILE" ) 2>/dev/null; then
echo "$ARGS" > "$ARGSFILE"
echo "adaptive-ban-helper: already running, lockfile \"$LOCKFILE\" exists, process id: $(cat "$LOCKFILE")."
return 9
fi
trap 'rm -f "$LOCKFILE" "$ARGSFILE" "$TEMPFILE"; exit $?' INT TERM EXIT
echo "$ARGS" > "$ARGSFILE"
# Delay to allow firewall script to complete
idle_wait 45
while [ -f "$ARGSFILE" ]; do
# Check whether chains exists
if ! check_for_chain ADAPTIVE_BAN_CHAIN; then
log_msg "ADAPTIVE_BAN_CHAIN does not exist"
break
fi
if ! check_for_chain ADAPTIVE_BAN_DROP_CHAIN; then
log_msg "ADAPTIVE_BAN_DROP_CHAIN does not exist"
break
fi
ARGS="$(cat "$ARGSFILE")"
file=""
args=""
num=0
unset IFS
for arg in $ARGS; do
num=$((num+1))
case "$num" in
1) file="$arg" ;;
2) time="$arg" ;;
3) count="$arg" ;;
*) args="${args}${args:+ }$arg" ;;
esac
done
if [ ! -f "$file" ]; then
log_msg "Input log file $file does not exist"
break
fi
if [ "$filetime" != "$(date -r "$file" "+%s")" -o "$argstime" != "$(date -r "$ARGSFILE" "+%s")" ]; then
filter "$file" "$count" $args
filetime="$(date -r "$file" "+%s")"
argstime="$(date -r "$ARGSFILE" "+%s")"
fi
# Idle - interrupted if ARGSFILE is deleted
idle_wait $time
done
rm -f "$LOCKFILE" "$ARGSFILE" "$TEMPFILE"
trap - INT TERM EXIT
return 0
}
stop()
{
rm -f "$ARGSFILE"
# If the background start_run() is in idle_wait() this ensures a clean stop.
sleep 1
# If start_run() is not in idle_wait() we deal with that as well.
# We could loop while LOCKFILE exists, but doesn't seem necessary.
}
status()
{
echo " Banned Hosts:"
echo " =============================="
ip4tables -n -L ADAPTIVE_BAN_CHAIN | awk '$1 == "ADAPTIVE_BAN_DROP_CHAIN" { print " "$4 }'
if [ "$IPV6_SUPPORT" = "1" ]; then
ip6tables -n -L ADAPTIVE_BAN_CHAIN | awk '$1 == "ADAPTIVE_BAN_DROP_CHAIN" { print " "$3 }'
fi
echo " ------------------------------"
echo ""
echo " Whitelisted Hosts:"
echo " =============================="
ip4tables -n -L ADAPTIVE_BAN_CHAIN | awk '$1 == "RETURN" { print " "$4 }'
if [ "$IPV6_SUPPORT" = "1" ]; then
ip6tables -n -L ADAPTIVE_BAN_CHAIN | awk '$1 == "RETURN" { print " "$3 }'
fi
echo " ------------------------------"
echo ""
}
filter()
{
local file="$1" count="$2" type types PREFIX HOST IFS
shift 2
types="$@"
# regex to pull out offending IPv4/IPv6 address
#
HOST="([0-9a-fA-F:.]{7,})"
unset IFS
for type in $types; do
# regex match the start of the syslog string
#
PREFIX=".*${type}\[[0-9]*]:[[:space:]]*"
case "$type" in
sshd) filter_sshd "$file" "$PREFIX" "$HOST"
;;
asterisk) filter_asterisk "$file" "$PREFIX" "$HOST"
;;
lighttpd) filter_lighttpd "$file" "$PREFIX" "$HOST"
;;
mini_httpd) filter_mini_httpd "$file" "$PREFIX" "$HOST"
;;
pptpd) filter_pptpd "$file" "$PREFIX" "$HOST"
;;
*) log_msg "Unsupported type \"$type\""
continue
;;
esac
if [ $? -ne 0 ]; then
log_msg "Filter Error for type \"$type\""
else
count_attempts_then_ban "$count" "$type"
fi
rm -f "$TEMPFILE"
done
}
filter_sshd()
{
local file="$1" PREFIX="$2" HOST="$3"
sed -n -r -e "s/^${PREFIX}Failed (password|publickey) for .* from ${HOST}( port [0-9]*)?( ssh[0-9]*)?$/\2/p" \
-e "s/^${PREFIX}[iI](llegal|nvalid) user .* from ${HOST}[[:space:]]*$/\2/p" \
"$file" >"$TEMPFILE"
}
filter_asterisk()
{
local file="$1" PREFIX="$2" HOST="$3"
sed -n -r -e "s/^${PREFIX}NOTICE.* .*: Registration from '.*' failed for '${HOST}' - Wrong password$/\1/p" \
-e "s/^${PREFIX}NOTICE.* .*: Registration from '.*' failed for '${HOST}' - No matching peer found$/\1/p" \
-e "s/^${PREFIX}NOTICE.* .*: Registration from '.*' failed for '${HOST}' - Username\/auth name mismatch$/\1/p" \
-e "s/^${PREFIX}NOTICE.* .*: Registration from '.*' failed for '${HOST}' - Device does not match ACL$/\1/p" \
-e "s/^${PREFIX}NOTICE.* '${HOST}' - Dialplan Noted Suspicious IP Address$/\1/p" \
-e "s/^${PREFIX}NOTICE.* ${HOST} failed to authenticate as '.*'$/\1/p" \
-e "s/^${PREFIX}NOTICE.* .*: No registration for peer '.*' \(from ${HOST}\)$/\1/p" \
-e "s/^${PREFIX}NOTICE.* .*: Host ${HOST} failed MD5 authentication for '.*' \(.*\)$/\1/p" \
"$file" >"$TEMPFILE"
}
filter_lighttpd()
{
local file="$1" PREFIX="$2" HOST="$3"
sed -n -r -e "s/^${PREFIX}.* password doesn't match for .* IP: ${HOST}[[:space:]]*$/\1/p" \
-e "s/^${PREFIX}.* get_password failed, IP: ${HOST}[[:space:]]*$/\1/p" \
"$file" >"$TEMPFILE"
}
filter_mini_httpd()
{
local file="$1" PREFIX="$2" HOST="$3"
sed -n -r -e "s/^${PREFIX}${HOST} authentication failure - access denied$/\1/p" \
"$file" >"$TEMPFILE"
}
filter_pptpd()
{
local file="$1" PREFIX="$2" HOST="$3" PPP_PREFIX=".*pppd\[[0-9]*]:[[:space:]]*"
sed -n -r -e "/^${PPP_PREFIX}.* failed CHAP authentication$/ {N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;\
s/^.*\n${PREFIX}CTRL: Client ${HOST} control connection finished\n.*$/\1/p}" \
"$file" >"$TEMPFILE"
}
count_attempts_then_ban()
{
local count="$1" type="$2" line host IFS
# Remove possible IPv4 port numbers, IPv4:PORT -> IPv4
sed -i -r -e 's/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+):[0-9]+$/\1/' "$TEMPFILE"
IFS=$'\n'
for line in $(sort "$TEMPFILE" | uniq -c); do
if [ "$(echo "$line" | awk '{ print $1; }')" -ge "$count" ]; then
host="$(echo "$line" | awk '{ print $2; }')"
ban_host "$host" "$type"
fi
done
}
ban_host()
{
local host="$1" type="$2"
get_numeric_ip_version "$host"
case $? in
4)
if ! ip4tables -n -L ADAPTIVE_BAN_CHAIN | grep -q " ${host//./\.}[/ ]"; then
ip4tables -A ADAPTIVE_BAN_CHAIN -s $host -j ADAPTIVE_BAN_DROP_CHAIN
if [ $? -eq 0 ]; then
log_msg "Banned IPv4 Host: $host Filter Type: $type"
fi
fi
;;
6)
if [ "$IPV6_SUPPORT" = "1" ]; then
if ! ip6tables -n -L ADAPTIVE_BAN_CHAIN | grep -q " ${host}[/ ]"; then
ip6tables -A ADAPTIVE_BAN_CHAIN -s $host -j ADAPTIVE_BAN_DROP_CHAIN
if [ $? -eq 0 ]; then
log_msg "Banned IPv6 Host: $host Filter Type: $type"
fi
fi
fi
;;
esac
}
idle_wait()
{
local time="$1" cnt=0
while [ -f "$ARGSFILE" -a $cnt -lt $time ]; do
cnt=$((cnt+1))
sleep 1
done
}
check_for_chain()
{
local err
ip4tables -n -L "$1" >/dev/null 2>&1
err=$?
if [ "$IPV6_SUPPORT" = "1" -a $err -eq 0 ]; then
ip6tables -n -L "$1" >/dev/null 2>&1
err=$?
fi
return $err
}
ip4tables()
{
local result retval
result="$($IP4TABLES "$@" 2>&1)"
retval=$?
if [ $retval -ne 0 ]; then
log_msg "$IP4TABLES: ($retval) $result"
elif [ -n "$result" ]; then
echo "$result"
fi
return $retval
}
ip6tables()
{
local result retval
result="$($IP6TABLES "$@" 2>&1)"
retval=$?
if [ $retval -ne 0 ]; then
log_msg "$IP6TABLES: ($retval) $result"
elif [ -n "$result" ]; then
echo "$result"
fi
return $retval
}
get_numeric_ip_version()
{
case $1 in
0/0)
;;
[0-9][0-9.][0-9.][0-9.][0-9.]*.*[0-9])
return 4
;;
[0-9]*.*/*[0-9]|[0-9]/*[0-9]|[1-9][0-9]/*[0-9]|[12][0-9][0-9]/*[0-9])
return 4
;;
*:*)
return 6
;;
esac
return 0
}
log_msg()
{
logger -t "firewall: adaptive-ban" -p kern.info "$1"
echo "$1" >&2
}
# main
ACTION="$1"
IP4TABLES="$2"
if [ -z "$IP4TABLES" -o "$IP4TABLES" = "ip4tables" ]; then
ACTION=""
fi
IP6TABLES="$3"
if [ -z "$IP6TABLES" -o "$IP6TABLES" = "ip6tables" ]; then
ACTION=""
fi
IPV6_SUPPORT="$4"
shift 4
case $ACTION in
start)
if [ -z "$1" -o -z "$2" -o -z "$3" -o -z "$4" ]; then
echo "Usage: adaptive-ban-helper start ip4tables_path ip6tables_path ipv6_flag logfile time count args..."
exit 1
fi
start_run "$@"
;;
stop)
stop
;;
status)
status
;;
*)
echo "Usage: adaptive-ban-helper start|stop|status ip4tables_path ip6tables_path ipv6_flag"
echo " [ logfile time count args... ]"
exit 1
;;
esac
# ------------------------------------------------------------------------------
# -= Arno's iptables firewall - Adaptive Ban plugin =-
# ------------------------------------------------------------------------------
# To actually enable this plugin make ENABLED=1:
# ------------------------------------------------------------------------------
ENABLED=0
# Log file where failed access attempts are derived
# ------------------------------------------------------------------------------
ADAPTIVE_BAN_FILE="/var/log/messages"
# The time in seconds between each iteration of analyzing the log file
# ------------------------------------------------------------------------------
ADAPTIVE_BAN_TIME=120
# The number of log failures to ban host
# ------------------------------------------------------------------------------
ADAPTIVE_BAN_COUNT=6
# A list of analysis types that are applied
# Choose from: sshd asterisk lighttpd mini_httpd pptpd
# ------------------------------------------------------------------------------
ADAPTIVE_BAN_TYPES="sshd asterisk"
# By default, inbound packets from banned IP addresses will be silently DROP'ed
# As an option, the packets can be REJECT'ed instead of being DROP'ed
# Define ADAPTIVE_BAN_REJECT=1 for an ICMP error message to be returned
# ------------------------------------------------------------------------------
ADAPTIVE_BAN_REJECT=0
# Bt default, INTERNAL (LAN) networks will be whitelisted against banning
# As an option, this automatic whitelisting can be disabled
# Define ADAPTIVE_BAN_WHITELIST_INTERNAL=0 to disable INTERNAL whitelisting
# ------------------------------------------------------------------------------
ADAPTIVE_BAN_WHITELIST_INTERNAL=1
# Whitelist Hosts
# A list of IP addresses whose traffic will never be banned
# ------------------------------------------------------------------------------
ADAPTIVE_BAN_WHITELIST=""
#!/bin/sh
#
# chkconfig: 2345 11 89
# description: init.d script for Arno's iptables firewall
### BEGIN INIT INFO
# Provides: arno-iptables-firewall
# Required-Start: $local_fs $remote_fs $network
# Required-Stop: $local_fs $remote_fs $network
# Default-Start: S
# Default-Stop: 0 6
# Short-Description: Setup iptables firewall configuration
### END INIT INFO
############################################################################################
# You should put this script in eg. "/etc/init.d/" . #
# Furthermore make sure it's executable! -> "chmod 700" or "chmod +x" it #
# If you want to run it upon boot, either add an entry in your "/etc/rc.d/rc.local" or #
# (for eg. Debian) in "/etc/rcS.d/" create a symlink to the arno-iptables-firewall script #
# ("ln -s /etc/init.d/arno-iptables-firewall script S99-arno-iptables-firewall script"). #
############################################################################################
PATH=/bin:/usr/bin:/sbin:/usr/sbin
PROGRAM="/usr/local/sbin/arno-iptables-firewall"
NAME="arno-iptables-firewall"
# Be verbose(1)?:
VERBOSE=0
test -x $PROGRAM || exit 0
. /lib/lsb/init-functions
if [ "$VERBOSE" = "0" ]; then
case "$1" in
start)
log_daemon_msg "Starting Arno's Iptables Firewall..."
;;
stop)
log_daemon_msg "Stopping Arno's Iptables Firewall..."
;;
restart)
log_daemon_msg "Restarting Arno's Iptables Firewall..."
;;
force-reload)
log_daemon_msg "(Forced) reloading Arno's Iptables Firewall..."
;;
status)
$PROGRAM $*
exit $?
;;
*)
$PROGRAM
exit 1
;;
esac
# Call firewall script:
result=`$PROGRAM $*`
retval=$?
else
<