The solution from Block outdated clients won´t work with syslog-ng 3.4.2, because syslog-ng syslog-ng uses “lseek()” to get the end of /proc/net/xt_recent/something
while the program() destination just starts the program.
Withe the destination file
you get log-entries like:
Aug 29 00:00:44 mx03.schaal-24.de syslog-ng[20351]: Error suspend timeout has elapsed, attempting to write again; fd='24'
Aug 29 00:00:44 mx03.schaal-24.de syslog-ng[20351]: I/O error occurred while writing; fd='24', error='Input/output error (5)'
Aug 29 00:00:44 mx03.schaal-24.de syslog-ng[20351]: Suspending write operation because of an I/O error; fd='24', time_reopen='10
'
So you have to change the destination from file
to program
and create a shell-script.
destination deny-mirror {
program("/root/scripts/syslog/ban-recent.sh"
template("+${APACHE.SRC-IP} clamav-403\n"));
};
The shell-script may looks like:
#!/bin/bash
IP=`echo $1|cut -d" " -f1`
JAIL=`echo $1|cut -d" " -f2`
echo +$IP > /proc/net/xt_recent/$JAIL
Basically
#!/bin/sh
echo +$1 > /proc/net/xt_recent/$2
would do the job.
With the first solution you can also use a whitelist or store the data in an database.:
#!/bin/bash
WHITELIST_MX_02="1.2.3.4 4.5.6.7"
WHITELIST_MX_03="10.11.12.13 14.15.16.17"
WHITELIST=$WHITELIST_MX_02" "$WHITELIST_MX_03"
SQLBIN=`which mysql`
DB="system-log"
TAB=iptables
IP=`echo $1|cut -d" " -f1`
JAIL=`echo $1|cut -d" " -f2`
for IP_WL in $(echo $WHITELIST); do
if [ $IP != $IP_WL ]; then
echo +$IP > /proc/net/xt_recent/$JAIL
$SQLBIN $DB -e "INSERT INTO $TAB VALUES(INET_ATON('$IP'),INET_ATON('0.0.0.0'),80,'$JAIL',1,now(),DEFAULT) ON DUPLICATE KEY UPDATE hits=hits+1,remote=DEFAULT;"
fi
done;
Thanks for hinting at the lseek() issue! I’ve been wondering for a while why my rules stopped working after the upgrade.
Some hints, though …
If you’re using bash anyway,
IP=`echo $1|cut -d” ” -f1`
JAIL=`echo $1|cut -d” ” -f2`
is better written as
IP=${1%% *}
JAIL=${1#* }
to avoid creating two new processes.
Also I don’t think your whitelist loop works like that … Did you really intend to jail the source ip if you find one ip in the whitelist that doesn’t match? If your whitelist has two different ips, this will jail all candidates. I think what you want is to check all ips in the whitelist, and jail the candidate if it doesn’t match any of them.
Finally, syslog-ng (at least for version 3.5 that I’m looking at) keeps the script running and expects it to read further input through stdin. This is kind of obscurely implied in the documentation here:
https://syslog-ng.com/documents/html/syslog-ng-ose-3.5-guides/en/syslog-ng-ose-guide-admin/html/reference-destination-program.html
You’ll notice if you add logging to the script: The log output is written many times per second, because when the script exits, syslog-ng restarts it immediately, even before there’s anything to log.
Thus you want to wrap the script in an endless loop, like so:
while true ; do
{
read ip target
[ -z “$ip” ] && continue
echo +$ip > /proc/net/xt_recent/$target
date +”%F %T $ip $target”
} 2>&1 >> /var/log/ban.log
done
The `read` will block until input is available.
I’m still seeing empty output every 20 minutes … guessing syslog-ng still restarts the script regularly even if nothing has happened. That’s what the “empty parameter – continue” shortcut is for.
I’ve also wrapped the echo-to-proc in with the logging so that next time this throws errors, I’ll see them in the ban.log.
HTH! Jan
Pingback: Block outdated clients | florian @it