19-bo‘lim

Zaxira nusxa, taymerlar va himoya

Ishlaydigan zaxira skripti, systemd taymerlari, tiklashni sinash va fail2ban bilan takroriy hujumlarni bloklash.

🕑 26 daqiqa o‘qish 📄 1 708 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Uch-ikki-bir qoidasi
  2. Nimani zaxiraga olish kerak
  3. Arxiv va tiklash
  4. O'sishli zaxira - rsync --link-dest
  5. Ma'lumotlar bazasi
  6. Zaxira skripti
  7. systemd taymerlari
  8. Tiklashni sinash
  9. fail2ban
  10. Nazorat skripti
  11. Xulosa

Zaxira nusxa - tiklash demak. Nusxa olingani hech nimani anglatmaydi, agar undan tiklab bo'lmasa. Bu bo'lim shu farqqa qurilgan.

Uch-ikki-bir qoidasi #

3-2-1 qoidasi 3 nusxa Asl ma'lumot + ikkita mustaqil zaxira 2 turli muhit Server diski + obyekt saqlash yoki boshqa disk 1 boshqa joyda Boshqa server, boshqa provayder, boshqa shahar Nima uchun "boshqa joyda" shart Zaxira o'sha serverning o'zida bo'lsa: disk yonsa - ikkalasi ham yo'q. Server buzilsa - hujumchi zaxirani ham o'chiradi. Bu birinchi qiladigan ishi. Provayder hisobi yopilsa - server ham, zaxira ham qo'lingizdan chiqadi. Zaxira serverga YOZISH huquqi bo'lsin, O'CHIRISH huquqi bo'lmasin.
Uchta nusxa, ikki xil muhit, bittasi butunlay boshqa joyda

Nimani zaxiraga olish kerak #

NimaNima uchun
Ma'lumotlar bazasiTiklab bo'lmaydigan yagona narsa
/etcButun server sozlamasi (2-bo'lim)
Foydalanuvchi yuklagan fayllar/var/www/.../yuklamalar
/homeFoydalanuvchi ma'lumotlari
Ilova kodiAgar Git da bo'lmasa
Zaxira skriptining o'ziAks holda tiklash usulini yo'qotasiz
Nima kerak emasSabab
/proc, /sysSoxta fayl tizimlari
/tmpVaqtinchalik
node_modules, vendorQayta o'rnatiladi
Jurnal fayllariOdatda kerak emas

Arxiv va tiklash #

Terminal
mkdir -p manba/ichki nusxa
echo "birinchi" > manba/a.txt
echo "ikkinchi" > manba/ichki/b.txt
Terminal
tar -czf nusxa/zaxira.tar.gz -C manba .
tar -tzf nusxa/zaxira.tar.gz | sort
Natija
./
./a.txt
./ichki/
./ichki/b.txt
BayroqVazifa
-cYaratish
-xOchish
-tRo'yxatni ko'rish
-zgzip bilan siqish
-f faylFayl nomi
-C katalogShu katalogga o'tib ishlash
--exclude=naqshChiqarib tashlash
Terminal
tar -czf nusxa/zaxira.tar.gz -C manba .
mkdir -p tiklangan
tar -xzf nusxa/zaxira.tar.gz -C tiklangan
find tiklangan -type f | sort
Natija
tiklangan/a.txt
tiklangan/ichki/b.txt
-C bilan ishlang, mutlaq yo'l bilan emas
Terminal
tar -czf zaxira.tar.gz /var/www/sayt

Bu arxivda yo'llar var/www/sayt/... bo'lib saqlanadi va tar ogohlantirish beradi. Ochganda esa joriy katalogda var/www/sayt/ tuzilmasi paydo bo'ladi - siz kutgan joyda emas.

To'g'ri shakl:

Terminal
tar -czf zaxira.tar.gz -C /var/www sayt

Endi arxivda sayt/... yotadi va uni istagan joyga ochish mumkin:

Terminal
tar -xzf zaxira.tar.gz -C /var/www

Ochishdan oldin doim tar -tzf bilan ichida nima borligini ko'ring - ayniqsa arxiv boshqa joydan kelgan bo'lsa.

Har kuni to'liq nusxa olish diskni tez to'ldiradi. rsync o'zgarmagan fayllar uchun qattiq havola yaratadi.

Terminal
mkdir -p kun1 kun2
rsync -a manba/ kun1/
echo "uchinchi" > manba/c.txt
rsync -a --link-dest=../kun1 manba/ kun2/
[ "$(stat -c %i kun1/a.txt)" = "$(stat -c %i kun2/a.txt)" ] \
    && echo "a.txt - bitta inode, disk joyi ikki marta band emas"
[ -f kun2/c.txt ] && echo "c.txt - yangi fayl, alohida nusxa"
Natija
a.txt - bitta inode, disk joyi ikki marta band emas
c.txt - yangi fayl, alohida nusxa

kun2 katalogi to'liq nusxaga o'xshaydi - unda hamma fayllar bor. Lekin o'zgarmagan fayllar diskda ikkinchi marta yozilmagan: ular 14-bo'limda ko'rgan qattiq havolalar.

Bu naqsh - Time Machine ning ishlash usuli

Har kun uchun alohida katalog, lekin disk faqat o'zgargan fayllar hajmicha o'sadi:

Terminal
rsync -a --delete \
    --link-dest="../$(date -d yesterday +%F)" \
    /var/www/ "/zaxira/$(date +%F)/"

Afzalliklari:

XususiyatIzoh
Har kun to'liq nusxaga o'xshaydiTiklash oson - shunchaki ko'chiring
Disk kam ishlatiladiFaqat o'zgarishlar
Eskisini o'chirish osonrm -rf /zaxira/2026-08-01
Zanjir yo'qBitta kunni o'chirish qolganlarga ta'sir qilmaydi

Oxirgisi muhim: an'anaviy "to'liq + o'sishli" sxemada oradagi bitta arxiv buzilsa, butun zanjir yaroqsiz bo'ladi. --link-dest da bunday bog'liqlik yo'q.

Ma'lumotlar bazasi #

Terminal
mysqldump --single-transaction --quick --routines \
    --databases softromeda_edu | gzip > /zaxira/baza.sql.gz
BayroqNima uchun
--single-transactionJadvalni qulflamaydi - sayt ishlashda davom etadi
--quickKatta jadvallarni xotiraga to'liq yuklamaydi
--routinesSaqlangan protseduralar
--databasesCREATE DATABASE ni ham qo'shadi
Ishlab turgan bazani tar bilan nusxalamang

/var/lib/mysql katalogini tar bilan arxivlash - buzilgan zaxira olishning ishonchli usuli. Nusxa olish paytida baza fayllarga yozishda davom etadi va arxivda yarim yozilgan holat qoladi.

To'g'ri usullar:

UsulQachon
mysqldump --single-transactionInnoDB uchun - eng oddiy
mariabackup / xtrabackupKatta bazalar, tez tiklash
Bazani to'xtatib tarFaqat texnik tanaffusda

--single-transaction InnoDB da ishlaydi, chunki u 16-17-bo'limlardagi ma'lumotlar bazasi darsligida ko'rgan REPEATABLE READ snapshotidan foydalanadi: dump butun davomida bitta izchil holatni ko'radi.

MyISAM jadvallar uchun bu ishlamaydi - u yerda --lock-tables kerak, ya'ni sayt to'xtaydi.

Zaxira skripti #

Bu skript darslik davomida to'plangan qoidalarni birlashtiradi.

Terminal
cat > zaxira.sh <<'EOF'
#!/bin/bash
set -euo pipefail
umask 077

MANBA="/var/www/sayt"
NUSXA="/zaxira"
QULF="/run/zaxira.pid"

exec > >(systemd-cat -t zaxira -p info) 2>&1

if [ -f "$QULF" ] && kill -0 "$(cat "$QULF")" 2>/dev/null; then
    echo "oldingi nusxa hali ishlayapti - chiqilmoqda"
    exit 0
fi
echo $$ > "$QULF"
trap 'rm -f "$QULF"' EXIT

SANA=$(date +%F)
echo "zaxira boshlandi: $SANA"

nice -n 19 ionice -c 3 \
    tar -czf "$NUSXA/sayt-$SANA.tar.gz" -C "$(dirname "$MANBA")" "$(basename "$MANBA")"

find "$NUSXA" -name 'sayt-*.tar.gz' -mtime +14 -delete

echo "zaxira tugadi: $(du -h "$NUSXA/sayt-$SANA.tar.gz" | cut -f1)"
EOF
chmod 755 zaxira.sh
bash -n zaxira.sh && echo "sintaksis to'g'ri"
Natija
sintaksis to'g'ri

Har qatorning sababi:

QatorQaysi bo'limdan
set -euo pipefailXatoda darhol to'xtash
umask 0774-bo'lim - arxivni faqat egasi o'qisin
exec > >(systemd-cat ...)13-bo'lim - jurnalga yozish
kill -0 bilan qulf10-bo'lim - oldingi nusxa ishlayaptimi
trap ... EXIT10-bo'lim - chiqishda tozalash
nice + ionice10-bo'lim - saytga xalaqit bermaslik
Mutlaq yo'llar2-bo'lim - cron boshqa katalogdan ishga tushiradi
find -mtime +14 -deleteEskilarini tozalash
set -e va quvurlar

set -e xato bo'lganda skriptni to'xtatadi - lekin quvurda faqat oxirgi buyruqning kodiga qaraydi:

Terminal
mysqldump baza | gzip > nusxa.sql.gz

mysqldump yiqilsa ham, gzip muvaffaqiyatli tugaydi - va sizda bo'sh, lekin "muvaffaqiyatli" arxiv qoladi.

set -o pipefail aynan shuni tuzatadi: quvurdagi istalgan buyruq yiqilsa, butun quvur xato hisoblanadi.

Shuning uchun uchtasi doim birga: set -euo pipefail.

-u esa e'lon qilinmagan o'zgaruvchini xato deb hisoblaydi - bu 7-bo'limdagi rm -rf $ZAXIRA /* halokatining oldini oladi.

systemd taymerlari #

cron o'rniga systemd taymerlari afzalroq.

Xususiyatcronsystemd taymeri
JurnalPochtaga yoki hech qayergajournalctl -u
O'tkazib yuborilgan ishlarYo'qoladiPersistent=true bilan bajariladi
Resurs chekloviYo'qMemoryMax, CPUQuota
Bog'liqliklarYo'qAfter=, Requires=
Tasodifiy kechikishQo'ldaRandomizedDelaySec=
Holatni ko'rishQiyinsystemctl list-timers
Terminal
rm -f /etc/systemd/system/sr-zaxira.service /etc/systemd/system/sr-zaxira.timer
cat > /etc/systemd/system/sr-zaxira.service <<'EOF'
[Unit]
Description=Softromeda zaxira nusxasi

[Service]
Type=oneshot
ExecStart=/bin/echo "zaxira bajarildi"
Nice=19
IOSchedulingClass=idle
EOF

cat > /etc/systemd/system/sr-zaxira.timer <<'EOF'
[Unit]
Description=Har kuni 03:30 da zaxira

[Timer]
OnCalendar=*-*-* 03:30:00
RandomizedDelaySec=15m
Persistent=true

[Install]
WantedBy=timers.target
EOF
systemctl daemon-reload
Terminal
systemd-analyze verify /etc/systemd/system/sr-zaxira.timer && echo "taymer to'g'ri"
Natija
taymer to'g'ri
Terminal
systemctl show sr-zaxira.timer -p Persistent -p RandomizedDelayUSec
Natija
RandomizedDelayUSec=15min
Persistent=yes
SozlamaNima beradi
OnCalendar=*-*-* 03:30:00Har kuni soat 03:30 da
Persistent=trueServer o'chiq bo'lgan bo'lsa - yoqilganda bajaradi
RandomizedDelaySec=15m0-15 daqiqa tasodifiy kechikish
OnBootSec=5minYuklanishdan 5 daqiqa keyin
OnUnitActiveSec=1hOxirgi bajarilishdan bir soat keyin
RandomizedDelaySec nima uchun kerak

Agar sizda o'nta server bo'lsa va hammasi soat 03:30 da zaxira olsa, ular bir vaqtda:

  • Bitta zaxira serveriga yozadi - tarmoq to'yinadi;
  • Bitta ma'lumotlar bazasidan o'qiydi;
  • Provayder tarmog'ida cho'qqi yaratadi.

Tasodifiy kechikish yukni yoyadi. Bu bulutdagi API so'rovlarida ham bir xil naqsh - "thundering herd" muammosining oddiy yechimi.

Persistent=true esa boshqa muammoni hal qiladi: noutbuk yoki vaqtincha o'chirilgan server soat 03:30 da o'chiq bo'lsa, cron ishni butunlay o'tkazib yuboradi, taymer esa yoqilishi bilan bajaradi.

Kalendar ifodasini tekshirish:

Terminal
systemd-analyze calendar '*-*-* 03:30:00' | grep 'Normalized'
Natija
Normalized form: *-*-* 03:30:00
Terminal
systemd-analyze calendar daily | grep 'Normalized'
Natija
Normalized form: *-*-* 00:00:00
Taymerni yoqish - taymerni, xizmatni emas
Terminal
sudo systemctl enable --now sr-zaxira.timer

.timer ni yoqasiz, .service ni emas. Xizmat enable qilinsa, u har yuklanishda ishga tushadi - bu kerak emas.

Tekshirish:

BuyruqNima ko'rsatadi
systemctl list-timersBarcha taymerlar va keyingi ishga tushish vaqti
systemctl status sr-zaxira.timerTaymer holati
journalctl -u sr-zaxiraBajarilish tarixi
systemctl start sr-zaxira.serviceQo'lda sinash

Oxirgisi muhim: taymerni kutmasdan, xizmatni qo'lda ishga tushirib sinang.

Terminal
systemctl start sr-zaxira.service
sleep 1
journalctl -u sr-zaxira -n 3 --no-pager -o cat | grep -c 'zaxira bajarildi'
Natija
1

Tiklashni sinash #

Sinalmagan zaxira - zaxira emas

Bu bo'limning eng muhim jumlasi.

Amalda ko'p uchraydigan holatlar:

HolatQachon aniqlanadi
Skript oyiga bir marta yiqilganTiklash kerak bo'lganda
Arxiv bo'sh (pipefail yo'q)Tiklash kerak bo'lganda
Baza dumpi buzilganTiklash kerak bo'lganda
Shifrlash kaliti yo'qolganTiklash kerak bo'lganda
Zaxira diski to'lganTiklash kerak bo'lganda

Barchasi bir xil vaqtda aniqlanadi - va bu eng yomon vaqt.

Chora:

AmaliyotQanchalik tez-tez
Arxiv hajmini tekshirishHar nusxadan keyin, avtomatik
Bitta faylni tiklab ko'rishHaftada
To'liq tiklashni sinashChoragiga bir marta
Tiklash tartibini yozib qo'yishBir marta, keyin yangilab turish

Oxirgisi ham muhim: tiklash tartibi serverning o'zida saqlanmasin. Server yo'q bo'lganda unga kira olmaysiz.

Terminal
tar -czf nusxa/sinov.tar.gz -C manba .
tar -tzf nusxa/sinov.tar.gz > /dev/null && echo "arxiv butun"
[ "$(stat -c %s nusxa/sinov.tar.gz)" -gt 100 ] && echo "arxiv bo'sh emas"
Natija
arxiv butun
arxiv bo'sh emas

Bu ikki tekshiruvni zaxira skriptining oxiriga qo'shing - ular bo'sh yoki buzilgan arxivni darhol aniqlaydi.

fail2ban #

SSH ga takroriy urinishlarni jurnaldan topib, IP ni vaqtincha bloklaydi.

Avval mexanizmni ko'ramiz - jurnaldan urinishlarni sanash:

Terminal
cat > auth.log <<'EOF'
Sep 10 08:14:02 srv sshd[1201]: Failed password for root from 203.0.113.55 port 41022 ssh2
Sep 10 08:14:05 srv sshd[1203]: Failed password for root from 203.0.113.55 port 41028 ssh2
Sep 10 08:14:09 srv sshd[1205]: Failed password for admin from 203.0.113.55 port 41034 ssh2
Sep 10 08:15:11 srv sshd[1210]: Failed password for husanboy from 198.51.100.7 port 50122 ssh2
Sep 10 08:16:40 srv sshd[1215]: Accepted publickey for husanboy from 198.51.100.7 port 50130 ssh2
EOF
grep 'Failed password' auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn
Natija
      3 203.0.113.55
      1 198.51.100.7

fail2ban aynan shuni avtomatlashtiradi: naqshni topadi, sanaydi va chegaradan oshsa xavfsizlik devoriga qoida qo'shadi.

Terminal
sudo apt install fail2ban
sudo tee /etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
backend  = systemd

[sshd]
enabled = true
EOF
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
SozlamaMa'no
maxretry = 5Necha urinishdan keyin
findtime = 10mShu oraliqda sanaladi
bantime = 1hQancha vaqtga bloklanadi
backend = systemdJurnalni journald dan o'qish
ignoreip = 10.0.0.0/8O'zingizni chiqarib qo'ying
fail2ban sizni ham bloklashi mumkin

Parolni bir necha marta noto'g'ri kiritsangiz, o'zingiz ham bloklanasiz.

Uchta chora:

ChoraIzoh
ignoreip ga ofis IP sini qo'shingDoimiy manzil bo'lsa
Kalit bilan kiring8-bo'lim - parol umuman ishlatilmaydi
Provayder konsolini bilingBloklanganda yagona yo'l

Blokni qo'lda yechish:

Terminal
sudo fail2ban-client set sshd unbanip 203.0.113.55

Muhim nuqta: fail2ban kalit bilan kirishning o'rnini bosmaydi. PasswordAuthentication no qo'yilgan serverda parol taxmin qilish hujumi allaqachon foydasiz - fail2ban esa faqat jurnalni tozaroq qiladi va yukni kamaytiradi.

Tartib shunday: avval kalit, keyin xavfsizlik devori, undan keyin fail2ban.

Nazorat skripti #

14 va 18-bo'limlarda va'da qilingan tekshiruvlarni birlashtiramiz:

Terminal
cat > nazorat.sh <<'EOF'
#!/bin/bash
set -uo pipefail
CHEGARA=85

df -h -x tmpfs -x devtmpfs --output=pcent,target | tail -n +2 |
while read -r foiz nuqta; do
    son=${foiz%\%}
    if [ "$son" -ge "$CHEGARA" ]; then
        logger -t nazorat -p user.warning "$nuqta ${son}% to'ldi"
    fi
done

if ! systemctl is-system-running --quiet; then
    logger -t nazorat -p user.warning \
        "yiqilgan xizmatlar: $(systemctl --failed --no-legend | wc -l)"
fi
EOF
chmod 755 nazorat.sh
bash -n nazorat.sh && echo "nazorat skripti to'g'ri"
Natija
nazorat skripti to'g'ri

Uni ham taymerga qo'ying - OnCalendar=hourly.

Ogohlantirish qayerga borishi kerak

logger xabarni jurnalga yozadi - lekin jurnalni hech kim o'qimasa, foydasi yo'q.

UsulIzoh
PochtaOddiy, lekin spamga tushishi mumkin
Telegram botTez, telefonda ko'rinadi
Monitoring tizimiZabbix, Prometheus + Alertmanager
systemd OnFailure=Xizmat yiqilganda xabar yuborish

Oxirgisi eng oddiy va ko'pincha yetarli:

Natija
[Unit]
OnFailure=xabar@%n.service

Endi har qanday xizmat yiqilganda xabar@ xizmati ishga tushadi va sizga yozadi.

Muhimi - ogohlantirish kam va ahamiyatli bo'lsin. Kuniga o'nlab xabar kelsa, siz ularni o'qishni to'xtatasiz - va haqiqiy muammoni o'tkazib yuborasiz.

Amaliy topshiriq
  1. tar -C bilan arxiv yarating va -t bilan ichini ko'ring.
  2. Arxivni boshqa katalogga tiklang.
  3. rsync --link-dest bilan o'sishli nusxa oling.
  4. stat -c %i bilan qattiq havolani tasdiqlang.
  5. Zaxira skriptini yozing - qulf, umask, nice bilan.
  6. set -o pipefail nima uchun kerakligini tushuntiring.
  7. systemd xizmati va taymerini yarating.
  8. systemd-analyze calendar bilan ifodani tekshiring.
  9. Jurnaldan muvaffaqiyatsiz urinishlarni IP bo'yicha sanang.
  10. bash -n bilan ikkala skriptni tekshiring.

Xulosa #

  • Zaxira nusxa emas, tiklash muhim - sinalmagan zaxira yo'q hisoblanadi.
  • 3-2-1: uch nusxa, ikki muhit, biri boshqa joyda.
  • Zaxira serverida o'chirish huquqi bo'lmasin.
  • tar -C ishlating, mutlaq yo'l bilan arxivlamang.
  • rsync --link-dest - to'liq ko'rinishli, lekin o'sishli nusxa.
  • Ishlab turgan bazani tar qilmang - mysqldump --single-transaction.
  • Skriptda set -euo pipefail; pipefail bo'sh arxivdan saqlaydi.
  • systemd taymeri cron dan afzal: jurnal, Persistent, cheklovlar.
  • .timer ni enable qiling, .service ni emas.
  • fail2ban kalit bilan kirishning o'rnini bosmaydi.

Keyingi va oxirgi bo'limda hamma narsani birlashtiramiz: bo'sh serverdan ishlaydigan saytgacha to'liq yo'l.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.