← شروع آموزش

WIUNIX ACADEMY

تغییر اتمیک nftables؛ برگشت زمان‌دار رو قبل از قطع دسترسی تمرین کن

صفحهٔ 2 از 4؛ قبل از ادامه، مراحل قبلی و چیزهایی رو که لازم داری مرور کن.

آموزش متناسب با محیط تو

کجا اجرا می‌کنی؟

سیستم‌عامل و نسخهٔ سرورت رو انتخاب کن تا مراحل، دستورها و راه‌حل‌های همون محیط رو ببینی.

AlmaLinux 9بررسی‌شده با مستندات رسمی ·

آموزش متناسب با مقادیر تو

تنظیمات این آموزش

مقادیر نمونه رو با مشخصات سرورت عوض کن تا متن و دستورها با هم تغییر کنن. رمز، کلید خصوصی و توکن اینجا وارد نکن. مقدارها فقط توی همین زبانه می‌مونن و به سرور یا لینک اشتراک‌گذاری فرستاده نمی‌شن. قبل از اجرا، DNS، گواهی‌ها و تنظیمات دسترسی شبکه رو روی سرورت بررسی کن.

اگر آی‌پی، دامنه یا پورت‌های نمونه با سرورت فرق دارن، بخش تنظیمات پایین رو باز کن. مقدارها رو عوض کن و «اعمال در آموزش» رو بزن؛ بعد دستورهای تازه رو کپی کن.

تنظیم مقادیر برای محیط من8 مقدار قابل‌تغییر
05

قدم بعدی

فایل قانون سالم و پیشنهاد عمداً خراب رو آماده کنیم

در پوشهٔ انحصاری شواهد دو فایل تازه با دسترسی فقط root می‌سازیم و با sudoedit باز می‌کنیم. هر پنل بعدی رو در فایل متناظرش بذار. فایل موجود باعث توقف می‌شه؛ اگر رزرو فایل دوم شکست بخوره، ممکنه فایل اول خالی باقی مونده باشه. همان برخورد نام رو قبل از ادامه حل کن.

این فایل‌ها ورودی آزمایش هستن، نه تنظیم بوت میزبان. هیچ‌کدوم رو در پوشهٔ include فایروال توزیع نذار و به سرویس شروع سیستم عملیاتی وصل نکن.

bash

ترمینال ماشین مجازی آزمایشی قابل‌حذف

sudo sh -c 'set -euC; : > "$1/baseline.nft"; : > "$1/candidate.nft"' sh '/var/lib/academy-nft-rollback-lab' || exit 1
sudo chmod 0600 '/var/lib/academy-nft-rollback-lab/baseline.nft' '/var/lib/academy-nft-rollback-lab/candidate.nft' || exit 1
sudoedit '/var/lib/academy-nft-rollback-lab/baseline.nft' '/var/lib/academy-nft-rollback-lab/candidate.nft' || exit 1
از کجا بفهمم درست انجام شده؟

دو فایل تازه آماده‌اند تا محتوای قانون سالم و پیشنهاد بعدی رو داخلشون بذاری.

فقط درخواست echo کلاینت آزمایشی رو راه بدیم

قانون اولیه یک زنجیرهٔ ورودی inet با سیاست drop می‌سازه و loopback و درخواست ICMP echo از آدرس کلاینت انتخاب‌شده رو راه می‌ده. پاسخ از مسیر خروجیِ بدون فیلتر همین فضا می‌ره. این آزمایش کوچک IPv4، سیاست کامل IPv4/IPv6، DNS یا SSH نیست.

نام جدول داخل نقل‌قول است تا نام عمومیِ پذیرفته‌شده به نحو nft تبدیل نشه. روی میزبان واقعی، اولویت hook و زنجیره‌های دیگر و قانون‌های مدیر فعلی هم مهمن؛ فضای تازه این تمرین رو عمداً از آن‌ها جدا نگه می‌داره.

nft · /var/lib/academy-nft-rollback-lab/baseline.nft

محتوای فایل؛ در ترمینال اجرا نکن

table inet "academy_guard" {
    chain input {
        type filter hook input priority 0; policy drop;
        iifname "lo" accept
        ip saddr 192.0.2.2 icmp type echo-request counter accept
    }
}

پیشنهاد معتبر بنویسیم که عمداً ارتباط رو قطع می‌کنه

پیشنهاد تازه فقط جدول آزمایشی رو در یک batch بومی nft حذف و دوباره ایجاد می‌کنه. قانون drop صریح جای مجوز echo قبلی رو می‌گیره. وقتی فایل اعمال بشه، هر دو تغییر جدول با هم ثبت می‌شن؛ اگر حذف و ساخت رو به دستورهای جدا در حلقهٔ پوسته تبدیل کنی، دیگر همان تغییر اتمیک نیست.

بررسی این فایل می‌تونه موفق باشه، در حالی که دسترسی موردنظر خراب می‌شه. از همین اشتباه عمدی برای سنجیدن بازیابی استفاده می‌کنیم؛ پذیرش parser رو آزمون ارتباط حساب نمی‌کنیم.

nft · /var/lib/academy-nft-rollback-lab/candidate.nft

محتوای فایل؛ در ترمینال اجرا نکن

delete table inet "academy_guard"
table inet "academy_guard" {
    chain input {
        type filter hook input priority 0; policy drop;
        iifname "lo" accept
        ip saddr 192.0.2.2 icmp type echo-request counter drop
    }
}
06

قدم بعدی

قانون اولیه رو داخل فضای سرور بررسی و بارگذاری کن

قبل از قطع عمدی ارتباط، مطمئن می‌شیم قانون اولیه همان دسترسی سالمی رو می‌ده که بعداً می‌خوایم برگردونیم. فایل رو اول با ابزار و کرنل بررسی می‌کنیم تا بدون اعمال تغییر، خطاها معلوم بشن؛ بعد اون رو فقط داخل فضای سرور بارگذاری می‌کنیم. حالا از فضای کلاینت دوباره ارتباط رو بسنج و شمارندهٔ همین جدول رو ببین.

بخش انتخاب namespace رو حذف نکن و مقصد رو با ruleset میزبان عوض نکن. اگر بررسی اولیه جواب نداد، همین‌جا بایست؛ هنوز ارتباط سالمی نداریم که بخواهیم بعداً بهش برگردیم.

bash

ترمینال ماشین مجازی آزمایشی قابل‌حذف

sudo ip netns exec 'academy-nft-server' nft -c -f '/var/lib/academy-nft-rollback-lab/baseline.nft' || exit 1
sudo ip netns exec 'academy-nft-server' nft -f '/var/lib/academy-nft-rollback-lab/baseline.nft' || exit 1
sudo ip netns exec 'academy-nft-client' ping -c 2 -W 2 '192.0.2.1' || exit 1
sudo ip netns exec 'academy-nft-server' nft -n list table inet '"academy_guard"'
از کجا بفهمم درست انجام شده؟

جدول اولیه موجوده و ارتباط کلاینت جدا هنوز جواب می‌ده.

07

قدم بعدی

فایل برگشت رو فقط از همان جدول سالم بسازیم

از وضعیت واقعی همین جدول یک فایل برگشت مخصوص root می‌سازیم. فایل اول جدول رو حذف می‌کنه و بعد سیاست ثبت‌شده رو در همان تراکنش nft دوباره می‌سازه. صرفاً بارگذاری یک فهرست، جایگزینی انحصاری نیست؛ ممکنه با شیء موجود ترکیب بشه یا قانون تکراری بسازه، به‌جای اینکه تغییر رو برگردونه.

نسخهٔ برگشت فقط قانون‌های همین جدول رو نگه می‌داره. خروجی stateless عمداً مقدار زندهٔ شمارنده‌ها رو کنار می‌گذاره؛ connection tracking، وضعیت مدیر بیرونی و نشست برنامه هم با این فایل بازیابی نمی‌شن. در این نمونه مجموعهٔ زمان‌دار یا وابستگی میان جدول‌ها نداریم. روی میزبان مدیریت‌شده، بارگذاری نسخهٔ قدیمی ممکنه تغییر تازهٔ دیگری رو پاک کنه؛ برای همین فقط صاحب یک جدول در فضای جدا هستیم و هنگام آزمایش هم‌زمان ویرایشش نمی‌کنیم.

bash

ترمینال ماشین مجازی آزمایشی قابل‌حذف

sudo sh -c 'set -euC
out="$1/rollback.nft"
printf "delete table inet \"%s\"\n" "$3" > "$out"
ip netns exec "$2" nft -s -n list table inet "\"$3\"" >> "$out"
chmod 0600 "$out"
' sh '/var/lib/academy-nft-rollback-lab' 'academy-nft-server' 'academy_guard' || exit 1
sudo ip netns exec 'academy-nft-server' nft -c -f '/var/lib/academy-nft-rollback-lab/rollback.nft' || exit 1
sudo ip netns exec 'academy-nft-server' nft -c -f '/var/lib/academy-nft-rollback-lab/candidate.nft' || exit 1
از کجا بفهمم درست انجام شده؟

فایل کامل برگشتِ همین جدول و پیشنهاد تازه هر دو بررسی رو می‌گذرونن. شکست ساخت یا بررسی یعنی آزمایش متوقف می‌شه.

08

قدم بعدی

اول ثابت کنیم timer مستقل می‌تونه قانون سالم رو برگردونه

از مدیر سرویس سیستم یک timer کوتاه با نام جدا می‌گیریم. دستورش همان قفل فایل رو می‌گیره و قانون سالمِ بدون تغییر رو داخل namespace برمی‌گردونه. این یک sleep پس‌زمینهٔ وابسته به ترمینال نیست. نتیجهٔ موفق صریح و ارتباط سالم رو ببین و بعد سراغ مسلح‌کردن برگشت واقعی برو.

اگر ماشین مجازی خیلی معطل باشه، ممکنه چهار ثانیه برای پایان کافی نباشه؛ وضعیت همان timer و سرویس رو ببین و منتظر نتیجهٔ واقعی بمون. نبود نتیجه هنوز موفقیت نیست. گزینهٔ RemainAfterExit سرویس موفق رو در حالت active/exited برای بررسی نگه می‌داره تا خودمان جمعش کنیم؛ این timer تک‌نوبتی است، نه کار تکرارشونده.

bash

ترمینال ماشین مجازی آزمایشی قابل‌حذف

ip_bin=$(sudo sh -c 'command -v ip') || exit 1
nft_bin=$(sudo sh -c 'command -v nft') || exit 1
flock_bin=$(sudo sh -c 'command -v flock') || exit 1
sudo systemd-run --unit='academy-nft-rollback-rehearsal' --on-active=2s --timer-property=AccuracySec=1s --property=Type=oneshot --property=RemainAfterExit=yes "$flock_bin" -x '/var/lib/academy-nft-rollback-lab/change.lock' "$ip_bin" netns exec 'academy-nft-server' "$nft_bin" -f '/var/lib/academy-nft-rollback-lab/rollback.nft' || exit 1
sleep 4
test "$(systemctl show -p ActiveState --value 'academy-nft-rollback-rehearsal.service')" = active || exit 1
test "$(systemctl show -p SubState --value 'academy-nft-rollback-rehearsal.service')" = exited || exit 1
test "$(systemctl show -p Result --value 'academy-nft-rollback-rehearsal.service')" = success || exit 1
test "$(systemctl show -p ExecMainStatus --value 'academy-nft-rollback-rehearsal.service')" = 0 || exit 1
sudo journalctl -u 'academy-nft-rollback-rehearsal.service' --no-pager -n 30
sudo ip netns exec 'academy-nft-client' ping -c 2 -W 2 '192.0.2.1' || exit 1
از کجا بفهمم درست انجام شده؟

سرویس تمرینی Result=success و کد خروج صفر داره و کلاینت جدا هنوز جواب می‌گیره.

همهٔ آموزش‌های آکادمی ↗