ทำไม Fail2ban ถึงเป็นสิ่งจำเป็นสำหรับทุก Server
ผมดูแล server มามากกว่า 28 ปีและสิ่งแรกที่ผมติดตั้งทุกครั้งหลังจาก setup server ใหม่คือ Fail2ban เสมอเหตุผลง่ายๆคือทุก server ที่มี public IP จะถูกโจมตีตลอดเวลาไม่ว่าจะเป็น server ของบริษัทใหญ่หรือ VPS ตัวเล็กๆที่เพิ่งซื้อมาผมเคยตั้ง server ใหม่เปล่าๆไม่มีอะไรเลยภายใน 5 นาทีก็เริ่มเห็น brute force attempts ใน auth.log แล้ว
ตัวเลขจริงที่ผมเจอบน server ที่ดูแลอยู่: ภายใน 24 ชั่วโมงมี failed SSH login attempts เฉลี่ย 5,000-15,000 ครั้งจาก IP ทั่วโลกส่วนใหญ่มาจาก botnet ที่สแกน IP range แล้วลอง username/password ทั่วไปเช่น root/123456, admin/admin, ubuntu/password ถ้าไม่มี Fail2ban ป้องกันแม้จะใช้ password ที่แข็งแรงแต่ server ก็จะเสีย resource ไปกับการรับ connection requests เหล่านี้โดยเปล่าประโยชน์
Fail2ban ทำงานอย่างไร
หลักการทำงานของ Fail2ban เข้าใจง่ายมากมัน monitor log files (เช่น /var/log/auth.log) เมื่อเจอ pattern ที่ตรงกับ filter ที่ตั้งไว้ (เช่น "Failed password") จำนวนครั้งที่เกิน threshold ภายในเวลาที่กำหนดมันจะ execute action ที่ตั้งไว้ซึ่งปกติคือเพิ่ม rule ใน iptables/nftables เพื่อ block IP นั้นครบ ban time ก็ปลด block ให้อัตโนมัติ
ติดตั้งบน Ubuntu/Debian
# อัพเดท repository
apt update
# ติดตั้ง Fail2ban
apt install fail2ban -y
# ตรวจสอบ version
fail2ban-client version
# Fail2ban v1.0.2
# เปิดใช้งาน
systemctl enable --now fail2ban
# ตรวจสอบ status
systemctl status fail2ban
fail2ban-client status
ติดตั้งบน CentOS/Rocky Linux
# ต้องเปิด EPEL repository ก่อน
dnf install epel-release -y
dnf install fail2ban fail2ban-firewalld -y
# เปิดใช้งาน
systemctl enable --now fail2ban
# ตรวจสอบ
fail2ban-client status
โครงสร้างไฟล์ Configuration
# โครงสร้างไฟล์ที่ต้องรู้
/etc/fail2ban/
├── fail2ban.conf # Config หลัก (อย่าแก้ไฟล์นี้!)
├── fail2ban.local # Override config หลัก (สร้างเอง)
├── jail.conf # Jail definitions (อย่าแก้!)
├── jail.local # Override jail config (สร้างเอง)
├── jail.d/ # Directory สำหรับ jail configs เพิ่มเติม
│ └── defaults-debian.conf
├── filter.d/ # Filter definitions (regex patterns)
│ ├── sshd.conf
│ ├── nginx-http-auth.conf
│ └── ...
└── action.d/ # Action definitions
├── iptables-multiport.conf
├── nftables-multiport.conf
├── sendmail.conf
└── ...
# กฎสำคัญ: อย่าแก้ .conf files โดยตรง!
# สร้าง .local files แทน เพราะ .conf จะถูก overwrite ตอน update
ทำความเข้าใจ Jails, Filters และ Actions
Fail2ban มี 3 องค์ประกอบหลักที่ต้องเข้าใจ
Jail — กรงขัง
Jail คือ unit การทำงานของ Fail2ban แต่ละ jail กำหนดว่าจะ monitor log file ไหนใช้ filter อะไรถ้าตรง pattern กี่ครั้งภายในเวลาเท่าไรให้ทำ action อะไรและ ban นานแค่ไหนตัวอย่างเช่น sshd jail จะ monitor /var/log/auth.log ถ้า failed login 5 ครั้งใน 10 นาทีให้ ban IP นั้น 1 ชั่วโมง
Filter — ตัวกรอง
Filter คือ regex pattern ที่ใช้จับ log entries ที่เป็น failure Fail2ban มี built-in filters มากมายเช่น sshd filter จะจับ "Failed password for" และ "Connection closed by authenticating user" ใน auth.log คุณสามารถสร้าง custom filter เองได้
Action — การกระทำ
Action คือสิ่งที่ Fail2ban ทำเมื่อ IP ถูก ban เช่นเพิ่ม iptables rule ส่ง email notification หรือเรียก API ภายนอก Action ที่ใช้บ่อยคือ iptables-multiport สำหรับ Ubuntu หรือ firewallcmd-rich-rules สำหรับ CentOS ที่ใช้ firewalld
ตั้งค่า Jail สำหรับ SSH Protection
มาเริ่มกันที่ SSH ซึ่งเป็น service ที่ถูกโจมตีมากที่สุด
# สร้าง /etc/fail2ban/jail.local
cat > /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
# Ban IP เป็นเวลา 1 ชั่วโมง
bantime = 3600
# ช่วงเวลาที่นับ failures
findtime = 600
# จำนวน failures ก่อน ban
maxretry = 5
# Whitelist IPs (อย่าลืม whitelist IP ตัวเอง!)
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 192.168.0.0/16
# Action เริ่มต้น
banaction = iptables-multiport
banaction_allports = iptables-allports
# ส่ง email เมื่อ ban (optional)
# action = %(action_mwl)s
# destemail = admin@example.com
# sender = fail2ban@example.com
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 300
# ถ้าใช้ SSH port อื่น (เช่น 2222)
# port = 2222
[sshd-aggressive]
enabled = true
port = ssh
filter = sshd[mode=aggressive]
logpath = /var/log/auth.log
maxretry = 1
bantime = 86400
findtime = 3600
EOF
# Restart Fail2ban
systemctl restart fail2ban
# ตรวจสอบ jail status
fail2ban-client status sshd
Progressive Ban — เพิ่ม ban time สำหรับ repeat offenders
# /etc/fail2ban/jail.d/progressive.conf
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
filter = recidive
# ถ้า IP ถูก ban 5 ครั้งใน 24 ชั่วโมง → ban 1 สัปดาห์
banaction = iptables-allports
bantime = 604800
findtime = 86400
maxretry = 5
Nginx HTTP Authentication
# /etc/fail2ban/jail.d/nginx.conf
[nginx-http-auth]
enabled = true
port = http, https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
bantime = 3600
[nginx-botsearch]
enabled = true
port = http, https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 10
bantime = 86400
[nginx-limit-req]
enabled = true
port = http, https
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 10
bantime = 7200
ป้องกัน DDoS เบื้องต้นด้วย Nginx Rate Limit + Fail2ban
# Nginx config — เพิ่ม rate limiting
# /etc/nginx/conf.d/rate-limit.conf
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
server {
# Rate limit ทั่วไป
limit_req zone=general burst=20 nodelay;
# Rate limit สำหรับ login page
location /wp-login.php {
limit_req zone=login burst=3 nodelay;
# ... proxy settings
}
}
# เมื่อ rate limit ถูก exceed Nginx จะ log error
# Fail2ban จะจับ log นี้และ ban IP
Apache Protection
# /etc/fail2ban/jail.d/apache.conf
[apache-auth]
enabled = true
port = http, https
filter = apache-auth
logpath = /var/log/apache2/error.log
maxretry = 5
bantime = 3600
[apache-badbots]
enabled = true
port = http, https
filter = apache-badbots
logpath = /var/log/apache2/access.log
maxretry = 2
bantime = 172800
[apache-overflows]
enabled = true
port = http, https
filter = apache-overflows
logpath = /var/log/apache2/error.log
maxretry = 2
bantime = 3600
ป้องกัน WordPress Brute Force
WordPress เป็นเป้าหมายยอดนิยมของ attackers เพราะ wp-login.php และ xmlrpc.php เข้าถึงได้จากภายนอกผมเขียนเรื่อง WordPress Speed Optimization ไว้แล้วแต่เรื่อง security ก็สำคัญไม่แพ้กัน
สร้าง Custom Filter สำหรับ WordPress
# /etc/fail2ban/filter.d/wordpress-login.conf
[Definition]
failregex = ^ -.*"(GET|POST) /wp-login\.php.*" (200|401|403)
^ -.*"POST /xmlrpc\.php.*" (200|403)
ignoreregex =
# /etc/fail2ban/jail.d/wordpress.conf
[wordpress-login]
enabled = true
port = http, https
filter = wordpress-login
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 3600
findtime = 300
[wordpress-xmlrpc]
enabled = true
port = http, https
filter = wordpress-xmlrpc
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 86400
Filter สำหรับ WordPress xmlrpc.php
# /etc/fail2ban/filter.d/wordpress-xmlrpc.conf
[Definition]
failregex = ^ -.*"POST /xmlrpc\.php.*"
ignoreregex =
สร้าง Custom Filter สำหรับ Application ของคุณ
# ตัวอย่าง: ป้องกัน API brute force
# /etc/fail2ban/filter.d/myapi-auth.conf
[Definition]
failregex = ^.*\[error\].*authentication failed for user .* from
^ -.*"POST /api/auth/login.*" 401
ignoreregex =
# ทดสอบ filter ก่อนใช้จริง (สำคัญมาก!)
fail2ban-regex /var/log/myapp/error.log /etc/fail2ban/filter.d/myapi-auth.conf
# ผลลัพธ์จะบอกว่า regex จับ log entries ได้กี่บรรทัด
# ถ้า 0 แสดงว่า regex ไม่ตรง ต้องแก้
ใช้ nftables แทน iptables
# สำหรับ distro ที่ใช้ nftables เป็น default (Ubuntu 22.04+)
# แก้ใน jail.local
[DEFAULT]
banaction = nftables-multiport
banaction_allports = nftables-allports
ส่ง Notification ไปยัง Slack/Telegram
# /etc/fail2ban/action.d/slack-notify.conf
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = curl -s -o /dev/null -X POST \
-H 'Content-type: application/json' \
--data '{"text":"🚨 Fail2ban: Banned IP on jail (%(bantime)s seconds)"}' \
https://hooks.slack.com/services/YOUR/WEBHOOK/URL
actionunban = curl -s -o /dev/null -X POST \
-H 'Content-type: application/json' \
--data '{"text":"✅ Fail2ban: Unbanned IP from jail "}' \
https://hooks.slack.com/services/YOUR/WEBHOOK/URL
# ใช้ action นี้ใน jail
[sshd]
enabled = true
action = iptables-multiport[name=sshd, port="ssh", protocol=tcp]
slack-notify
Commands ที่ใช้บ่อย
# ดู status ทั้งหมด
fail2ban-client status
# ดู status ของ jail เฉพาะ
fail2ban-client status sshd
# ดู IP ที่ถูก ban
fail2ban-client get sshd banned
# Unban IP
fail2ban-client set sshd unbanip 203.150.x.x
# Ban IP ด้วยมือ
fail2ban-client set sshd banip 1.2.3.4
# Reload config (ไม่ต้อง restart)
fail2ban-client reload
# ดู log ของ Fail2ban
tail -f /var/log/fail2ban.log
# นับจำนวน banned IPs
fail2ban-client status sshd | grep "Currently banned"
# ดู iptables rules ที่ Fail2ban สร้าง
iptables -L f2b-sshd -n --line-numbers
ส่ง Ban Stats ไปยัง Monitoring
# Script สำหรับส่ง metrics ไปยัง Prometheus (via node_exporter textfile)
#!/bin/bash
# /usr/local/bin/fail2ban-metrics.sh
TEXTFILE_DIR="/var/lib/node_exporter/textfile_collector"
for jail in $(fail2ban-client status | grep "Jail list" | sed 's/.*://;s/,//g'); do
banned=$(fail2ban-client status $jail | grep "Currently banned" | awk '{print $NF}')
total=$(fail2ban-client status $jail | grep "Total banned" | awk '{print $NF}')
echo "fail2ban_banned_current{jail=\"$jail\"} $banned"
echo "fail2ban_banned_total{jail=\"$jail\"} $total"
done > "$TEXTFILE_DIR/fail2ban.prom.$$"
mv "$TEXTFILE_DIR/fail2ban.prom.$$" "$TEXTFILE_DIR/fail2ban.prom"
# เพิ่มใน crontab
# * * * * * /usr/local/bin/fail2ban-metrics.sh
สำหรับการ monitor แบบเจาะลึกผมแนะนำให้ส่ง Fail2ban logs ไปยัง ELK Stack เพื่อสร้าง dashboard แสดง attack patterns, top attacking countries และ ban statistics
Troubleshooting ที่พบบ่อย
# ปัญหา: Fail2ban ไม่ ban IP
# 1. ตรวจสอบว่า jail enabled จริง
fail2ban-client status
# 2. ตรวจสอบว่า filter จับ log ได้
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
# 3. ตรวจสอบว่า logpath ถูกต้อง
# ดูว่า Fail2ban อ่าน log file ได้หรือไม่
fail2ban-client get sshd logpath
# 4. ตรวจสอบ findtime และ maxretry
# บางทีตั้ง findtime สั้นเกินไป ทำให้ count reset ก่อนจะถึง maxretry
# ปัญหา: Ban ตัวเอง (lock out)
# ถ้า SSH ไม่ได้ ให้ login ผ่าน console (VPS provider panel)
# แล้วรัน:
fail2ban-client set sshd unbanip YOUR_IP
# หรือ
iptables -D f2b-sshd -s YOUR_IP -j REJECT
# ป้องกันไม่ให้ ban ตัวเอง: ใส่ IP ใน ignoreip เสมอ!
Fail2ban กิน resource เยอะไหม?
แทบไม่กินเลยครับ Fail2ban เขียนด้วย Python ใช้ RAM ประมาณ 30-50 MB CPU แทบไม่กระทบเพราะมันแค่ monitor log files ด้วย inotify ไม่ได้ poll ทุกวินาทีเทียบกับประโยชน์ที่ได้ถือว่าคุ้มค่ามากผมรัน Fail2ban บน VPS ที่มี RAM แค่ 512 MB ก็ยังทำงานได้ดี
ควรตั้ง bantime นานเท่าไร?
ขึ้นอยู่กับ service ครับสำหรับ SSH ผมตั้ง 1 ชั่วโมงสำหรับ first offense และใช้ recidive jail เพิ่ม ban time เป็น 1 สัปดาห์สำหรับ repeat offenders สำหรับ xmlrpc.php ของ WordPress ผมตั้ง 24 ชั่วโมงเลยเพราะไม่มีเหตุผลที่ user ปกติจะเข้าถึง xmlrpc.php บ่อยๆอย่าตั้ง permanent ban (bantime = -1) เว้นแต่คุณมี whitelist ที่ดีเพราะ IP อาจจะเปลี่ยนเจ้าของได้
Fail2ban กับ WireGuard VPN ใช้คู่กันได้ไหม?
ได้ครับผมแนะนำให้ whitelist WireGuard subnet (เช่น 10.10.0.0/24) ใน ignoreip ของ Fail2ban เพื่อไม่ให้ ban traffic จาก VPN นอกจากนี้ถ้าใช้ VPN เข้า server ควรปิด SSH จาก public IP เลยให้เข้าได้เฉพาะผ่าน VPN จะปลอดภัยกว่ามาก
Fail2ban รองรับ IPv6 ไหม?
รองรับครับตั้งแต่ version 0.10 ขึ้นไปแต่ต้องใช้ banaction ที่รองรับ IPv6 เช่น iptables-multiport จะเปลี่ยนเป็น ip6tables-multiport โดยอัตโนมัติหรือใช้ nftables-multiport ที่รองรับทั้ง IPv4 และ IPv6 ในตัว
สรุป
Fail2ban เป็นเครื่องมือที่ทุก Linux server ต้องมีมันง่ายในการติดตั้งใช้ resource น้อยแต่ให้ protection ที่มีประสิทธิภาพมากต่อ brute force attacks สิ่งสำคัญที่ต้องจำคืออย่าลืม whitelist IP ของตัวเองใช้ jail.local แทนการแก้ jail.conf ทดสอบ custom filters ด้วย fail2ban-regex เสมอและตั้ง recidive jail สำหรับ repeat offenders
Fail2ban เป็นแค่ชั้นหนึ่งของ defense-in-depth strategy ผมแนะนำให้ใช้ร่วมกับ SSH key authentication, firewall rules, Lynis Security Audit และ regular security updates เพื่อให้ server ของคุณปลอดภัยที่สุดครับ
อ่านเพิ่มเติม: สอนเทรด Forex | XM Signal | IT Hardware | อาชีพ IT