คู่มือ

Fail2ban: ตั้งค่าการป้องกัน SSH จากการเดารหัสผ่าน

อัปเดต: · Skillaria.Top

Fail2ban อ่านล็อกของบริการ ตรวจพบความพยายามเข้าสู่ระบบที่ล้มเหลวซ้ำๆ และบล็อก IP ของผู้โจมตีชั่วคราวผ่านไฟร์วอลล์ เพื่อป้องกัน SSH ให้ติดตั้งแพ็กเกจ สร้าง /etc/fail2ban/jail.local พร้อมส่วน [sshd] (enabled = true, maxretry, findtime, bantime) แล้วรีสตาร์ตบริการ ตรวจสถานะด้วย fail2ban-client status sshd

Fail2ban เป็นดีมอนที่เฝ้าดูล็อกของบริการ ตรวจจับความพยายามเข้าสู่ระบบที่ล้มเหลวซ้ำๆ และบล็อก IP ที่ส่งความพยายามนั้นเป็นเวลาหนึ่ง สำหรับ SSH นี่คือการป้องกันการเดารหัสผ่านที่ง่ายที่สุด เพราะบอตจะหยุดยิงเซิร์ฟเวอร์หลังจากพลาดไม่กี่ครั้ง ด้านล่างเป็นการตั้งค่า fail2ban ตั้งแต่การติดตั้ง การตรวจการแบน ไปจนถึงข้อผิดพลาดที่พบบ่อย

ทำไมต้องใช้ fail2ban ในเมื่อมี SSH key แล้ว

เซิร์ฟเวอร์ใดที่เปิดพอร์ต 22 จะเริ่มได้รับความพยายามเข้าสู่ระบบจากบอตภายในไม่กี่นาทีหลังเปิดเครื่อง ลองดูเองได้:

$ sudo journalctl -u ssh --since "1 hour ago" | grep -c "Failed password"
412

หากปิดการล็อกอินด้วยรหัสผ่านและใช้เฉพาะคีย์ การเดาการเข้าถึงแทบเป็นไปไม่ได้ แต่ fail2ban ยังมีประโยชน์: ช่วยลดสิ่งรบกวนในล็อก ลดภาระจากการเชื่อมต่อนับพัน และป้องกันความผิดพลาดด้านการตั้งค่า เมื่อการล็อกอินด้วยรหัสผ่านถูกเปิดกลับโดยไม่ตั้งใจ นี่คือชั้นป้องกันที่สอง ไม่ใช่ทางเลือกแทนคีย์

fail2ban ทำงานอย่างไร

ตรรกะประกอบด้วยสามส่วน:

  • ฟิลเตอร์ (filter) — ชุดนิพจน์ปรกติที่หาบรรทัดความล้มเหลวในล็อกและดึง IP ออกมา ฟิลเตอร์อยู่ใน /etc/fail2ban/filter.d/
  • แอ็กชัน (action) — สิ่งที่ทำกับผู้ทำผิด เช่น เพิ่มกฎใน iptables, nftables, ufw หรือ firewalld แอ็กชันอยู่ใน /etc/fail2ban/action.d/
  • เรือนขัง (jail) — การรวมกันของฟิลเตอร์ แอ็กชัน แหล่งล็อก และเกณฑ์ เช่น jail sshd เฝ้าล็อกของ SSH

หากในช่วง findtime มี IP หนึ่งตรงกับเงื่อนไขครบ maxretry ครั้ง IP นั้นจะถูกแบนเป็นเวลา bantime เมื่อครบกำหนดการแบนจะถูกยกเลิกอัตโนมัติ

การติดตั้ง fail2ban

บน Debian และ Ubuntu:

sudo apt update
sudo apt install fail2ban

บน RHEL, Rocky, AlmaLinux แพ็กเกจอยู่ในที่เก็บ EPEL:

sudo dnf install epel-release
sudo dnf install fail2ban

เปิดการเริ่มอัตโนมัติและตรวจสถานะของบริการ:

sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban

บน Debian และ Ubuntu jail ของ SSH เปิดอยู่แล้วตามค่าเริ่มต้นผ่าน /etc/fail2ban/jail.d/defaults-debian.conf ส่วนในตระกูล RHEL หลังติดตั้งไม่มีอะไรเปิดอยู่ ต้องเปิด jail ด้วยตนเอง

ที่เก็บการตั้งค่า: jail.conf และ jail.local

ไฟล์หลักคือ /etc/fail2ban/jail.conf แต่ไม่ควรแก้ไข เพราะจะถูกเขียนทับเมื่อแพ็กเกจอัปเดต การตั้งค่าของตนเองให้ใส่ใน /etc/fail2ban/jail.local หรือในไฟล์แยก /etc/fail2ban/jail.d/*.local fail2ban อ่านไฟล์ตามลำดับนี้ และแต่ละไฟล์ทับค่าของไฟล์ก่อนหน้า:

  1. jail.conf
  2. jail.d/*.conf
  3. jail.local
  4. jail.d/*.local

ไม่ควรคัดลอก jail.conf ทั้งไฟล์ไปเป็น jail.local เพราะจะแช่แข็งค่าเริ่มต้นเก่าไว้ ใน jail.local ให้เขียนเฉพาะสิ่งที่เปลี่ยน

ตั้งค่า fail2ban สำหรับ SSH: jail.local ขั้นต่ำ

สร้างไฟล์:

sudo nano /etc/fail2ban/jail.local

และเพิ่มเนื้อหานี้:

[DEFAULT]
# ที่อยู่ของเราที่ไม่ควรแบนเด็ดขาด
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
bantime  = 1h
findtime = 10m
maxretry = 5
# แหล่งล็อก: จอร์นัลของ systemd หรือไฟล์
backend  = systemd

[sshd]
enabled  = true
port     = ssh
maxretry = 3

รีสตาร์ตบริการและตรวจว่า jail ทำงานแล้ว:

$ sudo systemctl restart fail2ban
$ sudo fail2ban-client status
Status
|- Number of jail:      1
`- Jail list:   sshd

ความหมายของพารามิเตอร์

พารามิเตอร์ความหมายตัวอย่าง
enabledjail เปิดอยู่หรือไม่true
portพอร์ตที่จะบล็อกผู้ทำผิดssh, 2222, ssh,2222
maxretryจำนวนความผิดพลาดที่ยอมได้ก่อนแบน3
findtimeช่วงเวลาที่นับความผิดพลาด10m
bantimeระยะเวลาการแบน; -1 คือถาวร1h, 1d
ignoreipIP และซับเน็ตที่ไม่แบน10.0.0.0/8
backendแหล่งล็อกsystemd, auto
logpathพาธไฟล์ล็อกเมื่อใช้ backend แบบไฟล์/var/log/auth.log
banactionใช้ไฟร์วอลล์ใดในการแบนnftables-multiport, ufw

ระบุเวลาพร้อมหน่วยได้: s, m, h, d, w ตัวเลขที่ไม่มีหน่วยถือเป็นวินาที

backend: systemd หรือไฟล์

บน Debian 12 และ Ubuntu 24.04 รุ่นใหม่ อาจไม่มีไฟล์ /var/log/auth.log หาก rsyslog ไม่ได้ติดตั้ง เพราะล็อก SSH อยู่ในจอร์นัลของ systemd เท่านั้น จึงต้องใช้ backend = systemd มิฉะนั้น fail2ban จะไม่เริ่มทำงานและแจ้งว่าหาไฟล์ล็อกไม่พบ หาก rsyslog ติดตั้งอยู่ จะใช้แบบไฟล์ก็ได้:

[sshd]
enabled  = true
backend  = auto
logpath  = /var/log/auth.log

บนระบบตระกูล RHEL ไฟล์ที่เทียบเท่าคือ /var/log/secure

SSH บนพอร์ตที่ไม่ใช่ค่าเริ่มต้น

หาก sshd ฟังบนพอร์ต 2222 ให้ระบุพอร์ตนั้นใน jail มิฉะนั้น fail2ban จะบล็อกพอร์ต 22 แต่การโจมตียังดำเนินต่อบนพอร์ต 2222:

[sshd]
enabled = true
port    = 2222

หากต้องการบล็อกผู้ทำผิดจากทุกพอร์ต ใช้แอ็กชัน iptables-allports หรือ nftables-allports ผ่านพารามิเตอร์ banaction

เลือกไฟร์วอลล์: iptables, nftables, ufw, firewalld

ค่าเริ่มต้นบน Debian คือ banaction = nftables (ในเวอร์ชันเก่าใช้ iptables) และบน RHEL คือ firewalld หากเซิร์ฟเวอร์ตั้งค่า ufw ไว้ การแบนควรปรากฏใน ufw ด้วย:

[DEFAULT]
banaction = ufw

สำหรับ firewalld:

[DEFAULT]
banaction = firewallcmd-rich-rules

ตรวจว่ากฎถูกเพิ่มจริงด้วย sudo nft list ruleset | grep f2b หรือ sudo iptables -L -n | grep f2b เพราะ fail2ban สร้างเชนที่มีคำนำหน้า f2b-

วิธีตรวจการทำงาน: fail2ban-client status

เครื่องมือควบคุมหลักคือ fail2ban-client สถานะของ jail หนึ่งตัว:

$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 2
|  |- Total failed:     147
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 4
   |- Total banned:     38
   `- Banned IP list:   45.148.10.12 92.118.39.7 185.224.128.40 218.92.0.112

ที่นี่จะเห็นจำนวนความผิดพลาดในช่วงปัจจุบัน จำนวน IP ที่ถูกแบน และรายชื่อของ IP เหล่านั้น หากต้องการทดสอบการป้องกันจริง ให้ลองล็อกอินด้วยรหัสผ่านผิดหลายครั้งจากเครื่องอื่น (ไม่ใช่เครื่องที่อยู่ใน ignoreip) หลังความพยายามครั้งที่สาม การเชื่อมต่อจะไม่สามารถสร้างได้อีก

ล็อกของ fail2ban เองอยู่ที่ /var/log/fail2ban.log:

$ sudo tail -n 3 /var/log/fail2ban.log
2026-10-14 09:12:41,118 fail2ban.filter  [812]: INFO    [sshd] Found 218.92.0.112
2026-10-14 09:12:44,302 fail2ban.filter  [812]: INFO    [sshd] Found 218.92.0.112
2026-10-14 09:12:47,551 fail2ban.actions [812]: NOTICE  [sshd] Ban 218.92.0.112

วิธีปลดแบน IP ใน fail2ban

หากคุณหรือเพื่อนร่วมงานถูกแบนโดยไม่ตั้งใจ ให้ปลดแบนจากคอนโซลของเซิร์ฟเวอร์ (ผ่านแผงควบคุมของโฮสติ้งหรือจาก IP อื่น):

sudo fail2ban-client set sshd unbanip 203.0.113.25

ปลดแบนทุกรายการในทุก jail:

sudo fail2ban-client unban --all

แบน IP ด้วยตนเองโดยไม่รอให้ฟิลเตอร์ทำงาน:

sudo fail2ban-client set sshd banip 198.51.100.7

เพื่อไม่ให้เหตุการณ์เดิมเกิดซ้ำ ให้เพิ่ม IP คงที่หรือซับเน็ตของสำนักงานลงใน ignoreip

การแบนแบบเพิ่มระยะเวลาสำหรับผู้ทำผิดซ้ำ

บอตจำนวนมากกลับมาทันทีหลังถูกปลดแบน ตั้งแต่เวอร์ชัน 0.11 fail2ban รองรับการเพิ่มระยะเวลาแบนสำหรับผู้ทำผิดซ้ำ:

[DEFAULT]
bantime = 1h
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 4w

การแบน IP เดิมแต่ละครั้งจะนานกว่าครั้งก่อน แต่ไม่เกินสี่สัปดาห์ ทางเลือกสำหรับเวอร์ชันเก่าคือ jail recidive ซึ่งอ่านล็อกของ fail2ban เองและแบนระยะยาวให้กับ IP ที่ปรากฏหลายครั้ง:

[recidive]
enabled  = true
logpath  = /var/log/fail2ban.log
bantime  = 1w
findtime = 1d
maxretry = 5

ตรวจฟิลเตอร์: fail2ban-regex

หาก jail ทำงานแต่ไม่แบนใคร ให้ตรวจว่าฟิลเตอร์พบบรรทัดในล็อกจริงหรือไม่ สำหรับไฟล์ล็อก:

sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

สำหรับจอร์นัลของ systemd:

sudo fail2ban-regex systemd-journal sshd

ในผลลัพธ์ให้ดูบรรทัด Lines: ... matched หากจับคู่ได้ศูนย์ แสดงว่าฟิลเตอร์ไม่เข้ากับรูปแบบล็อกหรือระบุแหล่งผิด ก่อนรีสตาร์ตควรตรวจไวยากรณ์การตั้งค่าทั้งหมด:

sudo fail2ban-client -t

ข้อผิดพลาดที่พบบ่อย

  • บริการไม่เริ่ม: «Have not found any log file for sshd jail». ไม่มี /var/log/auth.log ตั้ง backend = systemd หรือติดตั้ง rsyslog
  • มีการแบนในสถานะ แต่การโจมตียังดำเนินต่อ. ระบุพอร์ตผิด (SSH ถูกย้ายพอร์ต) หรือกฎไฟร์วอลล์ถูกบดบังด้วยกฎอนุญาตที่อยู่ก่อนหน้า ตรวจ port และผลของ nft list ruleset
  • การเปลี่ยนแปลงไม่มีผล. แก้ jail.conf แต่ jail.local หรือ jail.d/*.local มีค่าอื่นอยู่ ดูค่าที่มีผลจริง: sudo fail2ban-client get sshd maxretry
  • ล็อกเอาตัวเองออก. ปลดแบนผ่านคอนโซล แล้วเพิ่ม IP ลงใน ignoreip
  • Fail2ban ใน Docker ไม่เห็นการโจมตี. พอร์ตของคอนเทนเนอร์ถูกเผยแพร่ผ่านเชน DOCKER ซึ่งข้าม INPUT สำหรับบริการเช่นนี้ให้ใช้ chain = DOCKER-USER ในแอ็กชัน

การป้องกัน SSH เพิ่มเติม

fail2ban ทำงานได้ดีที่สุดร่วมกับการตั้งค่าพื้นฐานใน /etc/ssh/sshd_config:

PasswordAuthentication no
PermitRootLogin no
MaxAuthTries 3

หลังแก้ไขให้ตรวจการตั้งค่าด้วย sudo sshd -t แล้วรีสตาร์ตบริการ อย่าปิดเซสชันปัจจุบันจนกว่าจะยืนยันในเซสชันใหม่ว่าการล็อกอินด้วยคีย์ทำงาน นอกจากนี้ยังจำกัดการเข้าถึง SSH ในระดับไฟร์วอลล์ให้เหลือเฉพาะที่อยู่ที่จำเป็นได้

สรุป

การตั้งค่า fail2ban สรุปได้เป็นไม่กี่ขั้นตอน: ติดตั้งแพ็กเกจ สร้าง jail.local พร้อมส่วน [sshd] เลือก backend และพอร์ตที่ถูกต้อง ตั้งค่า maxretry, findtime และ bantime เพิ่มที่อยู่ของตนเองใน ignoreip และตรวจผลด้วย fail2ban-client status sshd เมื่อใช้ร่วมกับการล็อกอินด้วยคีย์เท่านั้น จะปกป้อง SSH จากการเดารหัสผ่านได้อย่างมีประสิทธิภาพ การป้องกันเซิร์ฟเวอร์และ fail2ban ถูกอธิบายพร้อมตัวอย่างจริงในคอร์ส Linux

คำถามที่พบบ่อย

จำเป็นต้องใช้ fail2ban หรือไม่ หากปิดการล็อกอินด้วยรหัสผ่านแล้ว?

ไม่จำเป็น แต่มีประโยชน์ มันช่วยลดความพยายามขยะหลายพันครั้งออกจากล็อก ลดภาระ และเป็นการป้องกันเผื่อกรณีที่มีคนเปิดการล็อกอินด้วยรหัสผ่านกลับมาโดยไม่ตั้งใจ

จะดู IP ที่ถูกแบนทั้งหมดในทุก jail ได้อย่างไร?

รัน sudo fail2ban-client banned เพื่อแสดงรายการ IP ที่ถูกบล็อกในแต่ละ jail สำหรับ jail เดียวใช้ fail2ban-client status sshd

การแบนยังอยู่หลังเซิร์ฟเวอร์รีบูตหรือไม่?

อยู่ fail2ban เก็บการแบนไว้ในฐานข้อมูล SQLite (/var/lib/fail2ban/fail2ban.sqlite3) และกู้คืนการแบนที่ยังมีผลตอนเริ่มทำงาน เว้นแต่พารามิเตอร์ dbpurgeage จะลบไปก่อนแล้ว

fail2ban ป้องกันบริการอื่นนอกจาก SSH ได้หรือไม่?

ได้ มีฟิลเตอร์สำเร็จรูปสำหรับ nginx, Apache, Postfix, Dovecot และบริการอื่นๆ เพียงเปิด jail ที่ต้องการใน jail.local เช่น [nginx-http-auth] ด้วย enabled = true

fail2ban ต่างจากการจำกัดในไฟร์วอลล์อย่างไร?

ไฟร์วอลล์อนุญาตหรือปฏิเสธที่อยู่แบบคงที่ ส่วน fail2ban แบนแบบไดนามิกสำหรับผู้ที่แสดงพฤติกรรมไม่ดีในล็อก ทั้งสองมักใช้ร่วมกัน: whitelist ในไฟร์วอลล์ และ fail2ban สำหรับส่วนที่เหลือ

เรียนหัวข้อนี้ผ่านวิดีโอ

หัวข้อนี้สอนอย่างละเอียดพร้อมฝึกปฏิบัติในคอร์ส “Linux: с нуля до уверенного администрирования”

ไปที่คอร์ส