[แจก] Script รายงานการส่งเมล์ประจำวันสำหรับเครื่องที่ใช้ DA

เนื่องจากปัจจุบันมี server ถูกเจาะเพื่อใช้ส่ง spam ออกไปจำนวนมาก
ไม่ว่าจะมาจากการดักขโมยรหัสหรือเดารหัสผ่านแล้วเข้ามาส่ง spam ออกไป
หรือวางไฟล์ผ่านช่องโหว่ของ script แล้วส่งเมล์ออกไป
หรือส่งผ่านระบบ contact us / tell a friend / register ที่เป็นแบบฟอร์มต่างๆหน้าเว็บ ที่กรอกได้โดยไม่มี captcha หรือ captcha ไม่แข็งแรงพอ bot สามารถอ่านออก
ผู้ดูแล server หรือ ผู้เช่า vps ที่ต้องดูแลเองแต่ขาดความรู้ ก็ละเลยในการดูแลตรวจสอบ ทำให้ระบบส่ง spam ออกไปทุกวันอย่างไม่รู้ตัว (เพราะระบบไม่ล่ม ก็ไม่สนใจ)
จนในที่สุด IP ก็ติด blacklist และเมื่อ ip ใน class ใหนติดกันเยอะๆ ก็อาจพาลให้ติดยก class พาคนอื่นเดือนร้อนกันไปด้วย

วันนี้จึงนำ script ที่ใช้อยู่เองมาแบ่งปันให้เอาไปใช้กันฟรีๆ (ช่วยเอาไปใช้กันด้วย) อย่างน้อยเราก็รู้ตัวว่า server เราส่งเมล์ออกไปมากผิดปกติภายไม่เกิน 1-2 วัน ซึ่งปกติจะยังไม่ทันติด blacklist

[HR][/HR]
ขั้นแรกให้แก้ไขให้ระบบทำการ rotate log ของ exim ทุกวัน โดยแก้ไขไฟล์ /etc/logrotate.d/exim (สำหรับ CentOS)
โดยเพิ่ม daily และกำหนด rotate ตามจำนวนวันที่ต้องการให้เก็บย้อนหลัง


/var/log/exim/mainlog /var/log/exim/processlog /var/log/exim/rejectlog /var/log/exim/paniclog {
sharedscripts
rotate 14
daily

[HR][/HR]
อันนี้คือตัว script ที่เอามาแจก

Script รายงานการส่งเมล์ประจำวัน (Filename: mail_report.sh)


#!/bin/sh
#
#Mail Report Script by KKE, support@pinkkeyhost.com
#Filename: mail_report.sh
#
echo "Status of $(date +'%a %d %b %Y %H:%M')"
echo "Mail send by account (present status)"
ls -l /etc/virtual/usage/ | grep -v '\.' | awk '{print $5" "$NF}' | sort -nr
log="/var/log/exim/mainlog"$1
echo "Processing log: $log"
echo ""
echo ""
echo "Mail send by Login"
echo ""
grep '<=' $log | grep 'A=login' | awk -FA=login: '{print $2}' | awk '{print $1}' | sort | uniq -c | sort -nr
echo ""
echo ""
echo "Mail send by Apache"
echo ""
grep '<=' $log | grep 'U=apache' | awk '{print $5}' | sort | uniq -cd | sort -nr
echo ""
echo ""
echo "Login fail count"
echo ""
grep 'login authenticator failed' $log | awk -Fset_id= '{print $2}' | awk -F\) '{print $1}' | sort | uniq -cd | sort -nr
echo ""
echo ""
echo "Fail IP Lists"
echo ""
grep 'login authenticator failed' $log | awk -F\[ '{print $2}' | awk -F\] '{print $1}' | sort -n | uniq -cd | sort -nr
echo ""
echo ""

ปล. อย่าลืม chmod +x เพื่อให้ไฟล์ execute ได้
โหลดไฟล์ได้ตามนี้
#wget -O /root/mail_report.sh 61.19.246.211/support/CentOS/mail_report.sh
#chmod 755 /root/mail_report.sh

ค่า Mail send by account นั้นเอามาจากใน /etc/virtual/usage จะเป็นค่าปัจจุบัน ณ เวลานั้นๆ และค่าจะถูก reset เป็น 0 หลังเที่ยงคืน ถ้ากำหนด cron หลังเที่ยงคืนจะไม่ได้ค่านี้
และระบบจะไม่นับจำนวนให้หากกำหนดค่า limit ไว้เป็น 0 ดังนั้นต้องกำหนดค่า limit (/etc/virtual/limit) มากกว่า 0 (หรือจะกำหนดผ่านหน้า da ก็ได้ตามสะดวก)
ค่าอื่นๆที่เหลือประมวลจาก exim mainlog หากต้องการดูรายงานของ log วันก่อนๆเช่น mainlog.1 ก็ให้ใส่ .1 ต่อท้าย #./mail_report.sh .1
โดยในคำสั่ง uniq ใส่ -d เข้าไปด้วยเพื่อตัดผลลัพธ์ที่มีแค่ 1 ทิ้งไป จะได้ไม่ยาวเกินไป หากต้องการที่มีแค่ 1 ด้วยก็เอา d ออก เหลือ -c พอ

[HR][/HR]
กำหนด cron ให้ส่งเมล์ทุกวันก่อนเที่ยงคืน โดยสร้างไฟล์ /etc/cron.d/mail_report ใส่ข้อมูลดังนี้
58 23 * * * root /root/mail_report.sh | mail -s “Daily mail report for [hostname]” youremail@domain.com

[HR][/HR]
ตัวอย่าง output จากโปรแกรม

Status of Sat 20 Apr 2013 23:58
Mail send by account
248 userxx
53 userxx
50 userxx
44 userxx
37 uesrxx
32 userxx
28 userxx
7 userxx
4 userxx
4 userxx
1 userxx
1 userxx

Mail send by Login

35 xxx@domainxx.co.th
12 xxx@domainxx.co.th

4 xxx@domainxx.com
2 xxx@domainxx.co.th
2 xxx@domainxx.co.th

Mail send by Apache

182 user@domainxx.com
33 user@domainxx.com

4 user@domainxx.com

Login fail count

185 user@domainxx.com
183 nouser

17 user@domainxx.com

Fail IP Lists

366 112.90.196.6

8 218.18.184.22
6 198.100.99.93
2 222.240.161.147

[HR][/HR]
การแก้ปัญหาคร่าวๆ

หากพบว่า user ใหนส่งเมล์เกิน limit ก็วิเคราะห์จาก report ส่วนล่าง ว่าส่งผ่าน account หรือ apache แล้วไปแก้ไข
ถ้า ส่งผ่าน user@domain.com ก็ไปเปลี่ยน password ของ user นั้นๆไว้ก่อน (ก็ดูเอาว่าเป็น account หลักเลย หรือ account ที่สร้างเพิ่มอีกที)
ถ้าส่งผ่าน apache ก็ดูว่า โดนวางไฟล์ หรือส่งผ่านแบบฟอร์มต่างๆของเว็บ
ถ้า โดนวางไฟล์ใน folder ที่ chmod 777 ไว้ เบื้องต้นก็ลบไฟล์ที่โดนวางทิ้งและ chmod folder เป็น 755 เอาไว้ก่อนเพื่อกันไม่ให้วางไฟล์ได้อีก จนกว่าจะอุดช่องโหว่ของ script ได้แล้วจึง chmod 777 กลับเหมือนเดิม
ถ้า ส่งผ่านแบบฟอร์มหน้าเว็บก็แก้ code หา captcha มาใส่ หรือถ้ามี captcha อยู่แล้วแปลว่ามันกันไม่อยู่ ให้หาเปลี่ยน captcha ตัวใหม่ (แนะนำ captchazdr แล้วหา font แปลกๆมาใส่ หรือใช้ recaptcha และจะให้ดีใช้ร่วมกับให้กรอกข้อความภาษาไทยในช่องช่วยได้เยอะ)

การลบเมล์คิวบานเบอะ
/etc/init.d/exim stop; mv /var/spool/exim /var/spool/exim.xxx; /etc/init.d/exim restart;
rm -Rf /var/spool/exim.xxx (ก่อนลบอาจเข้าไปไล่ดูเมล์ที่ค้างในนั้นว่าส่งจากใหนไปใหนอย่างไร ตรงกับที่เจอใน report หรือเปล่า)
การที่มีเมล์ค้างอยู่ในคิวเยอะๆ แปลว่าไม่ได้กำหนด limit ไว้ หรือ เมล์ที่ส่งไม่สามารถส่ง error report ได้ คือมันไม่ีระบุ sender หรือ return address ไว้ หรือ return ไม่มีตัวตน

การลบเมล์ตีกลับใน user
เมื่อ user มีการส่งเมล์เกิน limit ที่เรากำหนดไว้ เมล์ส่วนที่เกินจะถูกตีกลับถึง user นั้นๆ ซึ่งจะมีจำนวนมาก
ถ้าเป็น user ที่มีการใช้งานอีเมล์อยู่ประจำ อาจต้องเข้าไปลบผ่าน webmail เพื่อป้องกันเมล์เก่าๆหาย
แต่ส่วนมากมักจะเป็น account หลักของระบบ ไม่มีการใช้งาน เราก็ลบ folder ทิ้งไปได้เลย
เช่น user abc ส่ง spam ออกไป โดยถูกเดารหัสผ่าน เราก็เปลี่ยนรหัสผ่านของ user abc ใหม่ซะก่อน แล้วก็ลบไฟล์ใน /home/abc/Maildir/new ทิ้ง
#cd /home/abc/Maildir
#rm -Rf new
(ก่อนลบก็เปิดสุ่มๆดูซัก 3-4 ฉบับ ว่าส่งจากใหนอย่างไร แก้ปัญหาให้เสร็จก่อนค่อยลบทิ้ง)

หากเป็น user ที่สร้างเพิ่ม ไม่ใช่ user หลักใน da จะอยู่ใน /home/[user]/imap/[domain.com]/[mailuser]/Maildir/new (ถ้าเมล์เปิดเช็คไปแล้วก็จะไปอยู่ใน cur)
#/home/[user]/imap/[domain.com]/[mailuser]/Maildir
ลบไฟล์ที่ไม่เกิน 1 วัน
#find new/ -type f -mtime -1 -exec rm -f {} “;”
หรือถ้าไม่สนใจเมล์เก่า(ซึ่งน่าจะอยู่ใน cur)ก็ลบ new ทิ้งทั้ง folder เหมือนข้างบนได้เลย
#rm -Rf new

(ก่อนลบก็เปิดสุ่มๆดูซัก 3-4 ฉบับ ว่าส่งจากใหนอย่างไร แก้ปัญหาให้เสร็จก่อนค่อยลบทิ้ง)

:th_059_:

ขอบคุณมากครับพี่แมน

เป็นประโยชน์มากเลยครับ

มีประโยชน์มากครับขอบคุณครับ ^^

ขอบคุณครับ

สุโค่ย มากครับ ขอบคุณครับ :d5f02ecd:

ขอบคุณครับพี่แมน ผมลองเอาไปใช้กับ debian ต้องแก้เป็น
ls -l /etc/virtual/usage/ | grep -v ‘.’ | awk ‘{print $5" "[COLOR=#ff0000][U][B]$8[/B][/U][/COLOR]}’ | sort -nr

ขอบคุณครับ

ขอบคุณครับ

ใน debian แสดงวันที่ต่างออกไปใช้ - คั่นแทน space เลยน้อยลงไป column นึง
-rw-rw---- 1 root mail 100 2013-04-22 11:11 abc
-rw-rw---- 1 root mail 100 Apr 22 11:11 abc

เพื่อให้ใช้ได้ทั้งคู่ขอแก้ code เป็นแบบนี้แทนครับ


ls -l /etc/virtual/usage/ | grep -v '\.' | awk '{print $5" "[COLOR=#ff0000][U][B]$NF[/B][/U][/COLOR]}' | sort -nr

ส่งมาถ้า mail ที่ส่งออกเยอะๆ ก็เปิดไม่ไหวหรือเปล่าครับ :slight_smile:

ย้ายเข้า Articles/ How-to

เท่าที่ใช้งานกับหลายๆเครื่อง เมล์ฉบับนึงปกติก็ไม่เกิน 100 บรรทัด ครับ
ถ้าหากส่วนใหนมันเยอะเิกินไป ก็ปรับแก้ได้ตามต้องการ หลัง sort -nr ก็เพิ่ม | head -n 50 เข้าไป เพื่อเอาแค่ 50 บรรทัด แรกพอ เพราะผลลัพธ์เรียงลำดับจากมากไปน้อยอยู่แล้ว เราต้องการดูแค่อันที่มากผิดปกติ
เท่าที่ใช้งานมา ส่วนที่เยอะสุดก็จะเป็น fail ip list เพราะมาได้จากหลากหลาย IP
ส่วนรายงานอีเมล์ส่งออกยังไงก็มีได้ไม่เกินจำนวน email account ในเครื่องนั้นๆ ถ้ามันเยอะจัดจริงๆก็เพิ่ม head เข้าไปแบบข้างบน

ผมว่าระบบมันมี bug เรื่องภาษาแล้วล่ะ

ตกลงว่ามันจะ ตอบ: หรือมันจะ Re: ตอบกันไปตอบกันมา มันยาวขึ้นเรื่อยๆ
[B]ตอบ: Re: ตอบ: Re: ตอบ: Re: …[/B]


[add by admin: ใช่แล้ววววว]

อันนี้กด reply ใต้ post ครับ

ส่วนอันนี้กด reply ใต้กระทู้

ขออนุญาตแก้เพิ่มนิดหน่อย ให้รองรับ mod_ruid2 นะครับ (ของเดิมมัน detect หา user ที่ส่งด้วย U=apache ถ้าใช้ ruid แล้วมันจะไม่เจอ)

#!/bin/sh#
#Mail Report Script by KKE, support@pinkkeyhost.com

echo “Status of $(date +‘%a %d %b %Y %H:%M’)”
echo “Mail send by account (present status)”
ls -l /etc/virtual/usage/ | grep -v ‘.’ | awk ‘{print $5" "$NF}’ | sort -nr
log=“/var/log/exim/mainlog”$1
echo “Processing log: $log”
echo “”
echo “”
echo “Mail send by Login”
echo “”
grep ‘<=’ $log | grep ‘A=login’ | awk -FA=login: ‘{print $2}’ | awk ‘{print $1}’ | sort | uniq -c | sort -nr
echo “”
echo “”
echo “Mail send by Local MTA service”
echo “”
grep ‘<=’ $log | grep ’ P=local ’ | awk ‘{print $6, $5}’ | sort | uniq -cd | sort -nr
echo “”
echo “”
echo “Login fail count”
echo “”
grep ‘login authenticator failed’ $log | awk -Fset_id= ‘{print $2}’ | awk -F) ‘{print $1}’ | sort | uniq -cd | sort -nr
echo “”
echo “”
echo “Fail IP Lists”
echo “”
grep ‘login authenticator failed’ $log | awk -F[ ‘{print $2}’ | awk -F] ‘{print $1}’ | sort -n | uniq -cd | sort -nr
echo “”
echo “”

แก้เพิ่มตรงบรรทัดนี้ด้วย เวอร์ชั่นใหม่มันมี folder user_ids เพิ่มขึ้นมา

ls -l /etc/virtual/usage/ | grep -v '\.' | grep -v '_ids' | awk '{print $5" "$NF}' | sort -nr 

ผมทำตามแล้วครับ ้าไม่มีข้อความอะไรมาในเมล์เลยนี้คือไม่ส่งเหรอครับ หรือผมทำผิด ?

รบกวนสอบถามครับ

ของผมเป็น CentOS ลองทำตามวิธี ทุกอย่างแล้ว

ระบบได้ส่งจดหมายมา แต่ไม่มีรายละเอียดใดๆ เลย ควรแก้ยังไงดีครับ

ขอบคุณครับ :slight_smile:

ลองสั่งรันสคริป mail_report.sh ดูใน SSH