پورتهایی را ببندید که ufw پوشش نمیدهد
portguard یک اسکریپت bash است که هر دقیقه با cron اجرا میشود. به هر پورت TCP در حال گوشدادن همانطور وصل میشود که یک ماشین دیگر در شبکه وصل میشد، و هر پورتی را که جواب بدهد میبندد.
چرا ufw پورتها را از قلم میاندازد
Docker وقتی با دسترسی root اجرا شود، پورت را با قانونهای فایروال خودش منتشر میکند و ترافیک آن قانونها از ufw رد میشود. ممکن است پورتی از شبکه در دسترس باشد در حالی که ufw status چیزی برایش نشان نمیدهد.
خواندن قانونها نشان نمیدهد پورتی واقعاً در دسترس است یا نه، برای همین portguard آنها را نمیخواند. از یک network namespace جداگانه واقعاً وصل میشود و فقط به پاسخ پورت نگاه میکند.
هر دقیقه چه اتفاقی میافتد
- پورتهای TCP را که روی ماشین گوش میدهند فهرست میکند.
- هر کدام را از یک network namespace موقت آزمایش میکند، پس فایروال آزمایش را یک ماشین شبکه محلی میبیند.
- برای هر پورتی که جواب داد، یک قانون drop در nftables برای اتصالهای ورودی تازه میگذارد.
- برای هر پورت بستهشده یک هشدار syslog مینویسد و یک اعلان حیاتی روی دسکتاپ نشان میدهد.
نصب
فایلهای portguard و portguard.cron را از صفحه نسخهها بگیرید و با دسترسی root سر جایشان بگذارید. پیش از نصب کار cron، مقدار ALLOWED_PORTS را تنظیم کنید: فهرست پیشفرض خالی است و اولین اجرا همهٔ پورتهای در دسترس، از جمله SSH، را میبندد.
# the script: 0755, owned by root sudo install -m 0755 -o root -g root portguard /usr/local/sbin/portguard sudoedit /usr/local/sbin/portguard # set ALLOWED_PORTS first, e.g. "22" for SSH: an empty list blocks SSH too # the cron job: 0644, owned by root sudo install -m 0644 -o root -g root portguard.cron /etc/cron.d/portguard
برای برداشتن یک مسدودسازی، جدولی را که portguard ساخته پاک کنید:
sudo nft delete table inet portguard
برای اینکه عمداً پورتی باز بماند، شمارهاش را به ALLOWED_PORTS در /usr/local/sbin/portguard اضافه کنید. این کار پورتی را که portguard پیشتر بسته است دوباره باز نمیکند: ابتدا جدول را پاک کنید. با این کار همهٔ مسدودسازیها برداشته میشود و اجرای بعدی بقیه را دوباره میبندد.
چه چیزهایی را پوشش نمیدهد
- فقط پروتکل TCP پوشش داده میشود و شنوندههای UDP آزمایش نمیشوند.
- قانونهای ufw که فقط به شبکههای مبدأ، رابطها یا نشانیهای مقصد مشخصی اجازه میدهند شبیهسازی نمیشوند.
- حالت مسیریابی (routed gateway) در Docker شبیهسازی نمیشود.
- IPv6 باید روی میزبان فعال باشد: آزمایش یک نشانی IPv6 اضافه میکند و اگر این کار شکست بخورد، اجرا هشدار میدهد و هیچ پورتی را بررسی نمیکند.
- شنوندهای که به یک رابط واحد وصل شده باشد (IPv4 یا IPv6، مثلاً با
SO_BINDTODEVICEیا دامنهٔ%eth0) فقط ثبت میشود و آزمایش نمیشود. - پورتی که از قبل بسته شده، با افزودن به
ALLOWED_PORTSباز نمیشود؛ برای برداشتن همهٔ مسدودسازیها جدول را پاک کنید.
این پروژه با پروانه Apache-2.0 منتشر شده است. برای گزارش مشکل امنیتی به bb@cocode.dk نامه بنویسید.