WIUNIX ACADEMY
تغییر اتمیک nftables؛ برگشت زماندار رو قبل از قطع دسترسی تمرین کن
صفحهٔ 2 از 4؛ قبل از ادامه، مراحل قبلی و چیزهایی رو که لازم داری مرور کن.
آموزش متناسب با محیط تو
کجا اجرا میکنی؟
سیستمعامل و نسخهٔ سرورت رو انتخاب کن تا مراحل، دستورها و راهحلهای همون محیط رو ببینی.
آموزش متناسب با مقادیر تو
تنظیمات این آموزش
مقادیر نمونه رو با مشخصات سرورت عوض کن تا متن و دستورها با هم تغییر کنن. رمز، کلید خصوصی و توکن اینجا وارد نکن. مقدارها فقط توی همین زبانه میمونن و به سرور یا لینک اشتراکگذاری فرستاده نمیشن. قبل از اجرا، DNS، گواهیها و تنظیمات دسترسی شبکه رو روی سرورت بررسی کن.
اگر آیپی، دامنه یا پورتهای نمونه با سرورت فرق دارن، بخش تنظیمات پایین رو باز کن. مقدارها رو عوض کن و «اعمال در آموزش» رو بزن؛ بعد دستورهای تازه رو کپی کن.
تنظیم مقادیر برای محیط من8 مقدار قابلتغییر
قدم بعدی
فایل قانون سالم و پیشنهاد عمداً خراب رو آماده کنیم
در پوشهٔ انحصاری شواهد دو فایل تازه با دسترسی فقط root میسازیم و با sudoedit باز میکنیم. هر پنل بعدی رو در فایل متناظرش بذار. فایل موجود باعث توقف میشه؛ اگر رزرو فایل دوم شکست بخوره، ممکنه فایل اول خالی باقی مونده باشه. همان برخورد نام رو قبل از ادامه حل کن.
این فایلها ورودی آزمایش هستن، نه تنظیم بوت میزبان. هیچکدوم رو در پوشهٔ include فایروال توزیع نذار و به سرویس شروع سیستم عملیاتی وصل نکن.
ترمینال ماشین مجازی آزمایشی قابلحذف
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 و زنجیرههای دیگر و قانونهای مدیر فعلی هم مهمن؛ فضای تازه این تمرین رو عمداً از آنها جدا نگه میداره.
محتوای فایل؛ در ترمینال اجرا نکن
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 رو آزمون ارتباط حساب نمیکنیم.
محتوای فایل؛ در ترمینال اجرا نکن
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
}
}
قدم بعدی
قانون اولیه رو داخل فضای سرور بررسی و بارگذاری کن
قبل از قطع عمدی ارتباط، مطمئن میشیم قانون اولیه همان دسترسی سالمی رو میده که بعداً میخوایم برگردونیم. فایل رو اول با ابزار و کرنل بررسی میکنیم تا بدون اعمال تغییر، خطاها معلوم بشن؛ بعد اون رو فقط داخل فضای سرور بارگذاری میکنیم. حالا از فضای کلاینت دوباره ارتباط رو بسنج و شمارندهٔ همین جدول رو ببین.
بخش انتخاب namespace رو حذف نکن و مقصد رو با ruleset میزبان عوض نکن. اگر بررسی اولیه جواب نداد، همینجا بایست؛ هنوز ارتباط سالمی نداریم که بخواهیم بعداً بهش برگردیم.
ترمینال ماشین مجازی آزمایشی قابلحذف
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"'
جدول اولیه موجوده و ارتباط کلاینت جدا هنوز جواب میده.
قدم بعدی
فایل برگشت رو فقط از همان جدول سالم بسازیم
از وضعیت واقعی همین جدول یک فایل برگشت مخصوص root میسازیم. فایل اول جدول رو حذف میکنه و بعد سیاست ثبتشده رو در همان تراکنش nft دوباره میسازه. صرفاً بارگذاری یک فهرست، جایگزینی انحصاری نیست؛ ممکنه با شیء موجود ترکیب بشه یا قانون تکراری بسازه، بهجای اینکه تغییر رو برگردونه.
نسخهٔ برگشت فقط قانونهای همین جدول رو نگه میداره. خروجی stateless عمداً مقدار زندهٔ شمارندهها رو کنار میگذاره؛ connection tracking، وضعیت مدیر بیرونی و نشست برنامه هم با این فایل بازیابی نمیشن. در این نمونه مجموعهٔ زماندار یا وابستگی میان جدولها نداریم. روی میزبان مدیریتشده، بارگذاری نسخهٔ قدیمی ممکنه تغییر تازهٔ دیگری رو پاک کنه؛ برای همین فقط صاحب یک جدول در فضای جدا هستیم و هنگام آزمایش همزمان ویرایشش نمیکنیم.
ترمینال ماشین مجازی آزمایشی قابلحذف
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
فایل کامل برگشتِ همین جدول و پیشنهاد تازه هر دو بررسی رو میگذرونن. شکست ساخت یا بررسی یعنی آزمایش متوقف میشه.
قدم بعدی
اول ثابت کنیم timer مستقل میتونه قانون سالم رو برگردونه
از مدیر سرویس سیستم یک timer کوتاه با نام جدا میگیریم. دستورش همان قفل فایل رو میگیره و قانون سالمِ بدون تغییر رو داخل namespace برمیگردونه. این یک sleep پسزمینهٔ وابسته به ترمینال نیست. نتیجهٔ موفق صریح و ارتباط سالم رو ببین و بعد سراغ مسلحکردن برگشت واقعی برو.
اگر ماشین مجازی خیلی معطل باشه، ممکنه چهار ثانیه برای پایان کافی نباشه؛ وضعیت همان timer و سرویس رو ببین و منتظر نتیجهٔ واقعی بمون. نبود نتیجه هنوز موفقیت نیست. گزینهٔ RemainAfterExit سرویس موفق رو در حالت active/exited برای بررسی نگه میداره تا خودمان جمعش کنیم؛ این timer تکنوبتی است، نه کار تکرارشونده.
ترمینال ماشین مجازی آزمایشی قابلحذف
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 و کد خروج صفر داره و کلاینت جدا هنوز جواب میگیره.