Asosiy kontentga o‘tish

Maqolalar 29 daqiqa 16 ko‘rish

ufw: serverdagi firewall nega kerak va uni qachon, qanday qo'yamiz

Internetga ochilgan server — eshigi ochiq uy: kim xohlasa kirib ko'radi. Firewall shu eshiklarni yopadi, faqat keraklisini ochiq qoldiradi. ufw'ni boshdan-oyoq: qachon kerak (va qachon yetarli emas), systemd bilan aloqasi, SSH'ni o'zimizdan yopib qo'ymaslik, bitta IP, interfeys va Docker bilan bog'liq tuzoqlar — real server sozlamalari bilan.

linux security devops

Mundarija

Yangi serverga ilova qo'yish oson: pip install, systemctl start — ishlayapti. Ko'pincha shu joyda to'xtaymiz. Lekin bir narsa e'tibordan chetda qoladi: serverdagi har bir tinglayotgan port butun internetga ochiq. Postgres 5432 da turibdi — demak, Xitoydan ham, Braziliyadan ham unga ulanib parol terib ko'rish mumkin. Redis 6379 da parolsiz turibdi — demak, u umuman sizniki emas. Bu mubolag'a emas: tarmoqni skanerlab yuradigan botlar yangi IP'ni bir necha soat ichida topadi.

Firewall shu masalani hal qiladi. Uning mantig'i sodda: hammasi yopiq, faqat men ongli ravishda ochganim ochiq. Ubuntu'da bu ish uchun ufw (Uncomplicated Firewall) bor — nomi ham "murakkab emas" degani. Bu maqolada uni boshdan-oyoq ko'ramiz: nazariyasi (u aslida nima, nimadan himoya qiladi, nimadan qilmaydi), keyin real server ssenariylari — SSH, bitta IP, alohida interfeys, Docker va boshqa tuzoqlar.

VPS'ni noldan sozlash maqolasida ufw'ni to'rt buyruq bilan yoqqan edik. Bu yerda o'sha to'rt buyruq ortida nima turganini va undan keyin nima qilinishini ko'ramiz.

Firewall aslida nima qiladi#

Har bir tarmoq paketi serverga kirganda Linux yadrosi (kernel) uni bir qator qoidalardan o'tkazadi: kimdan keldi, qaysi portga, qaysi protokol bilan. Qoidalar "o'tkaz", "tashla" yoki "rad et" deydi. Bu mexanizm yadroning ichida — netfilter — va u har doim ishlab turadi, siz uni sozlamagan bo'lsangiz ham (shunchaki qoidalari bo'sh, hammasi o'tadi).

Qoidalarni yadroga yetkazadigan vositalar bir nechta:

  • iptables — klassik, batafsil, lekin sintaksisi og'ir;
  • nftables — yangisi, iptables o'rnini bosmoqda;
  • ufw — shu ikkisining ustidagi qulay qatlam. Siz ufw allow 443 deysiz, u yadroga kerakli iptables/nftables qoidalarini yozadi.

Ya'ni ufw alohida "dastur" emas — u yadro firewall'ining boshqaruv puli. Shuning uchun ufw ishlamayotganda ham netfilter ishlayveradi; ufw uni faqat sozlaydi.

Bundan ikkita amaliy xulosa chiqadi, ikkalasi ham keyin kerak bo'ladi:

  • yadroga qoida yozadigan yagona narsa ufw emas. Docker, fail2ban, provayderning sozlash skriptlari ham to'g'ridan-to'g'ri iptables'ga yozadi — va ufw ular haqida bilmaydi, ufw status da ko'rsatmaydi. Pastdagi Docker tuzog'i va fail2ban banlari "qayerda?" degan savol aynan shundan;

  • zamonaviy Ubuntu/Debian'da iptables buyrug'i aslida iptables-nft — nftables ustidagi moslik qatlami. Siz uchun shaffof, bilib qo'yish kifoya.

CentOS / RHEL / Fedora'da

U yerda ufw yo'q, firewalld bor — mantiq bir xil (zonalar, xizmatlar, portlar), buyruqlar boshqa: firewall-cmd --add-service=http --permanent. Bu maqola Ubuntu/Debian haqida; firewalld'ni alohida yozaman.

Nimadan himoya qiladi, nimadan qilmaydi#

Firewall — tarmoq darajasidagi to'siq. U quyidagilarni beradi:

  • tasodifan ochiq qolgan xizmatlar (baza, kesh, admin panel, monitoring) tashqaridan ko'rinmaydi;

  • SSH'ga brute-force urinishlari kamayadi (limit qoidasi bilan);

  • "faqat shu IP'dan" va "faqat ichki tarmoqdan" kabi chegaralar bir joyda turadi — ilova kodida emas.

U quyidagilarni bermaydi:

  • 80/443 ochiq bo'lsa, ilovangizdagi xatodan (SQL injection, buzuq auth) himoya qilmaydi — u portni ochdi, ichkarida nima bo'lishi uning ishi emas;

  • parolsiz Redis'ni xavfsiz qilmaydi — faqat uni yashiradi. Ikki qatlam kerak: xizmat 127.0.0.1ga bog'langan va firewall yopiq;

  • provayderning bulut firewall'i (security group) o'rnini bosmaydi — ular birga ishlaydi (pastda).

Qachon firewall kerak#

Qisqa javob: internetga ochiq har qanday serverda, birinchi soatda. Uzunroq javobda uchta holat bor.

1. Provayderda tashqi firewall yo'q (oddiy VPS). Bu eng keng tarqalgan holat: pochtaga IP va root parol keladi, server to'g'ridan-to'g'ri internetda. ufw bu yerda yagona to'siq — u shart.

2. Provayderda security group bor (AWS, Hetzner Cloud, DigitalOcean). Ko'pchilik "tashqarida firewall bor-ku" deb ichkarida hech narsa qilmaydi. Baribir ufw qo'ying: security group'ni kimdir "vaqtincha" ochib qo'yishi, server boshqa provayderga ko'chishi yoki ichki tarmoqdagi boshqa mashina buzilishi mumkin. Ikki qatlam bir-birini sug'urtalaydi; buni defense in depth deyiladi.

3. Bir nechta server (app, baza, monitoring). Bu yerda firewall shunchaki "yopish" emas, kim kimga ulanishi mumkinligini tavsiflaydi: baza faqat app serverdan, monitoring porti faqat monitoring serveridan. Bu qoidalar ilova kodida emas, firewall'da turgani to'g'ri.

Firewall kerak bo'lmagan yagona holat — internetga umuman chiqmaydigan mashina (masalan, faqat ichki tarmoqdagi test stendi). Ammo "keyin ochamiz" degan stend odatda ochilib ketadi.

Boshlashdan oldin: uchta oltin qoida va muhit#

Firewall bilan ishlashdagi birinchi raqamli xato — admin o'zini serverdan yopib qo'yishi (lockout). Bu har kuni minglab odam bilan bo'ladi, va oldini olish uch qoidaga bog'liq:

  1. Har doim ikkita SSH sessiya oching. Birida o'zgartirasiz, ikkinchisi "zaxira eshik" bo'lib turadi. Firewall mavjud ulanishlarni uzmaydi, faqat yangilarini to'sadi — noto'g'ri sozlab qo'ysangiz, ikkinchi (allaqachon ochiq) sessiyada tuzatasiz.
  2. Avval ruxsat, keyin taqiq. SSH portiga ruxsat bermay turib firewall yoqilmaydi. Nuqta.
  3. Provayder konsolini hoziroq toping. DigitalOcean, Hetzner, Vultr, AWS, Fornex — hammasida panel ichida VNC/veb-konsol bor. Bu SSH ishlamay qolganda kiradigan favqulodda eshik; qayerdaligini yopilib qolgandan keyin emas, hozir bilib qo'ying.

Qayerda mashq qilish#

Birinchi marta ish serverida (production) emas. Ikki variant:

  • arzon VPS — eng yaxshisi: real IP'ga internetdan real botlar keladi, firewall va keyin fail2ban'ning ishini jonli ko'rasiz. Yangi VPS ochilganidan 10–15 daqiqa o'tib loglarda allaqachon parol terish urinishlari paydo bo'ladi — bu mubolag'a emas;

  • lokal virtual mashina (VirtualBox, UTM, KVM + Ubuntu Server ISO) — bepul, lekin tashqi hujum bo'lmaydi; tekshiruvlarni o'zingiz qilasiz.

Tizimni aniqlab oling#

Qo'llanmadagi buyruq "ishlamasligi"ning yarmi shu yerdan: boshqa distributivda o'tirgan bo'lasiz.

Terminal
head -3 /etc/os-release
# PRETTY_NAME="Ubuntu 24.04.1 LTS"
# NAME="Ubuntu"
# VERSION_ID="24.04"
ID= Holat
ubuntu, debian ufw'ning tabiiy muhiti — bu maqola to'g'ridan-to'g'ri sizga
centos, rhel, almalinux, rocky ufw standart emas, firewalld ishlatiladi (yuqoridagi izoh). Ikkalasini birga qo'ymang — to'qnashadi
alpine na ufw, na systemd — bu maqolaning ko'p buyrug'i ishlamaydi

root'misiz yoki oddiy foydalanuvchi#

Terminal
whoami

root chiqsa — buyruqlardagi sudo ni yozmasangiz ham bo'ladi. Oddiy foydalanuvchi bo'lsangiz sudo kerak, va shu yerda klassik "menda ishlamayapti" bor: Debian'ning minimal o'rnatmasida sudo umuman yo'q — sudo ufw status deysiz, bash: sudo: command not found chiqadi. Bu ufw'ning aybi emas:

Terminal
su -                              # root paroli so'raladi
apt update && apt install -y sudo
usermod -aG sudo asadbek          # o'z foydalanuvchingiz
exit

Keyin chiqib qayta kiring — guruhga a'zolik faqat yangi sessiyada kuchga kiradi. Bu ham ko'pchilik qoqiladigan joy.

Boshlash: hozirgi holatni ko'ramiz#

Ubuntu Server'da ufw o'rnatilgan keladi, Debian'da — yo'q. Ikkalasida ham bir xil buyruq bilan ishonch hosil qilamiz:

Terminal
sudo apt update && sudo apt install -y ufw
sudo ufw status verbose
# Status: inactive

inactive — normal: o'rnatilgan, lekin hech narsani bloklamayapti. O'rnatgandan keyin ham ufw: command not found chiqsa — siz root emassiz va /usr/sbin sizning PATH ingizda yo'q (Debian'da oddiy foydalanuvchi uchun odatiy hol). sudo /usr/sbin/ufw status ishlaydi; to'g'ri yechim — yuqoridagi sudo sozlamasi.

Yoqishdan oldin serverda kim tinglayotganini ko'rib olamiz — firewall aynan shu ro'yxat bilan ishlaydi, uni bilmay turib "nimani yopish kerak"ni ham bilib bo'lmaydi:

Terminal
sudo ss -tulpn

Bayroqlarni yodlab oling, ish davomida yuz marta kerak bo'ladi: tcp, udp, listening (tinglayotganlar), process (qaysi dastur), numeric (port nomi o'rniga raqam). Eski qo'llanmalardagi netstat -tulpn — shu ishning o'zi, lekin yangi tizimlarda netstat o'rnatilmagan (net-tools paketi kerak); ss har doim bor.

Natija
Netid  State   Local Address:Port   Process
tcp    LISTEN  0.0.0.0:22           sshd
tcp    LISTEN  0.0.0.0:80           nginx
tcp    LISTEN  0.0.0.0:443          nginx
tcp    LISTEN  0.0.0.0:5432         postgres      ← muammo
tcp    LISTEN  127.0.0.1:6379       redis-server  ← faqat lokal, yaxshi
tcp    LISTEN  127.0.0.1:8000       gunicorn      ← faqat lokal, yaxshi

0.0.0.0 — "hamma interfeyslarda, butun internetga". 127.0.0.1 — faqat shu mashinaning ichida. Yuqoridagi ro'yxatda Postgres butun internetga ochiq: uning listen_addresses = '*' qilib qo'yilgani ko'rinib turibdi. Firewall uni yopadi, lekin to'g'ri yechim ikkalasi: Postgres'ni kerak bo'lmasa localhostga qaytarish va firewall.

Tez-tez beriladigan savol: "Redis 6379 da — uni ufw'da ochishim kerakmi?" Yo'q. Local Address 127.0.0.1 bo'lsa, tashqi dunyo uchun bu port mavjud emas — firewall qoidasi ham kerak emas, u baribir ko'rinmaydi. Qoida faqat 0.0.0.0 (yoki serverning tashqi IP'si) da tinglayotganlar uchun kerak.

Birinchi to'rt buyruq va ular ortidagi mantiq#

Terminal
sudo ufw default deny incoming    # kiruvchi: hammasi yopiq
sudo ufw default allow outgoing   # chiquvchi: ochiq — apt, pip, API chaqiruvlar
sudo ufw allow OpenSSH            # SSH — enable'dan OLDIN, aks holda o'zimizni yopamiz
sudo ufw enable

Bu ikki yondashuvdan birini tanlash: "hammasiga ruxsat, yomonini taqiqlayman" (denylist) yoki "hammasi taqiq, keraklisiga ruxsat" (allowlist). Real ishda faqat ikkinchisi ishlatiladi — barcha "yomon" portlarni oldindan bilib bo'lmaydi, keraklilari esa sanoqli.

default deny incoming — asosiy qaror. Bundan keyin ro'yxatda yo'q har qanday port yopiq. allow outgoing — server o'zi tashqariga chiqishi mumkin (paket yangilash, Telegram API, tashqi baza). Chiquvchini ham cheklash mumkin (default deny outgoing), lekin bu boshlovchi uchun tuzoq: apt, DNS, NTP birdan ishlamay qoladi va sababini soatlab qidirasiz. Oddiy web serverda kerak emas.

ufw enable so'rov chiqaradi: Command may disrupt existing ssh connections. Proceed with operation (y|n)? — bu standart ogohlantirish; SSH'ga ruxsat bergan bo'lsangiz dadil y. Yoqilgan zahoti ikkinchi terminalda yangi SSH sessiya oching. Ochildimi — davom etamiz. Ochilmadimi — birinchi (hali tirik) sessiyada sudo ufw disable va SSH qoidasiga qaytamiz.

Eng ko'p uchraydigan xato: o'zini SSH'dan yopib qo'yish

ufw enable mavjud SSH sessiyani uzmaydi — shuning uchun xato darrov sezilmaydi. Keyingi ulanishda esa server javob bermaydi. Tartib qat'iy: avval allow OpenSSH (yoki portingiz), keyin enable. Va portni faraz qilmang, tekshiring: sudo ss -tlnp | grep -E ':22 |:2222 ' — qaysi port chiqsa, o'shani oching. Baribir yopilib qolsangiz — boshidagi uchinchi qoida: provayder konsoli orqali kirib sudo ufw disable.

OpenSSH bu nima — port emas-ku?#

ufw'da ilova profillari bor. Paketlar o'rnatilganda ular o'z profilini /etc/ufw/applications.d/ ga qo'yadi:

Terminal
sudo ufw app list
# Available applications:
#   Nginx Full
#   Nginx HTTP
#   Nginx HTTPS
#   OpenSSH

sudo ufw app info OpenSSH
# Profile: OpenSSH
# Title: Secure shell server, an rshd replacement
# ...
# Port:
#   22/tcp
INI
# /etc/ufw/applications.d/openssh-server
[OpenSSH]
title=Secure shell server, an rshd replacement
description=OpenSSH is a free implementation of the Secure Shell protocol.
ports=22/tcp

allow OpenSSH bilan allow 22/tcp bir xil ish. Farq — o'qilishida: ufw status da "OpenSSH" so'zi "22" raqamidan tushunarliroq. Web server uchun ham shunday: allow 'Nginx Full' = 80 va 443.

SSH portini o'zgartirgan bo'lsangiz

/etc/ssh/sshd_config da Port 2222 bo'lsa, OpenSSH profili baribir 22 ni ochadi — u sozlamangizni o'qimaydi. Bunda aniq port bilan: sudo ufw allow 2222/tcp comment 'SSH'.

ufw va systemd: reboot'dan keyin nima bo'ladi#

ufw ham oddiy systemd xizmati — reboot'da qoidalarni yadroga qayta yuklaydi:

Terminal
systemctl status ufw
# ● ufw.service - Uncomplicated firewall
#      Loaded: loaded (/lib/systemd/system/ufw.service; enabled; ...)
#      Active: active (exited)

active (exited) — xizmat qoidalarni yuklab, o'z ishini tugatgan; u fon jarayoni sifatida ishlamaydi, chunki filtrlashning o'zini yadro qiladi. Ikki narsa muhim:

  • enabled — reboot'da o'zi ko'tariladi (sudo systemctl enable ufw, odatda allaqachon shunday);

  • /etc/ufw/ufw.conf dagi ENABLED=yes — ufw enable shu qatorni yozadi. Aynan shu ikkisi birga "reboot'dan keyin firewall bormi?" savoliga javob.

Terminal
grep ENABLED /etc/ufw/ufw.conf
# ENABLED=yes

Qoidalarning o'zi /etc/ufw/user.rules (va IPv6 uchun user6.rules) da saqlanadi — ularni qo'lda tahrirlash tavsiya etilmaydi, ufw buyrug'i orqali boshqaring. ufw disable xizmatni to'xtatmaydi, faqat qoidalarni yadrodan olib tashlaydi va ENABLED=no qiladi.

Reboot testi

Sozlab bo'lgach bir marta sudo reboot qilib, qayta kirgach sudo ufw status ni tekshiring. Reboot'ga chidamlilik auditi maqolasidagi ro'yxatga firewall'ni ham qo'shing.

Qoidalar tili#

Umumiy shakl:

Sintaksis
ufw [insert N] allow|deny|reject|limit [in|out] [on INTERFEYS]
    [proto tcp|udp] [from MANZIL [port P]] [to MANZIL [port P]] [comment '...']

Ko'p ishlatiladiganlari:

Terminal
# port + protokol
sudo ufw allow 443/tcp
sudo ufw allow 53/udp

# faqat bitta IP'dan (app serverdan Postgres'ga)
sudo ufw allow from 203.0.113.10 to any port 5432 proto tcp

# butun ichki tarmoqdan (10.0.0.0/24 — CIDR yozuvi: 10.0.0.0 dan 10.0.0.255 gacha, 256 ta manzil)
sudo ufw allow from 10.0.0.0/24 to any port 5432 proto tcp

# faqat ma'lum interfeys orqali (provayderning xususiy tarmog'i)
sudo ufw allow in on ens10 to any port 5432 proto tcp

# brute-force'ga qarshi: 30 soniyada 6 tadan ko'p urinish — bloklanadi
sudo ufw limit OpenSSH comment 'ssh brute-force limit'

Uchta harakatning farqi:

Harakat Nima bo'ladi Qachon
deny paket jimgina tashlanadi, ulanuvchi timeout kutadi tashqi dunyo uchun (skaner "port bormi-yo'qmi" bilmaydi)
reject ulanuvchiga "rad etildi" qaytadi ichki tarmoq uchun (o'z xizmatlaringiz darrov xato oladi, osilib qolmaydi)
limit ruxsat, lekin bir IP'dan 30 s ichida 6+ urinish bo'lsa vaqtincha yopiladi SSH va boshqa login portlari

limit haqida bir aniqlik: u parol to'g'ri yoki noto'g'riligini bilmaydi, faqat ulanish tezligini sanaydi. Sekin, har daqiqada bittadan parol terib ko'radigan botga u hech narsa qilmaydi. Buning uchun loglarni o'qiydigan fail2ban kerak — limit uning o'rnini bosmaydi, lekin arzon qo'shimcha qatlam sifatida u bilan birga bemalol ishlaydi.

Tartib muhim#

Qoidalar yuqoridan pastga o'qiladi, birinchi mos kelgani ishlaydi. Shuning uchun "hamma uchun yopiq, bitta IP uchun ochiq" qoidalari to'g'ri tartibda turishi kerak:

Terminal
sudo ufw status numbered
# [ 1] OpenSSH                    LIMIT IN    Anywhere
# [ 2] 80,443/tcp (Nginx Full)    ALLOW IN    Anywhere
# [ 3] 5432/tcp                   ALLOW IN    203.0.113.10
# [ 4] 5432/tcp                   DENY IN     Anywhere       ← ruxsatdan KEYIN

# kerakli joyga qo'yish:
sudo ufw insert 3 allow from 203.0.113.20 to any port 5432 proto tcp
# o'chirish — raqam bo'yicha (raqamlar o'chirishdan keyin siljiydi, qayta ko'ring)
sudo ufw delete 4

Aslida default deny incoming bo'lgani uchun 4-qator ortiqcha — u faqat "aniq ko'rinib tursin" deganlar uchun. Oddiy holatda: ruxsat qoidalari + default deny yetarli.

Tartibda eng ko'p qoqiladigan joy — bitta IP'ni bloklash. Sizda allow 80 bor, spam bot keldi:

Terminal
sudo ufw deny from 203.0.113.50        # ISHLAMAYDI

Nega: yangi qoida ro'yxat oxiriga qo'shiladi, paket esa unga yetguncha yuqoridagi allow 80/tcp ga mos kelib o'tib ketadi. To'g'risi — boshiga qo'yish:

Terminal
sudo ufw insert 1 deny from 203.0.113.50 comment 'spam bot'

Yuqoridagi "ishlamaydigan" buyruqni sinab ko'rgan bo'lsangiz, insert javobiga qarang. Skipping inserting existing rule chiqsa, ufw bunday qoida allaqachon borligini ko'rib, yangisini qo'shmagan — eski qoida esa oxirida turibdi. Avval uni o'chiring, keyin insert ni qaytaring:

Terminal
sudo ufw delete deny from 203.0.113.50
sudo ufw insert 1 deny from 203.0.113.50 comment 'spam bot'

Shu mantiq bilan fail2ban ham, banaction = ufw bilan sozlansa, banlarini ro'yxatning 1-o'rniga yozadi — buni keyingi maqolada o'z ko'zingiz bilan ko'rasiz.

O'chirishda ham nozik joy bor: delete 4 dan keyin qolganlar qayta raqamlanadi. Ikki qoidani o'chirmoqchi bo'lsangiz kattasidan boshlang (avval 4, keyin 3), aks holda ikkinchi buyruq boshqa qoidani o'chirib yuboradi — skriptlarda ayniqsa xavfli. Raqamsiz, qoida matni bo'yicha o'chirish ham mumkin: sudo ufw delete allow 80/tcp.

Izohlar — kelajakdagi o'zingiz uchun#

Har qoidaga comment yozing. Olti oydan keyin 9100/tcp ALLOW 198.51.100.7 nima ekanini eslash qiyin; comment 'prometheus -> node_exporter' bo'lsa — bir qarashda tushunarli.

Real ssenariylar#

1. Oddiy web server (nginx + Django + lokal baza)#

Eng ko'p uchraydigan holat. Baza va kesh 127.0.0.1 da, tashqariga faqat SSH va web:

Terminal
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw limit OpenSSH comment 'ssh, brute-force limit bilan'
sudo ufw allow 'Nginx Full' comment 'http + https'
sudo ufw enable

Shu bilan tamom. Postgres, Redis, gunicorn (8000) — hech biri ro'yxatda yo'q, demak yopiq. Sayt faqat HTTPS bo'lsa ham 80 ni oching — Let's Encrypt sertifikat olish/yangilash va HTTP → HTTPS yo'naltirish shu port orqali ishlaydi. Tekshirish:

Terminal
sudo ufw status verbose
# Status: active
# Logging: on (low)
# Default: deny (incoming), allow (outgoing), disabled (routed)
#
# To                         Action      From
# --                         ------      ----
# 22/tcp (OpenSSH)           LIMIT IN    Anywhere
# 80,443/tcp (Nginx Full)    ALLOW IN    Anywhere

2. SSH faqat mening IP'imdan#

Ofis yoki uyda statik IP bo'lsa, SSH'ni faqat undan ochish — kuchli himoya: dunyoning qolgan qismi uchun 22-port umuman yo'q.

Terminal
sudo ufw delete limit OpenSSH
sudo ufw allow from 198.51.100.42 to any port 22 proto tcp comment 'ssh faqat ofisdan'

Lekin ikki xavf bor. Birinchisi — IP o'zgarishi: uy interneti odatda dinamik IP beradi, ertaga u boshqa bo'ladi va siz serverga kira olmaysiz. Ikkinchisi — safarda, telefondan, boshqa joydan kirish. Shuning uchun men odatda yuqoridagi qat'iy variant o'rniga murosali yo'lni tanlayman: asosiy IP uchun allow, qolgan dunyo uchun limit (yopiq emas, lekin brute-force sekinlashadi), va parol bilan kirish o'chirilgan — kalitsiz baribir kirib bo'lmaydi. Birinchi blokni bajargan bo'lsangiz, ofis qoidasi allaqachon bor, unga faqat limit qo'shiladi:

Terminal
sudo ufw allow from 198.51.100.42 to any port 22 proto tcp comment 'ssh ofis'
sudo ufw limit 22/tcp comment 'ssh qolgan dunyo, limit bilan'

Tartib bu yerda ham ishlaydi: ofis IP'si birinchi qoidaga mos keladi va limit ga yetib bormaydi, qolganlar esa ikkinchi qoidaga tushadi.

Statik IP bo'lsa va zaxira yo'l (provayder konsoli) bo'lsa — faqat birinchi qoidani qoldirsangiz ham bo'ladi.

3. Baza alohida serverda: bitta IP va xususiy interfeys#

App server (203.0.113.10) va baza serveri alohida. Bazada Postgres tashqariga ochilishi kerak — lekin faqat app serverga. Bazani Anywhere ga ochiq qoldirish — ishdan haydalish darajasidagi xato: parolsiz yoki zaif parolli ochiq MongoDB/Elasticsearch'lardan sizib chiqqan minglab ma'lumotlar bazasi aynan shunday boshlangan.

Terminal
# baza serverida: faqat app serverdan
sudo ufw allow from 203.0.113.10 to any port 5432 proto tcp

Ko'p provayderlar (Hetzner, DigitalOcean, Fornex'ning ba'zi tariflari) serverlar orasida xususiy tarmoq beradi — alohida interfeys, masalan ens10, 10.0.0.x manzillar bilan. Bu holda qoidani interfeysga bog'lash yanada to'g'ri — tashqi IP orqali umuman o'tmaydi:

Terminal
ip -brief addr
# lo       UNKNOWN  127.0.0.1/8
# eth0     UP       203.0.113.11/24      ← tashqi
# ens10    UP       10.0.0.3/24          ← xususiy tarmoq

# faqat xususiy interfeys orqali
sudo ufw allow in on ens10 to any port 5432 proto tcp

Va Postgres'ning o'zida ham shu manzilni tinglash (listen_addresses = '10.0.0.3' — /etc/postgresql/16/main/postgresql.conf) + pg_hba.conf da faqat app serverning manzili. Uch qatlam: firewall, tinglash manzili, Postgres autentifikatsiyasi.

4. Monitoring: faqat bitta serverdan, faqat bitta port#

node_exporter 9100 portda tinglaydi va serverning ichki holatini beradi — uni internetga ochish mumkin emas, lekin Prometheus serveridan ko'rinishi kerak:

Terminal
# faqat Prometheus serveridan
sudo ufw allow from 198.51.100.7 to any port 9100 proto tcp

5. Docker — ufw'ni aylanib o'tadi#

Bu eng ko'p qon to'kadigan tuzoq. Docker konteynerni -p 8000:8000 bilan ishga tushirsangiz, u o'z iptables qoidalarini yozadi va ufw'dagi default deny ni chetlab o'tib portni butun internetga ochadi. ufw status da hech narsa ko'rinmaydi, port esa ochiq.

Ikki ishonchli yechim:

Terminal
# 1) konteyner portini faqat localhost'ga bog'lash — nginx oldida turadi
docker run -p 127.0.0.1:8000:8000 ...
YAML
# docker-compose.yml
services:
  web:
    ports:
      - "127.0.0.1:8000:8000"   # 0.0.0.0 emas!
Terminal
# 2) tashqariga port umuman kerak bo'lmasa — -p yozmang:
#    bir docker network ichidagi konteynerlar portsiz ham bir-birini ko'radi
docker network create app-net      # bir marta
docker run --network app-net ...

Uchinchi, murakkabroq yo'l ham bor — /etc/docker/daemon.json da { "iptables": false } yoki ufw-docker skripti. Lekin birinchisi Docker tarmog'ini sindirishi mumkin; boshlovchi darajasida tavsiya qilmayman.

Amalda birinchi yechim yetarli va xavfsizroq: konteyner faqat lokal tinglaydi, tashqariga nginx orqali chiqadi, nginx portlari esa ufw'da ochiq. Qoida oddiy: -p yozayotganda har safar "bu butun dunyoga ochilyapti" deb o'ylang. Tekshiruv yana o'sha ss -tulpn: 0.0.0.0:8000 ko'rinsa — noto'g'ri.

6. IPv6#

Provayder IPv6 bergan bo'lsa, server ikkita manzil bilan internetda. ufw ikkalasini ham boshqaradi — faqat /etc/default/ufw da yoqilgan bo'lsin:

Terminal
grep IPV6 /etc/default/ufw
# IPV6=yes

yes bo'lsa har ufw allow avtomatik ikkala protokol uchun qoida yozadi (status da (v6) qatorlari ko'rinadi). no bo'lsa IPv6 orqali hamma narsa ochiq qoladi — serverda umuman IPv6 bormi, ip -6 addr da global manzil bilan tekshiring.

IPV6=yes ni qoidalar yozilgandan keyin yoqsangiz, eski qoidalarning v6 nusxasi o'z-o'zidan paydo bo'lmaydi — ufw disable && ufw enable ham ularni yaratmaydi. Har bir allow/limit buyrug'ini qayta bajaring: ufw IPv4 qismini Skipping adding existing rule deb o'tkazib, yetishmayotgan (v6) qoidasini qo'shadi.

7. SSH portini o'zgartirish — o'zini yopib qo'ymasdan#

22 → 2222 qilish himoya emas, shovqin kamaytirish: botlarning ko'pi faqat 22 ni uradi. Lekin noto'g'ri tartibda qilsangiz — lockout. Tartib qat'iy, beshta qadam:

Terminal
# 1) AVVAL yangi portni ochamiz — eskisi hali ham ochiq
sudo ufw allow 2222/tcp comment 'ssh yangi port'

# 2) sshd sozlamasi: Port 2222 (qator boshidagi # ni olib tashlang)
sudo nano /etc/ssh/sshd_config
sudo systemctl daemon-reload
sudo systemctl restart ssh

# 3) haqiqatan 2222 da tinglayaptimi?
sudo ss -tlnp | grep -E ':22 |:2222 '

3-qadamda hali ham :22 ko'rinsa — siz Ubuntu 22.10+ dasiz: u yerda ssh.service ni systemd'ning ssh.socket i uyg'otadi (socket activation — xizmat birinchi ulanish kelganda ishga tushadi) va portni aynan shu socket tinglaydi. Shuning uchun restart ssh yetmaydi, socket'ni qayta ishga tushirish kerak.

Ubuntu 24.04 va undan yangilarida maxsus generator sshd_config dagi Port ni o'zi o'qiydi. 2-qadamdagi daemon-reload socket sozlamasini yangiladi, endi uni qayta ishga tushiramiz:

Terminal
sudo systemctl restart ssh.socket
sudo ss -tlnp | grep -E ':22 |:2222 '     # endi faqat :2222

Hozirgi SSH sessiyangiz uzilmaydi — socket faqat yangi ulanishlarni qabul qiladi.

Ubuntu 22.10–23.10 da generator yo'q, portni socket'ga qo'lda yozamiz:

Terminal
sudo systemctl edit ssh.socket
# ochilgan faylga:
#   [Socket]
#   ListenStream=
#   ListenStream=2222
# (bo'sh ListenStream= eski 22 ni tozalaydi — usiz ikkalasi ham qoladi)
sudo systemctl daemon-reload && sudo systemctl restart ssh.socket
sudo ss -tlnp | grep -E ':22 |:2222 '     # endi faqat :2222
Terminal
# 4) HOZIRGI SESSIYANI YOPMASDAN, yangi terminalda:
ssh -p 2222 user@SERVER_IP
# kirdingizmi? faqat SHUNDAN KEYIN:

# 5) eski portni yopamiz
sudo ufw delete limit OpenSSH            # yoki allow OpenSSH — qaysi bo'lsa
sudo ufw status numbered                 # 2222/tcp bor, 22 yo'q

Oltinchi qadam fail2ban ga tegishli: jail'da port = 2222 yozish. Buni ko'pchilik unutadi.

Tekshirish: ichkaridan va tashqaridan#

Firewall "yoqildi" degani "to'g'ri ishlayapti" degani emas. Uch tekshiruv:

Terminal
# 1) qoidalar ro'yxati — men nimani ochdim?
sudo ufw status numbered

# 2) tinglayotgan portlar — server nimani ochib turibdi?
sudo ss -tulpn

# 3) tashqaridan — boshqa mashinadan (o'z kompyuteringizdan):
nc -zv -w 3 203.0.113.11 22      # ochiq: succeeded   (-w 3: 3 soniyadan ko'p kutma)
nc -zv -w 3 203.0.113.11 5432    # yopiq: timed out (deny) yoki refused (reject)

Windows'da nc yo'q — PowerShell'da xuddi shu tekshiruv: Test-NetConnection 203.0.113.11 -Port 5432 (TcpTestSucceeded : False — yopiq).

Batafsil skaner kerak bo'lsa — nmap -Pn 203.0.113.11 (faqat o'z serveringizga). Loglar:

Terminal
sudo ufw logging low            # off | low | medium | high | full

# rsyslog bor tizimlarda (Ubuntu'ning odatiy o'rnatmasi):
sudo tail -f /var/log/ufw.log
# minimal Debian 12 / ba'zi cloud obrazlarda rsyslog yo'q, fayl ham yo'q — journal'dan:
sudo journalctl -k --grep='UFW' -f

# [UFW BLOCK] IN=eth0 SRC=45.xx.xx.xx DST=203.0.113.11 PROTO=TCP SPT=54321 DPT=5432 ...

/var/log/ufw.log yo'q bo'lsa — buzilgan emas, tizimingiz loglarni faqat systemd journal'da saqlaydi. Yozuvni o'qish: SRC — kim urinyapti, DPT — sizning qaysi portingizga. low darajada faqat bloklangan paketlar yoziladi — buni yoqib qo'ying: "mijoz ulanolmayapti" degan muammoda birinchi qiladigan ish — shu logda uning IP'sini qidirish. [UFW BLOCK] bilan ko'rinsa, muammo firewall'da; ko'rinmasa — boshqa joyda, va bu keyingi bo'limning mavzusi. high/full loglarni tez to'ldiradi, faqat tekshiruv paytida.

"Portni ochdim, baribir ishlamayapti"#

ufw'da hammasi to'g'ri, ulanib bo'lmayapti — bu holat firewall'ning o'zidan ko'ra ko'proq uchraydi. Sabablar qatlam-baqatlam, ichkaridan tashqariga.

Xizmat umuman tinglayaptimi?

Terminal
sudo ss -tlnp | grep 8080

Hech narsa chiqmasa — firewall'ning aloqasi yo'q: dastur ishga tushmagan yoki boshqa portda. Chiqsa, Local Address'ga qarang: 127.0.0.1:8080 — dastur faqat localhost'ni tinglayapti va tashqaridan hech qanday firewall sozlamasi bilan ham ulanib bo'lmaydi. Dastur sozlamasida 0.0.0.0 (yoki server IP) ni tinglashga o'tkazish kerak — masalan, gunicorn'da --bind 0.0.0.0:8080, Node'da app.listen(8080, '0.0.0.0'). Va avval o'ylab ko'ring: rostdan tashqariga kerakmi, yoki nginx orqasida 127.0.0.1 to'g'rimi?

Provayderning tashqi firewall'i. Paket sizning ufw'ingizgacha yetib kelishi uchun avval provayder darajasidan o'tishi kerak:

  • AWS — Security Groups (standartda deyarli hammasi yopiq);
  • Hetzner, DigitalOcean, Vultr — panelda ixtiyoriy "Cloud Firewall"; yoqilgan bo'lsa, u birinchi filtrlaydi;

  • Oracle Cloud — mashhur tuzoq: ham paneldagi Security List, ham obraz ichida oldindan yozib qo'yilgan iptables qoidalari. Oracle'da "port ochilmayapti"ning katta qismi shu.

Belgisi: ufw log'ida bloklangan paket ko'rinmaydi (u serverga umuman yetib kelmayapti), tashqaridan esa nc timed out deydi. Bunda provayder panelini oching.

Docker — 5-ssenariy: port ufw'siz ham ochiq bo'lishi, yoki aksincha, Docker'ning o'z qoidasi ustun kelishi mumkin.

Diagnostika tartibi — yodlab oling, har safar shu ketma-ketlik:

  1. sudo ss -tlnp — xizmat tinglayaptimi, qaysi manzilda?
  2. curl localhost:PORT serverning o'zida — xizmat javob beryaptimi?
  3. sudo ufw status verbose — qoida bormi, to'g'ri portgami?
  4. ufw log — paket kelib bloklanyaptimi, yoki umuman kelmayaptimi?
  5. Provayder paneli — cloud firewall / security group.
  6. sudo iptables -L -n --line-numbers | head -50 — ufw'dan tashqari kimdir (Docker, fail2ban, provayder skripti) qoida yozganmi? Bu iptables'dagi to'liq manzara; ufw faqat o'zinikini ko'rsatadi.

Shu xatolar chiqsa#

  • Serverga SSH orqali kira olmayapman, ufw enable qilgandim.

    Provayder panelidagi konsol orqali kiring → sudo ufw disable → SSH qoidasini qo'shib, qayta enable. Kelajak uchun: enable'dan oldin sudo ufw show added bilan qoidalarni ko'rib chiqish odatini qiling — u firewall o'chiq paytda ham qo'shilgan qoidalarni ko'rsatadi.

  • Qoida qo'shdim, lekin ishlamayapti.

    Tartibni tekshiring: ufw status numbered — yuqoridagi umumiyroq qoida sizniki oldidan ishlab ketayotgan bo'lishi mumkin. Va protokol: allow 53 tcp+udp ni ochadi, allow 53/tcp faqat tcp ni.

  • Docker konteyner porti ochiq, ufw'da yo'q.

    Yuqoridagi 5-ssenariy: 127.0.0.1:port:port bilan bog'lang.

  • Skriptda ufw enable so'rov chiqarib to'xtab qolyapti.

    Interaktiv tasdiq so'raydi ("may disrupt existing ssh connections"). Avtomat sozlashda: sudo ufw --force enable.

  • Hammasini boshidan boshlamoqchiman.

    sudo ufw reset — barcha qoidalar o'chadi, firewall o'chadi (eski qoidalar /etc/ufw/*.rules.20260828_120000 ko'rinishida zaxiralanadi). Keyin to'rt buyruqdan qayta.

  • IPv6 orqali port ochiq qolibdi.

    /etc/default/ufw → IPV6=yes, keyin sudo ufw disable && sudo ufw enable. Eski qoidalarning v6 nusxasi shu bilan paydo bo'lmaydi: ufw status da (v6) qatorlari yo'q bo'lsa, har bir allow/limit ni qayta bajaring (6-ssenariy).

  • ufw: command not found / sudo: command not found.

    "Boshlashdan oldin" bo'limi: Debian'da ufw va sudo o'rnatilmagan bo'lishi mumkin; oddiy foydalanuvchi uchun /usr/sbin PATH'da yo'q.

  • Portni ochdim, tashqaridan yopiq, ufw log'da hech narsa yo'q.

    Paket serverga yetib kelmayapti — provayder firewall'i (security group, cloud firewall, Oracle'ning iptables'i). Yuqoridagi diagnostika tartibi.

Yakuniy ro'yxat#

Yangi serverda firewall bo'yicha mening tartibim:

  1. ss -tulpn — nima tinglayapti; keraksizini 127.0.0.1ga qaytarish.
  2. default deny incoming, default allow outgoing.
  3. SSH — limit bilan (statik IP bo'lsa — from IP bilan), enable'dan oldin.
  4. Web — 'Nginx Full'. Boshqa hech narsa.
  5. Serverlararo ulanishlar — faqat from IP yoki in on <xususiy interfeys>.
  6. Docker portlari — faqat 127.0.0.1:....
  7. IPV6=yes, logging low.
  8. ufw enable → status numbered → tashqaridan nc -zv → reboot testi.
  9. ufw status numbered chiqishini oddiy matn faylga saqlab qo'yish — yangi serverda qoidalarni user.rules ni ko'chirish bilan emas, ufw allow ... ni qayta terish bilan tiklash ishonchliroq.

Shu qismning buyruqlari#

Shpargalka
sudo ufw status verboseholat va default policy
sudo ufw status numberedraqamlangan qoidalar
sudo ufw app listilova profillari
sudo ufw default deny incomingkiruvchi yopiq
sudo ufw default allow outgoingchiquvchi ochiq
sudo ufw limit OpenSSHSSH, brute-force limit bilan
sudo ufw allow 'Nginx Full'80 + 443
sudo ufw allow from IP to any port 5432 proto tcp comment '...'bitta IP
sudo ufw allow in on ens10 to any port 5432 proto tcpinterfeys
sudo ufw insert 1 ...qoidani ma'lum joyga
sudo ufw delete Nraqam bo'yicha o'chirish (kattasidan boshlab!)
sudo ufw delete allow 80/tcpqoida matni bo'yicha o'chirish
sudo ufw enable / disable / reset
sudo ufw logging lowbloklanganlarni yozish
systemctl status ufwreboot'da ko'tariladimi
sudo journalctl -k --grep='UFW' -floglar journal'da bo'lsa
sudo iptables -L -n --line-numbersiptables'dagi to'liq manzara (Docker, fail2ban ham)
head -3 /etc/os-releaseqaysi distributiv
sudo ss -tulpnnima tinglayapti
nc -zv -w 3 SERVER_IP PORTtashqaridan tekshirish

Firewall — serverdagi eng arzon va eng ko'p foyda beradigan himoya: o'n daqiqa, to'rt-besh qoida, va tasodifan ochiq qolgan port muammosi butunlay yo'qoladi. Lekin bitta savol ochiq qoldi: SSH porti yopib bo'lmaydigan eshik — unga parol terib ko'radigan botlarni kim to'xtatadi? Bu keyingi maqolaning ishi — fail2ban; u shu maqoladagi ikki sessiya odati, ss -tlnp va qoidalar tartibi bilimiga tayanadi. Undan keyin — nginx'ni to'g'ri sozlash va HTTPS: firewall ochgan ikki portni nima kutib oladi.

29 daqiqa 16 marta o‘qildi