LS,
Ik merkte dat IP Block functionaliteit in mijn DSM veel ongewenste gasten buiten houdt, maar niet alle.
Zo zag ik in mijn /var/log/messages regelmatig hele waslijsten met de volgende meldingen:
Jul 25 08:42:37 postfix/smtpd[11235]: warning: xxxxx[xxx.xxx.xxx.xxx]: SASL PLAIN authentication failed authentication failure
Jul 25 17:02:40 postfix/smtpd[30649]: warning: unknown[xxx.xxx.xxx.xxx]: SASL LOGIN authentication failed: authentication failure
En in mijn maillog zag ik dingen als:
dovecot: Oct 27 00:12:55 Info: pop3-login: Aborted login (auth failed, 1 attempts): user=<test>, method=PLAIN, rip=xxx.xxx.xxx.xxx, lip=yyy.yyy.yyy.yyy
dovecot: Oct 27 00:12:55 Info: pop3-login: Disconnected (auth failed, 1 attempts): user=<test@domain.com>, method=PLAIN, rip=xxx.xxx.xxx.xxx, lip=yyy.yyy.yyy.yyy
dovecot: Oct 25 00:09:29 Info: imap-login: Disconnected (auth failed, 1 attempts): user=<abc>, method=PLAIN, rip=xxx.xxx.xxx.xxx, lip=yyy.yyy.yyy.yyy, secured
Dit jeukte enorm, dus ging ik op zoek naar een oplossing. Op
http://forum.synology.com/enu/viewtopic.php?f=145&t=50723#p210120 vond ik een aardige aanzet welke me inspireerde voor het in elkaar sleutelen van de volgende oplossing:
Een paar sh scripts met de volgende functionaliteit:
1. Ongewenste SMTP logins bannen middels de ingebouwde firewall `iptables`
2. Ongewenste IMAP/POP logins bannen middels de ingebouwde firewall `iptables`
3. Bij syteem reboot deze firewall rules opnieuw laden1. Ongewenste SMTP logins bannen middels de ingebouwde firewall `iptables`Dit is het script
smtp_block.sh geworden. Het scant de /var/log/messages file voor eerder genoemde smtp login attempts en wanneer een IP adres meer dan MAX_ATTEMPTS voor komt word het ipadres geblocked in de Linux firewall `iptables`. Tevens word het IP gelogd in een iplog bestand zodat bij een systeem reboot deze IP's weer kunnen worden toegevoegd aan de firewall.
Resultaten worden gelogd in /var/log/messages.
Dit script dient te worden gestart vanuit crond door een regel toe te voegen aan /etc/crontab:
*/5 * * * * root /volume1/smtp_block/smtp_block.sh
(Hierbij zorgt */5 dat het script elke 5 minuten word uitgevoerd.)
Update 3 november 2013: kleine bug fix in onderstaand script (bijlage ook geupdate)smtp_block.sh (ook als bijlage bij dit bericht te vinden)
#!/bin/sh
# Remvs - October 2013
# Script for the Synology NAS system.
# Scan /var/log/messages for smtp failed login attempts. When number of failed attempts > MAX_ATTEMPTS: block.
# Use iptables to block the bad guys. Also log the banned IP in a separate log file for re-blocking after a system reboot.
#
# Looking for attempts on existing and non-existing users. For example:
# Jul 25 08:42:37 postfix/smtpd[11235]: warning: xxxxx[xxx.xxx.xxx.xxx]: SASL PLAIN authentication failed authentication failure
# Jul 25 17:02:40 postfix/smtpd[30649]: warning: unknown[xxx.xxx.xxx.xxx]: SASL LOGIN authentication failed: authentication failure
#
# Credits: awk logic & inspriration from the script by jroselarsen @ http://forum.synology.com/enu/viewtopic.php?f=145&t=50723#p210120
#### CONFIG #####
IPLOG=/var/log/banip.log # File with banned IPs
SYSLOG=/var/log/messages # System log to read login attempts & log script results
MAX_ATTEMPTS=3 # Max. number of failed login attempts before block
#################
#Scan SYSLOG for failed smtp login attempts. if a single IP has MAX_ATTEMPTS or more failed attepts block it.
grep "SASL PLAIN\|SASL LOGIN" $SYSLOG | awk 'BEGIN {FS="["}; {print $3}' | awk -v max_attempts=$MAX_ATTEMPTS 'BEGIN {FS="]"}; {try[$1]++; }
END { for (h in try) if (try[h]>max_attempts) print h; }' |
while read ip
do
echo $ip
#Skip empty IP strings.
[ -z "$ip" ] && continue
#Check if IP is already blocked.
iptables -L -n | grep $ip > /dev/null
if [ $? -eq 1 ]; then
#IP not yet blocked in IPtables; check if already present in IPLOG
grep "$ip" $IPLOG > /dev/null
if [ $? -eq 1 ]; then
#IP not in IPLOG, so add it
echo "$(date +%Y%m%d-%T) - banned IP [$ip]" >> $IPLOG
logger -p WARNING "banip SMTP: Added $ip to $IPLOG"
#echo "$(date +%Y%m%d-%T) banip SMTP: added $ip to $IPLOG" >> $SYSLOG
else
logger -p WARNING "banip SMTP: Banned $ip already in $IPLOG"
#echo "$(date +%Y%m%d-%T) banip SMTP: Banned $ip already in $IPLOG" >> SYSLOG
fi
#Add to IPtables
iptables -I INPUT -s $ip -j DROP
logger -p WARNING "banip SMTP: Added $ip to iptables"
fi
done
2. Ongewenste IMAP/POP logins bannen middels de ingebouwde firewall `iptables`Dit is het script
imap_block.sh geworden. Het werkt in principe hetzelfde als het hierboven beschreven script op twee punten na:
a. Het leest niet het /var/log/messages bestand, maar een mail log file die standaard niet word geschreven in DSM (meer hierover later)
b. Het voorziet in een 'white list' functionaliteit die ervoor zorgt dat je niet perongeluk jezelf, of 127.0.0.1 buitensluit wanneer je bijvoorbeeld via webmail een paar keer verkeerd inlogt.
Ook dit script logt de gebande IP's naar een(hetzelfde) iplog bestand voor herbruik na een reboot.
Resultaten worden gelogd in /var/log/messages
De mislukte IMAP/POP login attempts worden standaard niet gelogd in DSM. Dus om dit script te kunnen gebruiken dien je dit eerst aan te zetten.
Dit doe je door in de dovecot config file /volume1/@appstore/MailServer/etc/dovecot.conf de volgende regel toe te voegen:
info_log_path = /var/log/mail_info.log
Hierdoor zal Dovecot al het login verkeer (en meer) loggen. Dit bestand groeit snel. (Een TODO is dus een log rotatie te maken.)
Het (b)lijkt dat bij sommige DSM versies het config bestand van Dovecot word gerefreshed bij een (re)boot! Als dit het geval is kun je het *.sh scriptje dat onder punt 3. besproken wordin usr/local/etc/rc.d de volgende inhoud toevoegen:
#!/bin/sh
echo "info_log_path = /var/log/mail_info.log" >> /volume1/@appstore/MailServer/etc/dovecot.conf
Dit zorgt bij een systeem boot ervoor dat de info were wor dgelogd (NIET GETEST; IK WEET NIET ZEKER OF DIT SCRIPT WORD UITGEVOERD VOORDAT DOVECOT WORD GESTART)Lees mijn post hieronder voor de oplossing voor bovenstaandeDit script dient te worden gestart vanuit crond door een regel toe te voegen aan /etc/crontab:
*/5 * * * * root /volume1/smtp_block/imap_block.sh
(Hierbij zorgt */5 dat het script elke 5 minuten word uitgevoerd.)
imap_block.sh (ook als bijlage bij dit bericht te vinden)
#!/bin/sh
# Remvs - October 2013
# Script for the Synology NAS system.
# Scan MAILLOG for IMAP/POP failed login attempts. When number of failed attempts > MAX_ATTEMPTS: block.
# Use iptables to block the bad guys. Also log the banned IP in a separate log file for re-blocking after a system reboot.
#
# Looking for attempts on POP3 and IMAP. For example:
# dovecot: Oct 27 00:12:55 Info: pop3-login: Aborted login (auth failed, 1 attempts): user=<test>, method=PLAIN, rip=xxx.xxx.xxx.xxx, lip=yyy.yyy.yyy.yyy
# dovecot: Oct 27 00:12:55 Info: pop3-login: Disconnected (auth failed, 1 attempts): user=<test@domain.com>, method=PLAIN, rip=xxx.xxx.xxx.xxx, lip=yyy.yyy.yyy.yyy
# dovecot: Oct 25 00:09:29 Info: imap-login: Disconnected (auth failed, 1 attempts): user=<abc>, method=PLAIN, rip=xxx.xxx.xxx.xxx, lip=yyy.yyy.yyy.yyy, secured
#
# Credits: awk logic & inspriration from the script by jroselarsen @ http://forum.synology.com/enu/viewtopic.php?f=145&t=50723#p210120
#### CONFIG #####
IPLOG=/var/log/banip.log # File with banned IPs
MAILLOG=/var/log/mail_info.log # Mail info log to read login attempts
SYSLOG=/var/log/messages # System log to log script results
MAX_ATTEMPTS=0 # Max. number of failed login attempts before block
WHITELIST="192.168.*;127.0.0.1;0.0.0.0;119.*"
#################
export IFS=";"
#Scan MAILLOG for failed IMAP/POP login attempts. if a single IP has MAX_ATTEMPTS or more failed attepts block it.
grep "\(pop3-login\|imap-login\).*auth failed" $MAILLOG | #<-- grep all relevant entries from the MAILLOG and pipe
awk 'BEGIN {FS="rip="}; {print $2}' | #<-- take all after "rip="
awk -v max_attempts=$MAX_ATTEMPTS 'BEGIN {FS=", lip"}; #<-- take all before ", lip" (also: pass $MAX_ATTEMPTS to awk script), and pipe
{try[$1]++}; #<-- add to array, and/or increase array value when already present
END { for (h in try)
if (try[h]>max_attempts) print h; #<-- finally, loop over array and print all entries that have a value > max_attempts
}
' | #<-- and pipe
while read ip
do #<-- process all entries (that occure > $MAX_ATTEMPTS times)
#Skip empty IP strings.
[ -z "$ip" ] && continue
#Check IP against white list; if found; set $MATCH=1
MATCH=0
for word in $WHITELIST; do
echo $ip | grep "^$word" > /dev/null #<-- check IP against white list using REGEX, starting at begin of string(^)
if [ $? -ne 1 ]; then
#Match found
MATCH=1
break
fi
done
if [ $MATCH -eq 0 ]; then
#Not whitelisted
#Check if IP is already blocked.
iptables -L -n | grep $ip > /dev/null
if [ $? -eq 1 ]; then
iptables -I INPUT -s $ip -j DROP #<-- add blocking rule to iptables
logger -p WARNING "banip IMAP: Added $ip to iptables"
#IP not yet blocked in IPtables -> check if already present in IPLOG
grep "$ip" $IPLOG > /dev/null
if [ $? -eq 1 ]; then
#IP not in IPLOG, so add it
echo "$(date +%Y%m%d-%T) - IMAP banned IP [$ip]" >> $IPLOG
logger -p WARNING "banip IMAP: Added $ip to $IPLOG"
else
logger -p WARNING "banip IMAP: Banned $ip already in $IPLOG"
fi
fi
#else
#IP is whitelisted *commented!*
# logger -p WARNING "banip IMAP: IP $ip is whitelisted"
fi
done
unset IFS
3. Bij syteem reboot deze firewall rules opnieuw ladenDit is het script
banip_reload.shDit script leest de IP adressen uit het iplog bestand en voegt deze toe aan de linux firewall `iptables`. Resultaten worden gelogd in /var/log/messages.
Om ervoor te zorgen dat dit script word utegvoerd bij een (re)boot dien je een klein scriptje toe te voegen aan /usr/local/etc/rc.d/. Alles in deze directory word bij een boot opgestart.
LET OP: de @reboot event in crond werkt niet bij Synology DSM! Deze dus maar beter niet gebruiken.#!/bin/sh
# Joris Bots - October 2013
# File location: /usr/local/etc/rc.d
# Execute on startup
# Scan /var/log/banip.log for banned IP's
# Use iptables to block these
# Script to be run on system boot up to re-add blocked IP's logged by smtp_block.sh & imap_block.sh
sh /volume1/smtp_block/banip_reload.sh # point to the location of the banip_reload.sh file!
# Re-add mail_info log to dovecot config; as this is removed after a reboot.
echo "info_log_path = /var/log/mail_info.log" >> /volume1/@appstore/MailServer/etc/dovecot.conf
banip_reload.sh (ook als bijlage bij dit bericht te vinden)
#!/bin/sh
# scan /var/log/banip.log for banned ip's
# use iptables to block these
# script to be run on system boot up to re-add blocked ip's logged by smtp_block.sh
# Starteb by a script in /usr/local/etc/rc.d
# !!to have it start at boot time (cron does not work for that)
# banip.log format:
#20130726-13:54:01 - banned IP [123.139.247.204]
#20130726-13:54:01 - banned IP [62.49.101.65]
##### CONFIG ####
IPLOG=/var/log/banip.log
#################
logger -p WARNING "Start 'banip reload' script ${0}"
logger -p WARNING "banip RELOAD: Reading $IPLOG to add banned ip's to iptables"
# local function to do the looping
# needed to ensure COUNT variable isvisible at the end of the piped command
myloop(){
COUNT_N=0 #new count
COUNT_E=0 #existing count
COUNT_T=0 #total count
COUNT_X=0 #error count
while read ip;
do
# Skip empty ip strings
[ -z "$ip" ] && continue
let COUNT_T=COUNT_T+1
iptables -L -n | grep $ip > /dev/null
if [ $? -eq 1 ] ; then
# Ip not found in IPtables
iptables -I INPUT -s $ip -j DROP
if [ $? -eq 0 ] ; then
# sucesfully added to iptables
let COUNT_N=COUNT_N+1
else
# could not add to iptables. Not a valid IP?
let COUNT_X=COUNT_X+1
fi
else
let COUNT_E=COUNT_E+1
fi
done;
logger -p WARNING `printf "banip RELOAD: %5d IP's read from $IPLOG\n" "$COUNT_T"`
logger -p WARNING `printf "banip RELOAD: %5d banned IP's re-added to IPtables\n" "$COUNT_N"`
logger -p WARNING `printf "banip RELOAD: %5d banned IP's skipped; Already in IPtables\n" "$COUNT_E"`
logger -p WARNING `printf "banip RELOAD: %5d banned IP's could not be added to IPtables\n" "$COUNT_X"`
}
#Read banip.log entries, extract the IP addresses and for the whole set of the IPS perform myloop()
cat $IPLOG | awk 'BEGIN {FS="["}; {print $2}' | awk 'BEGIN {FS="]"}; {print $1};' | myloop
Groeten,
Remvs
Kleine disclaimer:
Ik ben niet heel ervaren met Linux of shell scripting. Gebruik bovenstaande op eigen risico. Als je vragen hebt, zal ik ze proberen te beantwoorden.
Verbeteringen zijn erg welkom!
Credits and thanks to jroselarsen @ http://forum.synology.com/enu/viewtopic.php?f=145&t=50723#p210120 for the awk logic and inspiration!