پرش به محتوا
آرش حاتمی

hatamiarash7/ ipset-exporter

سال توسعه: ۱۴۰۳ متن‌باز

پایش مجموعه‌های ipset با Prometheus

اکسپورتر سبک برای نمایش تعداد اعضای مجموعه‌های ipset در Prometheus، با خواندن مستقیم اطلاعات از Netlink، تنظیمات YAML و امکان اجرای مستقل یا Docker.

وقتی از ipset برای نگه‌داری مجموعه‌های مورد استفاده در قواعد فایروال لینوکس استفاده می‌کنید، تعداد اعضای هر مجموعه می‌تواند اطلاعات مفیدی دربارهٔ رشد یا خالی‌شدن فهرست‌ها بدهد. بررسی دستی این تعداد برای چندین میزبان کافی نیست؛ بهتر است تغییرات آن در سامانهٔ مانیتورینگ ثبت شود.

پروژهٔ ipset-exporter اطلاعات مجموعه‌ها را از کرنل می‌خواند و تعداد اعضای آن‌ها را به شکل متریک Prometheus منتشر می‌کند. می‌توانید فقط مجموعه‌های مشخصی را پایش کنید یا همهٔ مجموعه‌ها را در خروجی داشته باشید.

روش کار و خروجی

برنامه با Go نوشته شده و از طریق کتابخانهٔ Netlink به اطلاعات ipset دسترسی دارد؛ برای جمع‌آوری داده، خروجی متنی دستور ipset را پردازش نمی‌کند. یک بار هنگام شروع و سپس در فاصله‌های زمانی تنظیم‌شده، اطلاعات خوانده می‌شوند. درخواست‌های Prometheus آخرین مقادیر ثبت‌شده را دریافت می‌کنند.

متریک اصلی ipset_count از نوع Gauge است و نام مجموعه در برچسب set قرار می‌گیرد. نمونهٔ خروجی برای دو مجموعهٔ فرضی:

ipset_count{set="blocked-ips"} 41
ipset_count{set="trusted-networks"} 23

این مقدار تعداد ورودی‌های مجموعه است، نه شمار بسته‌ها، حجم ترافیک یا لزوماً تعداد آدرس‌های IP. برای مثال، یک ورودی شبکه می‌تواند چندین آدرس را پوشش دهد. این اکسپورتر محتوای قواعد فایروال را تغییر نمی‌دهد و وظیفهٔ آن انتشار همین آمار است.

تنظیمات

برای اجرا به میزبان لینوکسی با پشتیبانی کرنل از ipset و مجموعه‌های از قبل ساخته‌شده نیاز دارید. برنامه برای خواندن اطلاعات از Netlink به قابلیت NET_ADMIN احتیاج دارد.

ابتدا مخزن و فایل تنظیمات را آماده کنید:

git clone https://github.com/hatamiarash7/ipset-exporter.git
cd ipset-exporter
cp config.yml.example config.yml

محتوای config.yml را مطابق نیاز خود تنظیم کنید. در این مثال، نام‌ها فرضی هستند و باید با نام مجموعه‌های واقعی میزبان جایگزین شوند:

app:
  host: 127.0.0.1
  port: 4613
  log_level: info

ipset:
  update_interval: 15
  names:
    - blocked-ips
    - trusted-networks

گزینهٔ update_interval فاصلهٔ به‌روزرسانی اطلاعات بر حسب ثانیه است؛ در این نمونه هر ۱۵ ثانیه داده‌ها خوانده می‌شوند. برای پایش همهٔ مجموعه‌ها، مقدار names را به این شکل تغییر دهید:

names:
  - all

این بخش همچنان باید زیر ipset قرار بگیرد. وجود all در فهرست، انتخاب همهٔ مجموعه‌ها را فعال می‌کند.

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

مسیر پیش‌فرض فایل تنظیمات config.yml در دایرکتوری جاری است. با متغیر محیطی CONFIG_FILE یا گزینهٔ -config می‌توانید مسیر دیگری بدهید؛ گزینهٔ خط فرمان بر متغیر محیطی اولویت دارد.

نصب و اجرا

اجرای مستقل

برای ساخت نسخهٔ فعلی شاخهٔ اصلی، طبق go.mod به Go نسخهٔ ۱٫۲۶ یا جدیدتر نیاز دارید. Git، Make و ابزار setcap نیز باید روی سیستم موجود باشند. پس از آماده‌سازی تنظیمات، در دایرکتوری مخزن اجرا کنید:

make
sudo setcap cap_net_admin+ep ./bin/ipset-exporter
./bin/ipset-exporter -config ./config.yml

دستور setcap قابلیت لازم را به فایل اجرایی می‌دهد؛ پس از بازسازی یا جایگزینی باینری، ممکن است لازم باشد آن را دوباره اجرا کنید.

اجرای Docker

روش Docker از ایمیج معرفی‌شده در راهنمای پروژه استفاده می‌کند. از همان دایرکتوری که فایل config.yml را ساخته‌اید، اجرا کنید:

docker run -d \
  --name ipset-exporter \
  --network host \
  --cap-add=NET_ADMIN \
  -v "$(pwd)/config.yml:/app/configs/config.yml:ro" \
  -e CONFIG_FILE=/app/configs/config.yml \
  hatamiarash7/ipset-exporter:latest

روی میزبان لینوکسی، گزینهٔ --network host باعث می‌شود کانتینر مجموعه‌های فضای نام شبکهٔ میزبان را ببیند. قابلیت NET_ADMIN نیز برای خواندن آن‌ها لازم است. در این حالت نگاشت پورت با -p کاربردی ندارد و آدرس گوش‌دادن سرویس را همان app.host تعیین می‌کند.

این قابلیت دسترسی مدیریتی شبکه می‌دهد؛ بنابراین ایمیج و باینری باید مورداعتماد باشند. سرور متریک در پیاده‌سازی فعلی HTTP ساده و بدون احراز هویت است. اگر Prometheus روی میزبان دیگری قرار دارد، آدرس گوش‌دادن و دسترسی فایروال را متناسب با شبکهٔ مانیتورینگ تنظیم کنید.

اتصال به Prometheus

با تنظیمات بالا، از روی همان میزبان خروجی را بررسی کنید:

curl --fail http://127.0.0.1:4613/metrics

اگر Prometheus نیز مستقیماً روی همین میزبان اجرا می‌شود، این Job را به تنظیمات آن اضافه کنید:

scrape_configs:
  - job_name: ipset
    scrape_interval: 15s
    static_configs:
      - targets: ["127.0.0.1:4613"]

اگر Prometheus داخل کانتینر جداگانه‌ای اجرا می‌شود، 127.0.0.1 به همان کانتینر اشاره می‌کند؛ باید از آدرس قابل‌دسترسی میزبان و تنظیم شبکهٔ مناسب استفاده کنید. فاصلهٔ Scrape و update_interval مستقل‌اند؛ درخواست‌های بیشتر، خواندن اطلاعات از کرنل را سریع‌تر نمی‌کنند.

برای نمایش تعداد اعضای یک مجموعه در Prometheus یا پنل Grafana، این عبارت کافی است:

ipset_count{set="blocked-ips"}

چون این متریک Gauge است، برای مشاهدهٔ تعداد اعضا از مقدار مستقیم آن استفاده کنید، نه rate که معمولاً برای نرخ افزایش Counterها به کار می‌رود.

نکات مهم در تفسیر متریک‌ها

در پیاده‌سازی جمع‌آوری متریک‌ها، فهرست همهٔ مجموعه‌ها از Netlink دریافت می‌شود و سپس نام‌های انتخاب‌شده برای انتشار فیلتر می‌شوند. بنابراین محدودکردن names به معنی خواندن فقط همان مجموعه‌ها از کرنل نیست.

همچنین چند نکته برای ساخت داشبورد و هشدار اهمیت دارد:

  • مجموعهٔ خالی با مجموعهٔ ناموجود فرق دارد. مجموعهٔ موجود و خالی مقدار صفر می‌گیرد؛ نامی که وجود ندارد، صرفاً به دلیل حضور در تنظیمات متریک صفر تولید نمی‌کند.
  • حذف مجموعه، سری قبلی را پاک نمی‌کند. اگر مجموعه‌ای قبلاً دیده شده و بعد حذف شود، مقدار آخر آن می‌تواند تا راه‌اندازی مجدد برنامه در خروجی باقی بماند.
  • خطای خواندن، مقدار قبلی را نگه می‌دارد. خطای Netlink در لاگ ثبت می‌شود، اما متریک اختصاصی برای موفقیت جمع‌آوری یا زمان آخرین به‌روزرسانی وجود ندارد. مقدار up در Prometheus تنها موفقیت Scrape را نشان می‌دهد و تازگی اطلاعات ipset را تضمین نمی‌کند.

این پروژه برای افزودن شمار اعضای مجموعه‌های ipset به مانیتورینگ موجود مناسب است. کد آن با مجوز MIT منتشر شده و جزئیات اجرا در مستندات مخزن در دسترس است.