前言:
自建郵件主機 Linux + postfix + dovecot
除了垃圾郵件過濾末過於帳號被猜中而被半夜
大量寄信隔日被列入黑名單窘境
另因內部系統異常透過程式自動發eMail告急,確無
人處理造成郵件主機癱渙.
時至今日因工作上主管決定購買商業郵件伺服器,而
得以卸職機會.將所處理這方面經驗釋出給與需要人參考.
環境要求:
1).只適合本機帳號 (/etc/passwd)
2).不適用於海外工作者需大量寄信(建議用 vpn 克服)
3).利用 bash script 所攥寫.透過 crond 執行
會產生報表 report.txt
白名單設在 iptables.deny 及被 blocaking ip 也會寫入此檔
透過 /etc/rc.local 每次重開機重新執行 iptables.deny 內容
不足之處:
1).未來希望有高人補足 ad 使用者 或 mysql 帳號資料庫整合檢查
主程式: Check_eMail.sh
#!/bin/bash
#
# test --> sh -x ChekMail-num.sh
#
cat /dev/null > now_list.txt
cat /dev/null > temp.txt
cat /dev/null > log.txt
cat /dev/null > report.txt
echo " " >> report.txt
echo "-=---------------------------=-" >> report.txt
echo " The process ! " >> report.txt
echo "-=---------------------------=-" >> report.txt
LIMIT=10
if [ "$(date +'%d')" -lt 10 ]; then
nn=`date +'%b %d'`
cat /var/log/maillog | grep "$(echo $nn | sed 's/0/ /g')" > maillog
else
cat /var/log/maillog | grep "$(date +'%b %d')" > maillog
fi
user_name=$(awk -F':' '$3>=500{print $1}' /etc/passwd)
for loop in $user_name
do
echo -n "$loop," >> now_list.txt
cat ./maillog | grep sasl_username=$loop | wc -l >> now_list.txt
done
for loop in $user_name
do
num=$(cat before_list.txt | grep "$loop" | cut -d ',' -f 2 | head -n 1)
num1=$(cat now_list.txt | grep "$loop" | cut -d ',' -f 2 | head -n 1)
num2=$((num1 - num))
if [ "$num2" -ge "$LIMIT" ] ; then
echo "$loop,1" >> log.txt
fi
done
# +++ remove user list ...
sed -i '/aaa/d' log.txt
sed -i '/bbb/d' log.txt
# +++ function_name
check_bulk_mailling(){
# 4. Check local ip send email number > 10000
cat before_list.txt | sort -n -t ',' -k 2 -r | head -n 5 > log.txt
sed -i '/aaa/d' log.txt
sed -i '/bbb/d' log.txt
user_name=$(awk -F',' '{print $1}' ./log.txt)
f_LIMIT=3000
echo " " >> report.txt
echo "-=-----------------------------------=-" >> report.txt
echo " Display bulk mailing Local IP! " >> report.txt
echo "-=-----------------------------------=-" >> report.txt
for loop in $user_name
do
cat ./maillog | grep sasl_username=$loop | awk -F' ' '{print $7}' \
| cut -d '[' -f 2 | cut -d ']' -f 1 > temp.txt
sort temp.txt | uniq -c | sort -n -t ' ' -k 1 -r | head -n 5 > ip_list.txt
f_num=$( cat ip_list.txt | awk -F' ' '{print $1}' )
for loop1 in $f_num
do
hit_ip=$( cat ip_list.txt | grep $loop1 | awk -F' ' '{print $2}' )
if [ `echo "$loop1" | awk '{print int($0)}'` -ge "$f_LIMIT" ] ; then
f_num2=$( iptables -L -n | grep "$hit_ip" | wc -l )
if [ $f_num2 = '0' ]; then
/sbin/iptables -I INPUT -i $networkcard -s $hit_ip -j DROP
echo "IP: $hit_ip ; Num: $loop1 ; Id: $loop is drop" >> report.txt
# exit 0
else
echo "IP: $hit_ip ; Num: $loop1 ; Id: $loop is drop" >> report.txt
fi
fi
done
done
}
if [ -z log.txt ] ; then
mv -f now_list.txt before_list.txt
check_bulk_mailling
exit 0
fi
# -=--------------------------------------------------=-
#
cat /dev/null > temp.txt
cat /dev/null > dropip.txt
BAD_LIST="./temp.txt"
user_name=$(awk -F',' '{print $1}' ./log.txt)
for loop in $user_name
do
cat ./maillog | grep sasl_username=$loop | awk -F' ' '{print $7}' \
| cut -d '[' -f 2 | cut -d ']' -f 1 >> temp.txt
done
for i in $( cat $BAD_LIST | sort -u )
do
{
# hit=$(cat $BAD_LIST | egrep -o "$i" | wc -l)
if [ `echo $i | cut -d \. -f 1` != "10" ] ; then
if [ `echo $i | cut -d \. -f 1` == "172" ] && [ `echo $i | cut -d \. -f 2` == "17" ] && \
[ `echo $i | cut -d \. -f 3` == "2" ] ; then
echo "Bypass ip: $i " >> report.txt # ByPass 172.17.2.x
else
echo "$i" >> dropip.txt
fi
fi
}
done
# -=--------------------------------------------------=-
#
cat ./dropip.txt | sort -t '.' -k1n,1 -k2n,2 -k3n,3 -k4n,4 -o dropip.txt
denyfilepath="/etc/rc.d/iptables.deny"
target1=`cat ./dropip.txt`
networkcard="eth0"
declare -i k=0
if [ `cat \./dropip.txt | wc -l` -eq "0" ] ; then
echo "No IP Address Drop" >> report.txt
mv -f now_list.txt before_list.txt
check_bulk_mailling
exit 0
fi
for i in $target1; do
if [ -f "$denyfilepath" ]; then
target2=`cat $denyfilepath | grep $i`
else
echo "# 1??.1??.1.1??" > $denyfilepath
echo "# 2??.6?.1??.1??" >> $denyfilepath
fi
if [ "$target2" = "" ]; then
if [ $k -eq 0 ]; then
echo " " >> $denyfilepath
echo "#-=--------------------------------------------------------------------------=- " >> $denyfilepath
echo "# ChekMail-num.sh "`date` >> $denyfilepath
fi
echo -n "/sbin/iptables -A INPUT -i "'$EXTIF'" -s $i -j DROP" >> $denyfilepath
lname=$(cat ./maillog | grep sasl_username | grep "$i" | cut -d "=" -f 4 | head -n 1)
echo " # --- use LoginName $lname " >> $denyfilepath
declare -i k=$k+1
/sbin/iptables -I INPUT -i $networkcard -s $i -j DROP
# echo "IP: $i Add to $denyfilepath"
echo "(new)IP: $i to use as drop" >> report.txt
else
lname=$(cat report.txt | grep "$i" | wc -l )
if [ $lname -eq '0' ]; then
echo "IP: $i to use as drop" >> report.txt
fi
fi
done
# 2.
# -=--------------------------------------------------=-
#
echo " " >> report.txt
echo "-=-----------------------------------=-" >> report.txt
echo " Display TOP 10 User ! " >> report.txt
echo "-=-----------------------------------=-" >> report.txt
cat ./log.txt >> report.txt
echo " " >> report.txt
echo "-=----------------------------------------------------=-" >> report.txt
echo " Use ip , Login Name , Number of times " >> report.txt
echo "-=----------------------------------------------------=-" >> report.txt
num=$( cat dropip.txt | wc -l )
if [ $num -ge "0" ]; then
for i in $(cat ./dropip.txt)
do
cat ./maillog | grep sasl_username | grep "$i" | cut -d "=" -f 4 | head -n 1 > lname.txt
echo -n "$i," >> report.txt
for j in $(cat lname.txt)
do
echo -n "$j," >> report.txt
cat ./maillog | grep sasl_username="$j" | grep "$i" | wc -l >> report.txt
done
done
fi
mv -f now_list.txt before_list.txt
# 3.
today=`/bin/date +"%F"`
timestamp=`/bin/date +"%F %T"`
user_name=$(awk -F',' '{print $1}' ./log.txt)
for loop in $user_name
do
hit=$(cat report.txt | egrep -o "$loop" | wc -l)
hit=$((hit - 1))
if [ "$hit" -ge "$LIMIT" ] ; then
echo $today@home! | passwd --stdin $loop
echo "$timestamp eMail account: $loop " >> Lock_eMail.txt
fi
done
# 4. Check local ip send email number > 10000
check_bulk_mailling
II. 報表 report.txt 內容
# more report.txt
-=---------------------------=-
The process !
-=---------------------------=-
IP: 127.0.0.1 to use as drop
IP: 110.64.194.132 to use as drop
-=-----------------------------------=-
Display TOP 10 User !
-=-----------------------------------=-
cpril,1
school,1
-=----------------------------------------------------=-
Use ip , Login Name , Number of times
-=----------------------------------------------------=-
127.0.0.1,school,1
110.64.194.132,school,6
-=-----------------------------------=-
Display bulk mailing Local IP!
-=-----------------------------------=-
iii. 白名單檔內容 iptables.deny
# more /etc/rc.d/iptables.deny
# Valid IP List
# -=-----------------=-
# 110.64.194.132
# 120.228.202.173
# 121.147.1.146
# 57.123.45.135
# 127.0.0.1
#-=--------------------------------------------------------------------------=-
# ChekMail-num.sh Thu Oct 15 18:31:32 CST 2020
/sbin/iptables -A INPUT -i $EXTIF -s 61.60.203.139 -j DROP # --- use LoginName ann
敬請諸位參考!
可以考慮採用 Policyd 來搭配,它還有 Web UI 可以使用。
用SASL + SSL來解決外網連接發信的問題
用 fail2ban 來解決駭客踹密碼的問題
至於公司內的合法大量發信的需求,只能用人事規範要求,無法也難以禁止,至於發信速率你可以在postfix內拉大處理時間
至於駭客盜用你們信箱帳密的事,我覺得機率微乎其微,人家也沒必要用你們的主機來狂發信,只要確定你們沒做SPF + DMARC + DKIM做防偽造信件的話,用其他沒反relay的smtp server,就能偽造發信人成你們的郵箱域名,然後你們就RBLed!所以你們一定要做好SPF + DMARC + DKIM,長篇大論,自行到GOOGLE搜尋,很多教學
這裡也有郵箱測試工具可用
https://mxtoolbox.com/
https://www.mail-tester.com/
(拿不到8分就有很大的問題了,gmail是滿分10分)
https://talosintelligence.com/
volume超過3就要開始內部檢討了