SSD Nodes Learn Hosting plans →
คู่มือ Matt Connorโดย Matt Connor

วิธีติดตั้ง Fail2ban บน Ubuntu 24.04 ป้องกัน SSH บอท

เรียนรู้วิธีติดตั้ง Fail2ban บน Ubuntu 24.04 เพื่อป้องกันการสุ่มรหัสผ่าน SSH พร้อมวิธีตรวจสอบสถานะด้วย fail2ban-client และวิธีแก้ไขปัญหาหากค่า Total failed ยังคงเป็น 0

การทำงานจริงของ Fail2ban

Fail2ban คือ daemon สำหรับอ่าน log โดยจะคอยตรวจสอบข้อความการยืนยันตัวตนของ SSH และหากพบความล้มเหลวจากที่อยู่ IP เดียวกันหลายครั้งภายในระยะเวลาสั้นๆ โปรแกรมจะรันคำสั่ง firewall เพื่อบล็อกที่อยู่ IP นั้นชั่วคราว นี่คือแนวคิดหลักทั้งหมดของมัน การตั้งค่ามีเพียงประมาณ 30 บรรทัดในไฟล์เดียว และบน Ubuntu 24.04 การติดตั้งทำได้ด้วยคำสั่ง apt เพียงคำสั่งเดียว ซึ่งจะช่วยปกป้องระบบให้คุณทันทีโดยไม่ต้องแก้ไขค่าใดๆ

ต้องทำความเข้าใจให้ชัดเจนว่ามันคืออะไรและไม่ใช่สิ่งใด Fail2ban ไม่ได้ทำหน้าที่ยืนยันตัวตนผู้ใช้ ไม่ได้เข้ารหัสข้อมูลใดๆ และไม่ได้หยุดยั้งความพยายามในการล็อกอินที่มุ่งมั่นเพียงครั้งเดียว แต่จะหยุดยั้งเฉพาะการพยายามซ้ำๆ จากแหล่งที่มาเดิมเท่านั้น มันเป็นเพียงตัวกรองสัญญาณรบกวนและตัวจำกัดอัตราการเข้าถึง ไม่ใช่แม่กุญแจ หน้าที่ของมันคือการทำให้การสแกนพอร์ต 22 ที่เกิดขึ้นอยู่ตลอดเวลาในเบื้องหลังไม่มาสิ้นเปลือง CPU, แบนด์วิดท์ และพื้นที่จัดเก็บ log ของคุณ รวมถึงช่วยชะลอผู้โจมตีที่ต้องใช้ที่อยู่ IP เดียวในการพยายามเข้าถึงระบบ

สิ่งที่ Fail2ban ไม่สามารถทดแทนได้

Fail2ban เป็นปราการชั้นที่ 3 ไม่ใช่ชั้นที่ 1 หากเซิร์ฟเวอร์ของคุณยังยอมรับการล็อกอินด้วยรหัสผ่าน SSH บอทเน็ตที่กระจายตัวอยู่ตามหมายเลข IP นับพันอาจพยายามเดารหัสผ่านต่อไปได้เรื่อยๆ เนื่องจากแต่ละหมายเลข IP จะยังคงอยู่ต่ำกว่าเกณฑ์การแบนที่คุณตั้งไว้และไม่ถูกบล็อก การป้องกันที่แท้จริงสำหรับกรณีนี้คือการใช้การยืนยันตัวตนด้วย key-only authentication ซึ่งทำให้การเดารหัสผ่านเป็นไปไม่ได้ไม่ว่าจะมีการพยายามกี่ครั้งก็ตาม การใช้ Fail2ban ควบคู่ไปกับการยืนยันตัวตนด้วย key-only authentication มีประโยชน์ 2 ประการ คือช่วยลดสัญญาณรบกวนจากการพยายาม brute-force ใน log ของคุณ และช่วยคัดกรองตัวสแกนออกไปตั้งแต่เนิ่นๆ เพื่อไม่ให้พวกมันรบกวนพอร์ตของคุณอย่างต่อเนื่อง ให้มองว่านี่คือการป้องกันเชิงลึก (defence in depth) โดย Fail2ban จะทำงานอยู่เบื้องหลังการยืนยันตัวตนด้วย key และอยู่หลัง firewall เสมอ ไม่ใช่ทำงานอยู่หน้าสิ่งเหล่านี้

ข้อกำหนดเบื้องต้นและความเป็นจริงบน Ubuntu 24.04

คุณจำเป็นต้องมี VPS ที่รัน Ubuntu 24.04 โดยมีสิทธิ์ root หรือ sudo และมีการตั้งค่า SSH ให้ใช้งานได้แล้ว ซึ่งควรเป็นการยืนยันตัวตนด้วย key Fail2ban เป็นซอฟต์แวร์ที่ใช้ทรัพยากรน้อยมาก โดยใช้ RAM เพียงไม่กี่สิบเมกะไบต์และไม่จำเป็นต้องปรับแต่งค่าจำกัดใดๆ

ส่วนนี้คือสิ่งที่คู่มือเก่าๆ มักให้ข้อมูลผิดพลาด เป็นเวลาหลายปีที่คำแนะนำมาตรฐานคือ "ติดตั้ง Fail2ban แล้วเพิ่ม backend = systemd เพราะ Ubuntu เลิกเขียน /var/log/auth.log แล้ว" คำแนะนำนั้นใช้ได้กับบาง image เท่านั้น สำหรับ Ubuntu 24.04 เวอร์ชันมาตรฐานหรือ cloud image ยังคงติดตั้ง rsyslog ซึ่งกฎเริ่มต้นจะเขียน auth,authpriv.* ลงใน /var/log/auth.log ดังนั้นบน VPS ส่วนใหญ่ ความล้มเหลวในการเข้าถึง SSH จะถูกบันทึกไว้ในไฟล์นั้นควบคู่ไปกับ systemd journal สำหรับ minimal image (Ubuntu 24.04 minimal cloud image จะไม่มี rsyslog) และ container ส่วนใหญ่จะบันทึก log ของ SSH ไว้ใน journal เท่านั้น ซึ่งในกรณีนี้ไฟล์ข้อความจะไม่มีอยู่จริง ไม่ว่าจะเป็นกรณีใด บน Ubuntu 24.04 แพ็กเกจ Fail2ban ได้จัดการเรื่องนี้ไว้แล้ว แพ็กเกจจะติดตั้ง /etc/fail2ban/jail.d/defaults-debian.conf ลงไป และไฟล์นี้เองไม่ใช่ค่าเริ่มต้นจากต้นทางที่จะเป็นตัวกำหนดการทำงานจริงของเซิร์ฟเวอร์คุณ:

[DEFAULT]
banaction = nftables
banaction_allports = nftables[type=allports]
backend = systemd

[sshd]
enabled = true

โปรดอ่านอย่างละเอียด เพราะมันจะตอบคำถามสองข้อก่อนที่คุณจะเริ่มแก้ไขค่าใดๆ backend = systemd หมายความว่า SSH jail จะอ่านจาก journal ดังนั้นจึงไม่มีผลว่า image ของคุณจะเขียน auth.log หรือไม่ banaction = nftables หมายความว่าการแบนจะถูกบังคับใช้ผ่าน nftables ซึ่งเป็น firewall ที่ Ubuntu 24.04 ใช้งานจริง แทนที่จะเป็น iptables แบบเก่า และ [sshd] enabled = true หมายความว่า jail จะเปิดใช้งานตั้งแต่การบูตครั้งแรก สรุปคือ apt install fail2ban บน Ubuntu 24.04 จะทำการแบนการทำ SSH brute-force ได้ทันทีโดยไม่ต้องตั้งค่าเพิ่ม งานส่วนใหญ่ของคุณคือการตรวจสอบการทำงาน ปรับแต่งนโยบาย และตรวจสอบให้แน่ใจว่าคุณจะไม่ล็อกตัวเองออกจากระบบ

กับดัก auth.log แบบเก่ายังคงสร้างปัญหาใน 3 สถานการณ์ ซึ่งควรทำความเข้าใจไว้: คุณติดตั้ง Fail2ban ด้วย pip แทนที่จะเป็น apt ทำให้ไม่มี defaults-debian.conf; คุณอยู่ใน unprivileged container ที่ไม่มี systemd journal ให้ตรวจสอบ; หรือคุณทำตามคู่มือเก่าและคัดลอก backend = auto ไปใส่ใน jail.local ของคุณเอง ซึ่งเป็นการเขียนทับค่าเริ่มต้นที่ทำงานได้ดีอยู่แล้ว กรณีแรกและกรณีที่สามจะทำให้การแบน SSH ล้มเหลวเฉพาะบน image ที่ไม่มี rsyslog เช่น minimal image เท่านั้น เพราะในที่ที่ rsyslog ทำงานอยู่ ตัว backend แบบไฟล์จะพบ /var/log/auth.log และทำงานได้ตามปกติ ส่วนของโหมดความล้มเหลวจะแสดงให้เห็นว่าแต่ละกรณีมีลักษณะอย่างไร

ขั้นตอนที่ 1: ติดตั้งและตรวจสอบสถานะการแบน

sudo apt update
sudo apt install -y fail2ban

Ubuntu 24.04 มาพร้อมกับ Fail2ban 1.0.2 โดยแพ็กเกจจะดึง python3-systemd มาเป็น dependency หลัก ดังนั้น backend ของ journal จึงมีทุกอย่างที่จำเป็นสำหรับการทำงาน บริการจะเปิดใช้งานและเริ่มทำงานโดยอัตโนมัติ:

sudo systemctl status fail2ban

คุณควรใช้ active (running) จากนั้นให้ตรวจสอบ jail ที่กำลังทำงานอยู่:

sudo fail2ban-client status sshd

บน VPS สาธารณะที่เปิดให้เข้าถึงได้เพียงไม่กี่นาที คุณมักจะเห็นการนับจำนวนความล้มเหลวและที่อยู่ IP ที่ถูกแบนแล้ว เนื่องจากอินเทอร์เน็ตมีการสแกนพอร์ต 22 อยู่ตลอดเวลา นี่คือหลักฐานว่าการตั้งค่าเริ่มต้นทำงานได้จริง จากจุดนี้ไปคือการปรับแต่งให้เหมาะสม ไม่ใช่การสร้างใหม่ทั้งหมดจากศูนย์

ขั้นตอนที่ 2: แก้ไขไฟล์ jail.local ห้ามแก้ไข jail.conf

Fail2ban เก็บค่าเริ่มต้นจากผู้พัฒนาไว้ใน /etc/fail2ban/jail.conf ห้ามแก้ไขไฟล์ดังกล่าว เนื่องจากการอัปเกรดแพ็กเกจอาจเขียนทับไฟล์นี้ได้ตามที่ระบุไว้ในส่วนหัวของไฟล์ ซึ่งจะทำให้การตั้งค่าของคุณสูญหาย Fail2ban จะอ่านไฟล์ตามลำดับที่กำหนดไว้ โดยเริ่มจาก jail.conf ตามด้วย jail.d/*.conf ตามลำดับตัวอักษร จากนั้นเป็น jail.local และปิดท้ายด้วย jail.d/*.local ตามลำดับตัวอักษร โดยค่าที่อ่านได้ล่าสุดจะมีผลบังคับใช้ ดังนั้น jail.local จึงเขียนทับค่าจาก defaults-debian.conf ที่มากับแพ็กเกจ แต่ไฟล์ *.local ใดๆ ที่คุณวางไว้ใน jail.d/ จะถูกอ่านหลังจากนั้นและเขียนทับค่าเดิมอีกที คุณควรเก็บการตั้งค่าที่แก้ไขไว้ในที่เดียวเพื่อให้ทราบว่าค่าใดที่กำลังใช้งานจริง ไฟล์ .local เป็นไฟล์สำหรับผู้ใช้โดยเฉพาะ ซึ่งการอัปเกรดแพ็กเกจจะไม่เข้าไปยุ่งเกี่ยว กฎเดียวกันนี้ยังใช้กับตัวกรอง (filters) โดยไฟล์ *.local จะเขียนทับไฟล์ filter.d/*.conf ที่มากับซอฟต์แวร์

ดังนั้น คุณควรสร้างไฟล์ jail.local ขนาดเล็กเพื่อเขียนทับเฉพาะการตั้งค่าที่คุณต้องการ และปล่อยให้ทั้ง jail.conf และ jail.d/defaults-debian.conf ที่มากับแพ็กเกจคงสภาพเดิมไว้เพื่อใช้เป็นข้อมูลอ้างอิง

ขั้นตอนที่ 3: เขียนไฟล์ /etc/fail2ban/jail.local

sudo nano /etc/fail2ban/jail.local

ให้ใส่เนื้อหาต่อไปนี้ลงไป โดยเปลี่ยนที่อยู่บนบรรทัด ignoreip ให้เป็น IP สาธารณะของคุณเอง:

[DEFAULT]
# Ubuntu 24.04 already sets these two in jail.d/defaults-debian.conf.
# Pinning them here documents the dependency and survives if that
# file is ever removed or changed by an upgrade.
backend   = systemd
banaction = nftables

# Ban for one hour ...
bantime  = 1h
# ... if an address fails ...
maxretry = 5
# ... 5 times within 10 minutes.
findtime = 10m

# Never ban these. PUT YOUR OWN IP HERE.
ignoreip = 127.0.0.1/8 ::1 10.0.0.24

# Longer bans for repeat offenders: 1h, 2h, 4h ... up to a week.
bantime.increment = true
bantime.maxtime   = 1w

[sshd]
enabled = true

ทุกบรรทัดมีความสำคัญดังนี้:

  • bantime, findtime, maxretry คือนโยบายการทำงาน ค่าเริ่มต้นที่มากับซอฟต์แวร์อย่าง bantime กำหนดไว้เพียง 10 นาที ซึ่ง 1 ชั่วโมงเป็นค่าเริ่มต้นที่เหมาะสมกว่า การล้มเหลว 5 ครั้งจากที่อยู่เดียวกันภายใน 10 นาทีจะนำไปสู่การแบน ผู้ใช้งานจริงอาจพิมพ์รหัสผ่านผิด 1 หรือ 2 ครั้ง แต่การผิดพลาด 5 ครั้งใน 10 นาทีมักเป็นฝีมือของสคริปต์
  • ignoreip คือมาตรการป้องกันความปลอดภัยของคุณ ให้ใส่ที่อยู่สาธารณะที่คุณใช้เชื่อมต่อ จาก ที่นั่น เพื่อให้ Fail2ban ไม่ล็อกคุณออกจากเซิร์ฟเวอร์ของตัวเอง หากคุณใช้การเชื่อมต่อจากที่บ้านที่มี IP เปลี่ยนแปลงตลอดเวลา แนะนำให้ใช้วิธี VPN ในตอนท้ายแทนการข้ามบรรทัดนี้ไป
  • bantime.increment = true ทำให้การแบนซ้ำแต่ละครั้งยาวนานขึ้นเรื่อยๆ เริ่มจาก 1 ชั่วโมง, 2 ชั่วโมง, 4 ชั่วโมง ไปจนถึง bantime.maxtime ที่อยู่ที่พยายามโจมตีซ้ำๆ จะถูกล็อกไว้นานขึ้นตามลำดับ

ให้หาที่อยู่สำหรับทำ whitelist จากเครื่องที่คุณใช้ SSH เข้ามา ไม่ใช่จากตัวเซิร์ฟเวอร์:

curl -s ifconfig.me

คุณสามารถสร้าง jail.local ที่ปรับแต่งให้เหมาะกับพอร์ตและนโยบายการแบนของคุณได้ที่นี่ จากนั้นจึงคัดลอกไปวางในไฟล์:

ToolFail2ban jail generator

ขั้นตอนที่ 4: รีสตาร์ทและตรวจสอบว่ามีการอ่าน journal

sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

-t จะทำการทดสอบไฟล์คอนฟิกก่อน ดังนั้นหากมีการพิมพ์ผิดใน jail.local ระบบจะแจ้งเตือนข้อผิดพลาดทันที แทนที่จะปล่อยให้เซอร์วิสหยุดทำงาน สถานะของ jail ที่ทำงานปกติจะมีลักษณะดังนี้:

Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     14
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 1
   |- Total banned:     3
   `- Banned IP list:   203.0.113.66

ตัวเลขที่ยืนยันว่า Fail2ban กำลังอ่านข้อมูลการล็อกอินของคุณอยู่จริงคือ Total failed หากตัวเลขนี้มากกว่าศูนย์ หรือเพิ่มขึ้นเมื่อคุณจงใจล็อกอินผิดพลาดจากเครื่องอื่น แสดงว่ามีการอ่าน journal เรียบร้อยแล้ว หากตัวเลขยังคงเป็น 0 ไม่ว่าคุณจะล็อกอินผิดพลาดกี่ครั้งก็ตาม และคุณมั่นใจว่าไม่ได้ทดสอบจากหมายเลข IP ที่ระบุใน ignoreip ให้ข้ามไปดูหัวข้อรูปแบบความล้มเหลวด้านล่าง

สังเกตว่าบรรทัด Journal matches ยังคงระบุชื่อ sshd.service อยู่ บน Ubuntu นั้น unit ของ SSH จริงๆ คือ ssh.service แต่ตัวกรองที่มากับโปรแกรมก็รองรับการจับคู่กับ _COMM=sshd ด้วย และ OpenSSH บนเวอร์ชัน 24.04 จะบันทึกความล้มเหลวจากการทำงานของโพรเซสที่ชื่อ sshd ดังนั้นการจับคู่จึงทำงานได้ตามปกติ รายละเอียดนี้จะสำคัญก็ต่อเมื่อคุณใช้ OpenSSH เวอร์ชันใหม่กว่า (9.8 ขึ้นไป ซึ่งโพรเซสย่อยต่อการเชื่อมต่อคือ sshd-session) โดยรูปแบบความล้มเหลวจะครอบคลุมกรณีดังกล่าวไว้แล้ว

ขั้นตอนที่ 5: เฝ้าดูการแบนที่เกิดขึ้นจริง หรือทดสอบด้วยการบังคับแบน

การแบนจริงจะเกิดขึ้นเองภายในเวลาไม่กี่นาทีบน VPS ที่เปิดใช้งานสาธารณะ หากต้องการเฝ้าดูเหตุการณ์ดังกล่าว ให้ใช้คำสั่ง tail เพื่อดู log:

sudo tail -f /var/log/fail2ban.log

ลักษณะของการแบนจะเป็นดังนี้:

2026-07-15 10:31:40,502 fail2ban.filter  [812]: INFO    [sshd] Found 203.0.113.66 - 2026-07-15 10:31:40
2026-07-15 10:31:44,118 fail2ban.actions [812]: NOTICE  [sshd] Ban 203.0.113.66

หากต้องการพิสูจน์การทำงานของระบบตั้งแต่ต้นจนจบโดยไม่ต้องรอ ให้ทำการแบนที่อยู่ IP สำหรับเอกสารประกอบด้วยตนเอง (ห้ามแบน IP ของตนเองเด็ดขาด) 203.0.113.66 อยู่ในบล็อก TEST-NET-3 ซึ่งเป็นบล็อกที่สงวนไว้สำหรับเอกสารประกอบ ดังนั้นจึงไม่สามารถเป็นโฮสต์จริงหรือที่อยู่ส่วนตัวบนเครือข่ายของผู้ให้บริการของคุณได้:

sudo fail2ban-client set sshd banip 203.0.113.66

ระบบจะแสดงผล 1 และที่อยู่ดังกล่าวจะปรากฏภายใต้ Banned IP list ใน fail2ban-client status sshd จากนั้นให้ยืนยันว่ามีการบล็อกเกิดขึ้นจริงในไฟร์วอลล์ สำหรับ Ubuntu 24.04 จะใช้ nftables ไม่ใช่ iptables:

sudo nft list table inet f2b-table

คุณจะเห็นเซตที่ชื่อ addr-set-sshd ซึ่งบรรจุ 203.0.113.66 อยู่ และเห็น chain f2b-chain ที่ทำหน้าที่ปฏิเสธการเชื่อมต่อจากทุก source ที่อยู่ในเซตนั้น หาก fail2ban-client ระบุว่ามีการแบนที่อยู่ IP แล้ว แต่ไม่มีข้อมูลปรากฏใน nft list แสดงว่า action การแบนของคุณไม่สอดคล้องกับไฟร์วอลล์ที่ใช้งาน โปรดดูหมายเหตุเกี่ยวกับ nftables/iptables ในส่วนของรูปแบบความล้มเหลว

ขั้นตอนที่ 6: ยกเลิกการแบนตัวเอง และกู้คืนระบบหากถูกล็อกเอาต์

หากคุณแบนที่อยู่ IP ที่ไม่ควรแบน รวมถึงที่อยู่ของตัวคุณเอง ให้ลบออกด้วยคำสั่ง:

sudo fail2ban-client set sshd unbanip 203.0.113.66

คำสั่งจะส่งค่า 1 กลับมาเมื่อดำเนินการสำเร็จ หากต้องการล้างการแบนทั้งหมดในทุก jail ให้ใช้คำสั่ง:

sudo fail2ban-client unban --all

อย่าพึ่งพา SSH session ที่เปิดค้างไว้ว่าจะช่วยคุณได้ เพราะการแบนด้วย nftables จะปฏิเสธทุกแพ็กเก็ตจากที่อยู่ที่ถูกแบนไปยังพอร์ต 22 รวมถึงการเชื่อมต่อที่สร้างไว้แล้วด้วย ดังนั้น session ที่มีอยู่จะค้างทันทีที่การแบนมีผล หากคุณแบนตัวเองและไม่มีรายการ ignoreip คุณจะถูกล็อกเอาต์จนกว่าการแบนจะหมดอายุ ให้กู้คืนผ่านเว็บคอนโซลของผู้ให้บริการ (VNC หรือ serial) ซึ่งไม่ได้ผ่าน SSH จากนั้นให้รอจนครบเวลา bantime หรือรันคำสั่งยกเลิกการแบนจากที่นั่น

ขั้นตอนที่ 7: ทำให้การแบนคงอยู่ถาวรและเพิ่มระดับความรุนแรง

Fail2ban เก็บสถานะการแบนที่ใช้งานอยู่ไว้ในฐานข้อมูล SQLite ขนาดเล็กที่ /var/lib/fail2ban/fail2ban.sqlite3 เพื่อให้การแบนยังคงอยู่แม้จะมีการรีสตาร์ทเซอร์วิสหรือรีบูตเครื่อง คุณจึงไม่สูญเสียรายการที่แบนไป บรรทัด bantime.increment ที่คุณเพิ่มเข้าไปก่อนหน้านี้จะทำให้ผู้กระทำผิดซ้ำได้รับผลกระทบที่รุนแรงขึ้นเรื่อยๆ โดยระยะเวลาการแบนจะเพิ่มขึ้นเป็นสองเท่าจากหนึ่งชั่วโมงไปจนถึงหนึ่งสัปดาห์

สำหรับการกำหนดนโยบาย "สามครั้งออก" (three strikes) ทั่วทั้งระบบเพิ่มเติมจากเดิม Fail2ban มี jail ชื่อ recidive ที่คอยเฝ้าดู /var/log/fail2ban.log ของตัวมันเอง และจะทำการแบนระยะยาวกับที่อยู่ IP ใดก็ตามที่ถูกแบนซ้ำๆ ในทุก jail เนื่องจากตอนนี้ [DEFAULT] ของคุณใช้ backend แบบ systemd คุณจึงต้องกำหนด jail นี้ให้กลับไปอ่านไฟล์ log ที่ออกแบบมาให้มันอ่าน:

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

การใช้ backend = auto ร่วมกับ logpath ที่ระบุไว้อย่างชัดเจน จะช่วยให้ recidive อ่านค่าจาก fail2ban.log โดยตรง ซึ่งเป็นตำแหน่งที่บรรทัด Ban ที่ระบบใช้ในการนับจำนวนปรากฏอยู่ หากใช้ค่าเริ่มต้นของ systemd ที่คุณตั้งไว้ในระดับ global ระบบจะชี้ไปที่ journal ซึ่งไม่มีข้อมูลดังกล่าวอยู่

ขั้นตอนที่ 8: จับคู่กับการใช้ SSH แบบคีย์เท่านั้น และจะดียิ่งขึ้นหากใช้ VPN

Fail2ban จะทำงานได้เต็มประสิทธิภาพก็ต่อเมื่อใช้งานร่วมกับการยืนยันตัวตนด้วยคีย์เท่านั้น ในไฟล์แบบ drop-in ภายใต้ /etc/ssh/sshd_config.d/ เช่น /etc/ssh/sshd_config.d/00-hardening.conf ให้ตั้งค่าดังนี้:

PasswordAuthentication no
KbdInteractiveAuthentication no

จากนั้นให้ sudo systemctl restart ssh เมื่อปิดการใช้งานรหัสผ่าน การโจมตีแบบ brute force จะไม่สามารถทำได้เลย Fail2ban จึงทำหน้าที่ลดปริมาณ log ที่ไม่จำเป็นและคัดกรองผู้สแกนออกไปตั้งแต่เนิ่นๆ วิธีที่แข็งแกร่งยิ่งกว่าคือการปิด SSH จากอินเทอร์เน็ตสาธารณะโดยสิ้นเชิง: นำ SSH ไปไว้หลัง WireGuard VPN ที่คุณโฮสต์เอง และตั้งค่า firewall ที่พอร์ต 22 ให้ตอบสนองเฉพาะการเชื่อมต่อผ่าน tunnel เท่านั้น ไม่มีใครสามารถ brute-force พอร์ตที่พวกเขาเข้าถึงไม่ได้ และ Fail2ban จะกลายเป็นปราการด่านสุดท้ายแทนที่จะเป็นด่านหน้า

Fail2ban ไม่ได้มีไว้สำหรับ SSH เท่านั้น บริการใดก็ตามที่มีการบันทึก log การเข้าสู่ระบบที่ล้มเหลวสามารถสร้าง jail ขึ้นมาจัดการได้ ไม่ว่าจะเป็น mail server, เว็บไซต์บน Nginx หรือ ตัวจัดการรหัสผ่าน Vaultwarden ที่คุณโฮสต์เอง ซึ่งคุณอาจไม่ต้องการเปิดหน้าเว็บสำหรับล็อกอินทิ้งไว้ให้เสี่ยงต่อการถูกสุ่มรหัสผ่าน เมื่อเว็บแอปพลิเคชันอยู่หลัง เว็บไซต์ Nginx ที่มีใบรับรอง Let's Encrypt คุณสามารถกำหนดให้ Fail2ban filter ตรวจสอบ access log ของแอปนั้นได้ในลักษณะเดียวกับที่ SSH jail ตรวจสอบ journal

รูปแบบความล้มเหลวและข้อความแจ้งเตือนที่พบได้จริง

"Have not found any log file for sshd jail" และ Fail2ban ไม่ยอมเริ่มทำงาน นี่คือปัญหาเก่าของ auth.log ซึ่งบน Ubuntu 24.04 จะพบได้เฉพาะในกรณีที่ /var/log/auth.log ไม่มีอยู่จริง (เช่น อิมเมจที่ไม่มี rsyslog อย่างอิมเมจแบบ minimal หรือ container) และไม่มีการอ่านข้อมูลจาก journal: เช่น การติดตั้ง pip ที่ไม่มี defaults-debian.conf, container ที่ไม่มี journal หรือการคัดลอก backend = auto มาวางใน jail.local ผิดที่ ในกรณีที่ใช้ backend แบบไฟล์แต่ไม่มี /var/log/auth.log ตัว jail ของ sshd จะหาไฟล์ log ไม่พบและทำให้ daemon ทั้งหมดหยุดทำงาน fail2ban.log จะแสดงผลดังนี้:

ERROR   Failed during configuration: Have not found any log file for sshd jail

เนื่องจากข้อผิดพลาดนี้เป็นระดับวิกฤต (fatal) บริการจึงไม่สามารถเริ่มทำงานได้ และ fail2ban-client status จะรายงานอาการที่เกิดขึ้นตามมา:

ERROR  Failed to access socket path: /var/run/fail2ban/fail2ban.sock. Is fail2ban running?

บรรทัดที่ระบุว่า "socket path" ไม่ได้หมายความว่า Fail2ban เสียหาย แต่หมายความว่ามันไม่เคยเริ่มทำงานเพราะ jail ตัวหนึ่งหาไฟล์ log ไม่พบ การตั้งค่า backend = systemd ใน [DEFAULT] ซึ่งแพ็กเกจบน Ubuntu ตั้งค่าไว้ให้คุณอยู่แล้ว จะช่วยแก้ไขข้อความทั้งสองนี้ได้ในคราวเดียว

Jail ทำงานอยู่แต่ Total failed ไม่เพิ่มขึ้นเลย ตัว daemon ทำงานอยู่และมีการอ่าน journal ตามปกติ แต่ความล้มเหลวในการล็อกอินจริงกลับสะสมอยู่ใน journalctl -u ssh ในขณะที่ตัวนับยังคงอยู่ที่ 0 กฎข้อแรกคือให้ตัดสาเหตุที่ชัดเจนออกก่อน: คุณกำลังทดสอบจาก IP ที่อยู่ใน ignoreip หรือไม่ เพราะความล้มเหลวของคุณจะถูกยกเว้นโดยการออกแบบ หากไม่ใช่สาเหตุนั้น แสดงว่าคุณกำลังใช้ OpenSSH เวอร์ชันที่ worker ต่อการเชื่อมต่อเป็นแบบ sshd-session (เวอร์ชัน 9.8 ขึ้นไป) ซึ่งมี journal _COMM เป็น sshd-session ไม่ใช่ sshd ทำให้การจับคู่ (match) ที่มากับโปรแกรมทำงานไม่ได้ ให้ขยายการจับคู่ในบล็อก [sshd] ดังนี้:

[sshd]
enabled      = true
backend      = systemd
journalmatch = _SYSTEMD_UNIT=ssh.service + _COMM=sshd + _COMM=sshd-session

จากนั้นให้ restart แล้วลองล็อกอินให้ล้มเหลวโดยใช้ IP ที่ไม่อยู่ใน ignoreip เพื่อยืนยันว่า Total failed เพิ่มขึ้นแล้ว

คุณแบนตัวเอง: Connection refused คุณลืมใส่ IP ของตัวเองลงใน ignoreip แล้วทดสอบล็อกอินผิดพลาดหลายครั้ง จนตอนนี้เกิดเหตุการณ์:

ssh: connect to host 10.0.0.10 port 22: Connection refused

การที่ระบบปฏิเสธการเชื่อมต่อแทนที่จะปล่อยให้ timeout เป็นผลมาจากการที่ reject ของ action ใน nftables ทำงานตามหน้าที่ของมัน ให้แก้ไขตามขั้นตอนที่ 6: ยกเลิกการแบนจาก session อื่นที่ไม่ได้ถูกแบน หรือจาก console ของผู้ให้บริการ (เพราะ session ที่เปิดค้างไว้จาก IP ที่ถูกแบนจะค้างทันที) จากนั้นเพิ่ม IP ของคุณลงใน ignoreip เพื่อป้องกันไม่ให้เกิดเหตุการณ์นี้ซ้ำ

Fail2ban แจ้งว่าแบน IP แล้ว แต่ยังเชื่อมต่อได้ ตัวนับใน status sshd เพิ่มขึ้น แต่ IP นั้นยังคงเข้าถึงพอร์ต 22 ได้ ปัญหานี้เกิดจากการไม่สอดคล้องกันระหว่าง ban-action กับ firewall ซึ่งบน Ubuntu 24.04 มักเกิดจากการที่คุณไป override banaction = nftables ที่ทำงานได้ดีอยู่แล้วด้วย banaction = iptables-multiport ที่คัดลอกมาจากคู่มือเก่า ในเครื่องที่ไม่มีเลเยอร์ iptables อยู่ fail2ban.log จะแสดงผลดังนี้:

fail2ban.actions [812]: ERROR  Failed to execute ban jail 'sshd' action 'iptables-multiport'

ให้ลบการตั้งค่า override นั้นออกแล้วปล่อยให้ action nftables ที่มากับแพ็กเกจทำงานตามปกติ หรือหากคุณจัดการ firewall ผ่าน ufw ทั้งหมดและต้องการให้การแบนแสดงผลในนั้น ให้ตั้งค่า banaction = ufw ใน [DEFAULT] จากนั้น restart และตรวจสอบว่ากฎปรากฏขึ้นจริงด้วย sudo nft list ruleset | grep f2b

Fail2ban ไม่ยอมเริ่มทำงานหลังจากแก้ไข jail.local การพิมพ์ผิด, การมีหัวข้อเกินมา หรือการตั้งค่าเวลาที่ไม่ถูกต้อง ทำให้บริการปฏิเสธที่จะเริ่มทำงาน ให้สั่ง Fail2ban ตรวจสอบการตั้งค่าก่อนเริ่มทำงานจริง:

sudo fail2ban-client -t

มันจะระบุชื่อไฟล์และ jail ที่มีปัญหา เช่น Errors in jail 'sshd'. Skipping... เพื่อให้คุณแก้ไขที่ต้นเหตุแทนการเดาสุ่ม

FAQ

Fail2ban ที่ติดตั้งมาพร้อมกับ Ubuntu 24.04 สามารถบล็อกการโจมตี SSH ได้จริงหรือไม่?

ได้ แพ็กเกจนี้มาพร้อมกับ /etc/fail2ban/jail.d/defaults-debian.conf ซึ่งเปิดใช้งาน jail sshd โดยตั้งค่า backend = systemd ให้ระบบอ่านจาก systemd journal ไม่ว่าอิมเมจของคุณจะเขียนไฟล์ /var/log/auth.log หรือไม่ก็ตาม และตั้งค่า banaction = nftables เพื่อให้การบล็อกมีผลผ่าน firewall หลักของ Ubuntu การติดตั้ง apt install fail2ban แบบปกติจะช่วยปกป้อง SSH ตั้งแต่การบูตครั้งแรก คุณสามารถตรวจสอบได้ด้วยคำสั่ง sudo fail2ban-client status sshd และดูว่าค่า Total failed ไม่เป็นศูนย์

ทำไม Fail2ban ถึงไม่บล็อกอะไรเลยบนเซิร์ฟเวอร์ของฉัน?

ให้ตรวจสอบสาเหตุที่พบบ่อย 3 ประการตามลำดับ คุณอาจกำลังทดสอบจาก IP address ที่อยู่ใน ignoreip ซึ่งถูกยกเว้นไว้โดยการออกแบบ หรือคุณอาจไปเขียนทับค่าเริ่มต้นที่ทำงานได้ดีด้วยการคัดลอก backend = auto ไปวางใน jail.local จากคู่มือเก่า ซึ่งจะทำให้การบล็อก SSH บนอิมเมจที่ไม่มี rsyslog และไม่มี auth.log ใช้งานไม่ได้ หรือคุณอาจกำลังใช้งานอยู่ภายใน container ที่ไม่มี systemd journal ให้ระบบอ่าน ตรวจสอบค่า Total failed ใน fail2ban-client status sshd หากค่านี้ไม่เพิ่มขึ้นเลยในขณะที่ journalctl -u ssh แสดงให้เห็นว่ามีการล็อกอินล้มเหลวจริง แสดงว่า jail กำลังอ่านข้อมูลจากตำแหน่งที่ไม่ถูกต้อง

ฉันจะปลดบล็อก IP address ของตัวเองได้อย่างไร?

ให้รันคำสั่ง sudo fail2ban-client set sshd unbanip YOUR.IP.HERE ซึ่งจะส่งค่า 1 กลับมาหากสำเร็จ หรือใช้ sudo fail2ban-client unban --all เพื่อล้างการบล็อกทั้งหมด หากคุณถูกล็อกออกจาก SSH ให้ใช้ web console หรือ VNC console ของผู้ให้บริการเพื่อรันคำสั่งเดียวกัน เนื่องจากการบล็อกจะปฏิเสธทุกแพ็กเก็ตจาก address ของคุณที่ส่งไปยังพอร์ต 22 ทำให้แม้แต่เซสชันที่เปิดค้างไว้ก็จะหยุดทำงาน จากนั้นให้เพิ่ม address ของคุณลงใน ignoreip เพื่อป้องกันไม่ให้เกิดเหตุการณ์นี้ซ้ำ

jail.conf และ jail.local แตกต่างกันอย่างไร?

jail.conf เก็บค่าเริ่มต้นจากผู้พัฒนา Fail2ban และอาจถูกแทนที่เมื่อมีการอัปเกรดแพ็กเกจ ดังนั้นการแก้ไขไฟล์นี้จึงมีความเสี่ยง แพ็กเกจบน Debian/Ubuntu จะซ้อนทับการตั้งค่าของตนเองผ่าน jail.d/defaults-debian.conf การแก้ไขของคุณควรทำใน jail.local ซึ่งระบบจะอ่านหลังจากไฟล์ทั้งสองข้างต้นและมีลำดับความสำคัญสูงสุด อีกทั้งการอัปเกรดจะไม่แตะต้องไฟล์นี้ ไฟล์ *.local ที่อยู่ใน jail.d/ จะถูกอ่านในลำดับสุดท้าย ดังนั้นอย่าทิ้งไฟล์ที่ไม่จำเป็นไว้ในนั้น ให้เก็บ jail.conf ไว้เป็นไฟล์อ้างอิงแบบอ่านอย่างเดียวเท่านั้น

Fail2ban สามารถใช้แทนการยืนยันตัวตน SSH ด้วย key ได้หรือไม่?

ไม่ได้ Fail2ban ทำหน้าที่จำกัดอัตราความพยายามที่ล้มเหลวซ้ำๆ จาก address เดียวเท่านั้น แต่ไม่มีผลต่อการสุ่มเดาแบบช้าๆ และกระจายตัวที่แต่ละ address ยังคงอยู่ต่ำกว่าเกณฑ์ที่กำหนด การยืนยันตัวตนด้วย key เท่านั้น (PasswordAuthentication no) จะทำให้การสุ่มเดารหัสผ่านเป็นไปไม่ได้โดยสิ้นเชิง และ Fail2ban จะช่วยลดสัญญาณรบกวนใน log และคัดกรองตัวสแกนออกไปตั้งแต่เนิ่นๆ คุณควรใช้งานทั้งสองอย่างควบคู่กัน และหากเป็นไปได้ควรจำกัดไม่ให้ SSH เข้าถึงได้จากอินเทอร์เน็ตสาธารณะโดยตรง