Tarkibga o'tish

fail2ban

SSH hardening maqolasida fail2ban kengroq SSH checklist’ining bir qismi sifatida qisqacha tilga olingan edi: u log'larni kuzatadi va vaqt oralig'i ichida juda ko'p muvaffaqiyatsiz urinish qilgan IP manzilni ban qiladi. Bu maqolada u to'liq ko'rib chiqiladi. fail2ban umuman faqat SSH’ga xos emas. U log fayli va tanib olinadigan muvaffaqiyatsizlik shabloni bor har qanday servisni — pochta serveridan tortib web ilovaning login formasigacha — himoya qila oladigan umumiy log kuzatish framework’i.

Nimalarni o'rganasiz

Bu maqola oxirida siz quyidagilarni qila olasiz:

  • fail2ban log shablonini firewall ban’iga qanday aylantirishini tushuntirish;
  • tayyor standart sozlamalarni bevosita tahrirlamasdan jail.local da jail sozlash;
  • filtrning regex’ini production’da unga ishonishdan oldin haqiqiy log qatorlariga qarshi sinab ko'rish;
  • manzillarni qo'lda tekshirish, ban’dan chiqarish va oq ro'yxatga (whitelist) kiritish;
  • SSH’dan tashqari ikkinchi servisni o'z jail’i bilan himoya qilish.

fail2ban aslida qanday ishlaydi

fail2ban’da birgalikda bitta jail ni tashkil qiladigan uchta harakatlanuvchi qism bor:

  • kuzatiladigan log fayl (/var/log/auth.log, ilovaning o'z log'i va hokazo);
  • filter — o'sha log'dagi muvaffaqiyatsiz urinish qatorini tanib oladigan regular expression’lar to'plami;
  • action — filter vaqt oralig'i ichida bitta manzildan juda ko'p marta mos kelgandan keyin nima qilish kerakligi. Bu deyarli har doim uni bloklash uchun firewall qoidasini qo'shish.
sudo systemctl status fail2ban
● fail2ban.service - Fail2Ban Service
     Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled)
     Active: active (running)

fail2ban’ning o'zi firewall o'rnini bosmaydi — u firewall’ni boshqaradi. U ban qoidalarini nftables/iptables to'plami (set) sifatida dinamik qo'shadi va olib tashlaydi (qarang: iptables va nftables), ularni esa ostida baribir UFW yoki xom nftables ruleset’i majburlaydi.

Tayyor standart sozlamalarni hech qachon bevosita tahrirlamang

fail2ban /etc/fail2ban/jail.conf dagi standart konfiguratsiya bilan keladi. Lekin bu fayl keyingi paket yangilanishida qayta yozilishi kutiladi. Har qanday mahalliy sozlash /etc/fail2ban/jail.local ga yozilishi kerak. fail2ban uni jail.conf dan keyin o'qiydi va undagi har qanday sozlama ustun keladi:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Boshlang'ich nuqta sifatida butun faylni nusxalash an’anaviy yondashuv. Lekin faqat haqiqatan sozlanayotgan bo'limlarni qoldirish kifoya — o'rnatilmagan har qanday narsa avtomatik ravishda jail.conf ning standart qiymatiga qaytadi.

Jail sozlash

sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 203.0.113.5

[sshd]
enabled  = true
port     = 22
logpath  = %(sshd_log)s
maxretry = 3
  • bantime — ishga tushgan ban qancha davom etishi (1h yoki doimiy uchun -1);
  • findtime — ban’ni ishga tushirish uchun maxretry ta muvaffaqiyatsizlik sodir bo'lishi kerak bo'lgan siljuvchi vaqt oynasi;
  • maxretry — findtime ichida nechta mos keluvchi muvaffaqiyatsizlik ban’ni ishga tushirishi;
  • ignoreip — qanday mos kelishidan qat’i nazar hech qachon ban qilinmaydigan manzillar (va CIDR oraliqlari). Bu yerga har doim boshqaruv ish stansiyasining o'z manzilini qo'shing, chunki o'z IP’ingizga qo'yilgan ban hujumchinikiga qo'yilgani kabi sizni qulflab qo'yishda xuddi shunday samarali;
  • [sshd] aynan shu jail uchun maxretry ni qayta belgilaydi va aniq qayta yozilmagan hamma narsa uchun [DEFAULT] bo'limidagi qiymatlar ustiga qo'shiladi.
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 2
|  |- Total failed:     14
|  `- Journal matches:  _SYSTEMD_UNIT=ssh.service + _COMM=sshd
`- Actions
   |- Currently banned: 1
   |- Total banned:     3
   `- Banned IP list:   198.51.100.7

Filtrga ishonishdan oldin uni sinab ko'rish

Haqiqiy log qatorlariga mos kelmaydigan filter muammoni bildiradigan hech qanday xatosiz, jimgina hech narsani himoya qilmaydi. Shuning uchun filtrga tayanishdan oldin uning regex’i haqiqatan mos kelishini tekshirishga arziydi:

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

Success, the total number of match is 14

Overall
=======
Lines: 20348 lines, 0 ignored, 14 matched, 20334 missed

fail2ban-regex filtrni hech kimni ban qilmasdan haqiqiy log fayliga qarshi ishga tushiradi. Bu maxsus filtr (yoki distributiv log formatini o'zgartirgandan keyin o'zgartirilgan filtr) production’da unga tayanishdan oldin hali ham mos kelishini tasdiqlashning xavfsiz usuli.

Tekshirish, ban’dan chiqarish va oq ro'yxatga kiritish

sudo fail2ban-client status
Status
|- Number of jail:      2
`- Jail list:   sshd, nginx-http-auth
sudo fail2ban-client set sshd unbanip 198.51.100.7
198.51.100.7

Noto'g'ri ishlash (false positive) holatida — masalan, parolini juda ko'p marta noto'g'ri kiritgan qonuniy foydalanuvchi uchun — to'g'ri javob ban’dan chiqarish. Butun fail2ban servisini qayta ishga tushirish esa xatoga aloqasi bo'lmagan boshqa barcha faol ban’larni ham tozalab yuboradi.

sudo fail2ban-client get sshd bantime

Hech qachon ban’ni ishga tushirmasligi kerak bo'lgan manzillarni doimiy oq ro'yxatga kiritish qayta-qayta qo'lda ban’dan chiqarish bilan emas, ignoreip da qilinadi:

ignoreip = 127.0.0.1/8 ::1 203.0.113.5 198.51.100.0/28

Ikkinchi servisni himoya qilish

fail2ban’ning tuzilishi SSH’dan tashqariga ham umumlashadi — log fayli va tanib olinadigan muvaffaqiyatsizlik qatori bor har qanday servis o'z jail’iga ega bo'lishi mumkin. Keng tarqalgan misol: nginx saytiga qarshi takroriy muvaffaqiyatsiz HTTP basic-auth urinishlarini ban qilish.

sudo nano /etc/fail2ban/jail.local
[nginx-http-auth]
enabled  = true
port     = http,https
logpath  = /var/log/nginx/error.log

fail2ban aynan shu log shabloni uchun mos filtr bilan allaqachon keladi (/etc/fail2ban/filter.d/nginx-http-auth.conf). Filtrning o'zi standart distributivning bir qismi bo'lgani uchun jail ta’rifi faqat uni yoqishi va to'g'ri log yo'liga ishora qilishi kerak.

sudo fail2ban-client status nginx-http-auth
Status for the jail: nginx-http-auth
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     6
|  `- File list:        /var/log/nginx/error.log
`- Actions
   |- Currently banned: 0
   |- Total banned:     1
   `- Banned IP list:

Bu pam_faillock va UFW’ning limit i bilan qanday bog'liq

Bu kursdagi uchta mexanizm bir-biriga o'xshash eshitiladigan muammoni hal qiladi va ularni aniq farqlay olish uchun bevosita tayyorlanishga arziydi:

Mexanizm Nimaga javob beradi Bloklash doirasi
ufw limit (qarang: Firewall va UFW) Muvaffaqiyat/muvaffaqiyatsizlikni bilmagan holda xom ulanish tezligiga Har bir manba IP bo'yicha, firewall’da, autentifikatsiyaga urinishdan oldin
pam_faillock (qarang: Root va sudo) Bitta akkaunt uchun ketma-ket autentifikatsiya muvaffaqiyatsizliklariga Manba IP’dan qat’i nazar, har bir akkaunt bo'yicha
fail2ban Servisdan qat’i nazar, log fayldagi muvaffaqiyatsizlik shablonlariga Haqiqatan muvaffaqiyatsiz bo'lgan urinishlar asosida, har bir manba IP bo'yicha, firewall’da

Intervyuda: nega bittasini emas, uchalasini joriy qilish kerak

Har bir akkaunt uchun bir nechta urinishni minglab manba IP’lar bo'ylab tarqatadigan taqsimlangan brute-force hujum fail2ban’ning har bir IP bo'yicha ban qilishini yengadi (birorta ham IP chegaradan o'tmaydi), lekin pam_faillock ning har bir akkaunt bo'yicha bloklashini yengmaydi. Bitta IP’dan ko'plab foydalanuvchi nomlarini navbatma-navbat sinab ko'radigan sekin, sabrli hujumchi pam_faillock ning har bir akkaunt bo'yicha sanashini yengadi, lekin fail2ban’ning har bir IP bo'yicha ban qilishini yengmaydi. ufw limit ikkala shablonni ham aniq ushlamaydi, lekin aniq ko'rinib turgan yuqori tezlikdagi skanerlashni autentifikatsiya qatlamiga yetib bormasdan bloklaydigan qo'pol, arzon birinchi himoya chizig'ini qo'shadi. Uchalasidan hech biri yolg'iz o'zi har bir hujum shaklini qamrab olmaydi — bu qisqartirilishi kerak bo'lgan ortiqchalik emas, uchalasini birga joriy qilishning amaliy dalili.

Amaliy vaziyat: hech kimni ban qilmayotgan jail’ni diagnostika qilish

Muammo. SSH aniq faol hujum ostida (auth.log da o'nlab muvaffaqiyatsiz loginlar ko'rinadi), lekin fail2ban-client status sshd nol ban ko'rsatadi.

1-qadam — jail umuman yoqilgani va to'g'ri log'ni kuzatayotganini tasdiqlash:

sudo fail2ban-client status sshd
ERROR   NOK: ('sshd',)

Jail umuman mavjud emas — jail.local da [sshd] hech qachon enabled = true ga o'rnatilmagan. Shuning uchun amalda jail.conf ning o'z standart qiymati (bu distributivda o'chiq) ishlayapti.

2-qadam — uni yoqish va log yo'li haqiqatga mos kelishini tasdiqlash:

sudo nano /etc/fail2ban/jail.local
[sshd]
enabled = true
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0

3-qadam — filtr ishlatilayotgan log formatiga haqiqatan mos kelayotganini tekshirish:

sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
Lines: 20348 lines, 0 ignored, 14 matched, 20334 missed

Xulosa. Jail shunchaki hech qachon yoqilmagan edi — bu filtr yoki firewall muammosi emas, konfiguratsiyadagi bo'shliq. U yoqilib, haqiqiy log qatorlariga mos kelishi tasdiqlangach, keyingi muvaffaqiyatsiz urinishlar maxretry tomon to'g'ri to'plana boshlaydi.

Keng tarqalgan xatolar

  • jail.conf ni bevosita tahrirlash. Keyingi paket yangilanishi uni qayta yozadi va sozlashni jimgina yo'q qiladi. Barcha mahalliy o'zgarishlar jail.local ga tegishli.
  • Boshqaruv ish stansiyasining o'z IP’sini ignoreip ga qo'shishni unutish. Umumiy ofis IP’sidan bitta noto'g'ri kiritilgan parol faqat xato qilgan kishini emas, butun jamoani qulflab qo'yishi mumkin.
  • Konfiguratsiya faylida ko'rsatilgani uchungina jail yoqilgan deb o'ylash. Yuqoridagi vaziyatda ko'rsatilganidek, jail bo'limi enabled = true siz ham mavjud bo'lishi mumkin va bu holda u hech narsa qilmaydi.
  • Filtrni haqiqiy log qatorlariga qarshi sinamasdan unga ishonish. Distributiv yangilangandan keyingi log formati o'zgarishi oldin ishlagan filtrni jimgina buzishi mumkin. fail2ban-regex unga tayanishdan oldin u hali ham mos kelishini tasdiqlash usuli.
  • fail2ban’ni brute-force login urinishlariga qarshi yagona himoya sifatida ishlatish. Yuqorida ko'rib chiqilganidek, u pam_faillock va ufw limit dan boshqa hujum shaklini qamrab oladi. Faqat unga tayanish ma’lum hujum shablonlarini himoyasiz qoldiradi.

Mashqlar

  1. Lab VM’da sshd jail’ini past maxretry (2) va qisqa bantime (60) bilan yoqing, keyin ban ishga tushishi uchun boshqa mashina yoki terminaldan ataylab yetarli marta SSH login’da muvaffaqiyatsizlikka uchrang. fail2ban-client status sshd bilan tasdiqlang va keyin o'zingizni ban’dan chiqaring.
  2. O'z boshqaruv IP’ingizni ignoreip ga qo'shing va bu qator jail’ning o'zi xavfsizlik uchun qanchalik muhim bo'lsa, mavjudlik (availability) uchun ham shunchalik muhimligini bir jumlada tushuntiring.
  3. Servisning log fayli va unga mos filtrga qarshi fail2ban-regex ni ishga tushiring va chiqishdagi "matched" va "missed" sonlarini talqin qiling.
  4. Password-spraying hujumi ostidagi faraziy pochta serveri uchun (ko'plab akkauntlar, har biriga kam urinish, bitta IP’dan) fail2ban, pam_faillock va ufw limit dan qaysi biri uni birinchi bo'lib ushlashini va nega ekanini tushuntiring.

Xulosa

fail2ban log faylni tanib olinadigan muvaffaqiyatsizlik shabloni bo'yicha kuzatadi va vaqt oynasi ichida chegaradan o'tilgach, aybdor manzilni firewall’da ban qiladi. Bu SSH’ga xos emas, umumiy mexanizm bo'lib, qayta yozilishi mumkin bo'lgan jail.conf orqali emas, jail.local orqali sozlanadi. U pam_faillock ning har bir akkaunt bo'yicha bloklashini va UFW’ning xom rate limiting'ini almashtirmaydi, balki to'ldiradi, chunki uchalasining har biri boshqa hujum shaklini ushlaydi. Keyingi maqola, auditd, xavfsizlikka oid kernel hodisalarini bevosita yozib borishni ko'rib chiqadi. Bu xuddi shu "kuzat, keyin harakat qil" g'oyasining nozikroq, umumiyroq shakli.

Manbalar