ล็อกอินผิดมากเกิน แบนซะด้วย fail2ban

หากเซิร์ฟเวอร์ของคุณตั้งอยู่บนอินเตอร์เน็ต เพื่อให้บริการเว็บไซต์หรืออื่นๆ และคุณจำเป็นต้องเปิด SSH เพื่อสามารถ login เข้าไปตรวจสอบสถานะของเครื่องได้

คุณต้องเคยเจอปัญหานี้แน่นอน คือมีการพยายามเจาะระบบด้วยการ ssh เข้ามา ด้วย user, password ต่างๆ ที่คาดว่าจะมีในเครื่อง

ตัวอย่างไฟล์ /var/log/secure แสดงถึงการพยายาม ssh แต่ไม่สำเร็จ

May  2 16:39:27 server sshd[8309]: Invalid user john from x.x.x.x
May  2 16:39:27 server sshd[8310]: input_userauth_request: invalid user john
May  2 16:39:27 server sshd[8309]: pam_unix(sshd:auth): check pass; user unknown
May  2 16:39:27 server sshd[8309]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=x.x.x.x
May  2 16:39:27 server sshd[8309]: pam_succeed_if(sshd:auth): error retrieving information about user john
May  2 16:39:29 server sshd[8309]: Failed password for invalid user john from x.x.x.x port 3291 ssh2
May  2 16:39:29 server sshd[8310]: Received disconnect from x.x.x.x: 11: Bye Bye
 

การป้องกัน หรือคำแนะนำอย่างแรก ที่พึงกระทำคือ ตั้ง user, password ให้ยากต่อการคาดเดา แต่เท่านั้นอาจไม่เพียงพอ

บทความนี้ขอเสนอวิธีการป้องกันด้วย fail2ban ซึ่งจะช่วยแบน ip ที่พยายาม login แต่ไม่สำเร็จได้

หลักการทำงานคร่าวๆ คือ โปรแกรม fail2ban จะคอยตรวจสอบไฟล์ที่ตั้งไว้ โดยค้นหาคำหรือประโยคที่เกิดขึ้นในไฟล์ เมื่อมีการ failed attempts เกิดขึ้นถึงจำนวนครั้งที่กำหนด fail2ban จะทำการบางอย่างที่ตั้งไว้ เช่น รันคำสั่ง iptables เพื่อ DROP packets ได้

ติดตั้งไฟล์ rpm

ในที่นี้ทดสอบบน Fedora 14 ต้องติดตั้งไฟล์ rpm เพิ่มเติมดังนี้

[root@fc14-x64 ~]# rpm -ivh gamin-python-0.1.10-8.fc14.x86_64.rpm
[root@fc14-x64 ~]# rpm -ivh shorewall-4.4.11.1-1.fc14.noarch.rpm
[root@fc14-x64 ~]# rpm -ivh fail2ban-0.8.4-25.fc14.noarch.rpm

เพื่อความชัดเจนในการทดสอบ จะรันคำสั่ง service iptables stop เพื่อเคลียร์ rule ของ iptables ทั้งหมดออกก่อน

[root@fc14-x64 ~]# service iptables stop
iptables: Flushing firewall rules:                         [  OK  ]
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
iptables: Unloading modules:                               [  OK  ]

ใช้คำสั่ง iptables เพื่อแสดง rule ที่ใช้งานอยู่

[root@fc14-x64 ~]# iptables -L -v -n
Chain INPUT (policy ACCEPT 46 packets, 3176 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 40 packets, 5272 bytes)
 pkts bytes target     prot opt in     out     source               destination

ใช้คำสั่ง service เพื่อสตาร์ต fail2ban

[root@fc14-x64 ~]# service fail2ban start
Starting fail2ban:                                         [  OK  ]

ใช้คำสั่ง ps เพื่อดูโปรเซสของ fail2ban

[root@fc14-x64 ~]# ps -ef | grep fail2ban
root      1151     1  0 23:32 ?        00:00:00 /usr/bin/python /usr/bin/fail2ban-server -b -s /var/run/fail2ban/fail2ban.sock -x

ดูในไฟล์ /var/log/messages แสดงการเริ่มต้นทำงานของ fail2ban

[root@fc14-x64 ~]# tail /var/log/messages
May  6 23:35:32 fc14-x64 fail2ban.server : INFO   Changed logging target to SYSLOG for Fail2ban v0.8.4
May  6 23:35:32 fc14-x64 fail2ban.jail   : INFO   Creating new jail 'ssh-iptables'
May  6 23:35:32 fc14-x64 fail2ban.jail   : INFO   Jail 'ssh-iptables' uses Gamin
May  6 23:35:32 fc14-x64 fail2ban.filter : INFO   Added logfile = /var/log/secure
May  6 23:35:32 fc14-x64 fail2ban.filter : INFO   Set maxRetry = 5
May  6 23:35:32 fc14-x64 fail2ban.filter : INFO   Set findtime = 600
May  6 23:35:32 fc14-x64 fail2ban.actions: INFO   Set banTime = 600
May  6 23:35:32 fc14-x64 fail2ban.jail   : INFO   Jail 'ssh-iptables' started

ดีฟอลต์คอนฟิกไฟล์ rpm ที่ได้มาจาก Fedora 14 จะตรวจสอบเฉพาะการพยายาม SSH โดยดูในไฟล์ /var/log/secure

fail2ban จะสร้าง rule และ chain ใหม่ขึ้นมา ใน iptables

[root@fc14-x64 ~]# iptables -L -v -n
Chain INPUT (policy ACCEPT 92 packets, 7885 bytes)
 pkts bytes target     prot opt in     out     source               destination
   53  4052 fail2ban-SSH  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 84 packets, 8087 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain fail2ban-SSH (1 references)
 pkts bytes target     prot opt in     out     source               destination
   53  4052 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0

 

ไฟล์คอนฟิกของ fail2ban

ไฟล์คอนฟิกของ fail2ban อยู่ใน /etc/fail2ban/

ไฟล์ /etc/fail2ban/jail.conf จะเป็นการกำหนดการทำงานของ fail2ban

คอนฟิกบางส่วนจากไฟล์ jail.conf

[root@fc14-x64 ~]# cat /etc/fail2ban/jail.conf
...
[DEFAULT]
...
# "bantime" is the number of seconds that a host is banned.
bantime  = 600
# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime  = 600
...
[ssh-iptables]
enabled  = true
filter   = sshd
action   = iptables[name=SSH, port=ssh, protocol=tcp]
           sendmail-whois[name=SSH, dest=root, sender=fail2ban@mail.com]
logpath  = /var/log/secure
maxretry = 5

คำอธิบายคร่าวๆ จากไฟล์ jail.conf คือ ให้ตรวจสอบ (filter) การ ssh โดยดูในไฟล์ (logpath) /var/log/secure ว่า ถ้ามีการ failed login เกิน (maxretry) ครั้ง ภายในเวลา (findtime) 600 วินาที ให้ทำการ (action) รัน iptables ด้วยออปชั่นในวงเล็บ

สามารถดูรายละเอียด filter ในไฟล์ /etc/fail2ban/filter.d/sshd.conf

[root@fc14-x64 ~]# cat /etc/fail2ban/filter.d/sshd.conf
...
[Definition]
_daemon = sshd
...
failregex = ^%(__prefix_line)s(?:error: PAM: )?Authentication failure for .* from <HOST>\s*$
            ^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
            ^%(__prefix_line)sFailed (?:password|publickey) for .* from <HOST>(?: port \d*)?(?: ssh\d*)?$
            ^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
            ^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from <HOST>\s*$
            ^%(__prefix_line)sUser \S+ from <HOST> not allowed because not listed in AllowUsers$
            ^%(__prefix_line)sauthentication failure; logname=\S* uid=\S* euid=\S* tty=\S* ruser=\S* rhost=<HOST>(?:\s+user=.*)?\s*$
            ^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
            ^%(__prefix_line)sAddress <HOST> .* POSSIBLE BREAK-IN ATTEMPT!*\s*$
            ^%(__prefix_line)sUser \S+ from <HOST> not allowed because none of user's groups are listed in AllowGroups$

คำอธิบายจากไฟล์คอนฟิก filter คือ ให้ตรวจสอบหาคำหรือประโยคที่ระบุไว้ใน failregex (regular expression)

ส่วน action ที่ทำ หลังจาก maxretry ดูได้ในไฟล์  /etc/fail2ban/action.d/iptables.conf

[root@fc14-x64 ~]# cat /etc/fail2ban/action.d/iptables.conf
...
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
...
actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP

คำอธิบาย คือการรันคำสั่ง iptables เพื่อสร้าง rule เพื่อจะ ban <ip> ที่พยายามเข้ามา

และเมื่อเกินเวลา (bantime) 600 วินาที แล้ว ก็รันคำสั่ง iptables เพื่อลบ rule ที่สร้างขึ้น อนุญาตให้ <ip> สามารถเข้ามาได้อีกครั้ง

ทดสอบการ login fail

คำเตือน การทดลองใช้ fail2ban ให้ลองบนเครื่องที่สามารถ console ได้  เพราะการคอนฟิกหรือลอง login fail จะทำให้คุณไม่สามารถ ssh เข้าเครื่องนั้นได้ ช่วงเวลาหนึ่ง

สมมุติให้ลอง ssh login fail ด้วย root จาก 192.168.1.12

ดูไฟล์ /var/log/secure ที่เกิดขึ้นบน server

[root@fc14-x64 ~]# tail -f /var/log/secure
May  6 23:43:47 fc14-x64 unix_chkpwd[1340]: password check failed for user (root)
May  6 23:43:47 fc14-x64 sshd[1338]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.12  user=root
May  6 23:43:49 fc14-x64 sshd[1338]: Failed password for root from 192.168.1.12 port 34811 ssh2
May  6 23:43:56 fc14-x64 unix_chkpwd[1342]: password check failed for user (root)
May  6 23:43:58 fc14-x64 sshd[1338]: Failed password for root from 192.168.1.12 port 34811 ssh2
May  6 23:44:00 fc14-x64 unix_chkpwd[1343]: password check failed for user (root)
May  6 23:44:01 fc14-x64 sshd[1338]: Failed password for root from 192.168.1.12 port 34811 ssh2
May  6 23:44:01 fc14-x64 sshd[1339]: Connection closed by 192.168.1.12
May  6 23:44:01 fc14-x64 sshd[1338]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.12  user=root
May  6 23:44:16 fc14-x64 unix_chkpwd[1348]: password check failed for user (root)
May  6 23:44:16 fc14-x64 sshd[1346]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.12  user=root
May  6 23:44:19 fc14-x64 sshd[1346]: Failed password for root from 192.168.1.12 port 34812 ssh2
May  6 23:44:22 fc14-x64 unix_chkpwd[1349]: password check failed for user (root)
May  6 23:44:25 fc14-x64 sshd[1346]: Failed password for root from 192.168.1.12 port 34812 ssh2
May  6 23:44:25 fc14-x64 sshd[1347]: Connection closed by 192.168.1.12
May  6 23:44:25 fc14-x64 sshd[1346]: PAM 1 more authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.12  user=root

เมื่อ login fail เกินค่า maxretry ที่ตั้งไว้ ในที่นี้คือ 5 ครั้ง สังเกตในไฟล์ /var/log/messages  โปรแกรม fail2ban จะทำการ action ขึ้นมา เพื่อ ban 192.168.1.12

[root@fc14-x64 ~]# tail /var/log/messages
May  6 23:44:27 fc14-x64 <28>fail2ban.actions: WARNING [ssh-iptables] Ban 192.168.1.12

ใช้คำสั่ง iptables เพื่อตรวจสอบ rule ที่เพิ่มขึ้น

[root@fc14-x64 ~]# iptables -L -v -n
Chain INPUT (policy ACCEPT 61 packets, 10699 bytes)
 pkts bytes target     prot opt in     out     source               destination
  453 37587 fail2ban-SSH  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 60 packets, 7044 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain fail2ban-SSH (1 references)
 pkts bytes target     prot opt in     out     source               destination
    2   120 DROP       all  --  *      *       192.168.1.12            0.0.0.0/0
  451 37467 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0

สังเกตว่า rule ที่สร้างขึ้น จะ DROP เฉพาะการ ssh (tcp 22) เท่านั้น แปลว่า ip ที่ถูก ban ไป จะไม่สามารถ ssh เข้าเครื่อง server ได้อีก แต่ยังสามารถเปิด web (tcp 80) หรืออื่นๆ ได้ตามปกติ

คอนฟิกในไฟล์ jail.conf เมื่อมีการ ban เกิดขึ้น จะมีการส่ง mail หา root ด้วย

ตัวอย่าง mail ที่ส่งให้ root

From fail2ban@mail.com  Fri May  6 23:44:28 2011
Return-Path: <fail2ban@mail.com>
Date: Fri, 6 May 2011 23:44:27 +0700
Subject: [Fail2Ban] SSH: banned 192.168.1.12
From: Fail2Ban <fail2ban@mail.com>
To: root@fc14-x64.example.com
Status: R
Hi,
The IP 192.168.1.12 has just been banned by Fail2Ban after 5 attempts against SSH.
...

เมื่อเวลาผ่านไป เกินเวลา bantime ในที่นี้ 600 วินาที  โปรแกรม fail2ban ก็จะปลดการ ban ออก ดูได้จากไฟล์ /var/log/messsages

[root@fc14-x64 ~]# tail /var/log/messages
May  6 23:44:27 fc14-x64 <28>fail2ban.actions: WARNING [ssh-iptables] Ban 192.168.1.12
May  6 23:54:28 fc14-x64 <28>fail2ban.actions: WARNING [ssh-iptables] Unban 192.168.1.12

ใช้คำสั่ง iptables เพื่อตรวจสอบ rule ที่ใช้งานอยู่ หลังจาก unban

[root@fc14-x64 log]# iptables -L -v -n
Chain INPUT (policy ACCEPT 561 packets, 50572 bytes)
 pkts bytes target     prot opt in     out     source               destination
 1753  141K fail2ban-SSH  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 501 packets, 50410 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain fail2ban-SSH (1 references)
 pkts bytes target     prot opt in     out     source               destination
 1751  141K RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0

 

ลองนำไปใช้ดูครับ เพิ่มความปลอดภัยให้เครื่องได้อีกระดับ

ข้อมูลอ้างอิง

Leave a Reply