نمای کلی
این چیست، چه شکلی دارد، و عمداً چه کاری نمیکند.
این چیست
دیسیمنیج یک پلتفرم مدیریت دیتاسنتر و شبکه است: دارایی را نگه میدارد — سایتها، رکها، سوییچها، پورتها، سرورها و سرویسهایی که رویشان اجرا میشوند — ترافیک را در برابرش اندازه میگیرد، و ثبت میکند چه کسی چه چیزی را تغییر داده.
یک برنامهٔ Laravel است با پشتوانهٔ PostgreSQL. روی ماشینی نصب میشود که در اختیار شماست، روی شبکهٔ خودتان، و تا وقتی خودتان تنظیم نکنید به هیچجای اینترنت عمومی دست نمیزند.
شکل آن
سه پروسه، عمداً جدا:
- لایهٔ وب رابط را سرو میکند. نمیتواند اعتبارنامهٔ ذخیرهشدهٔ دستگاه را باز کند، یعنی هیچ صفحهای را نمیشود وادار کرد منتظر دستگاهی بماند که جواب نمیدهد.
- زمانبند جمعآوری و نگهداری را طبق جدول اجرا میکند، هر کار در پروسهٔ خودش با نگهبان همپوشانی خودش.
- ورکر کار دستگاهی را انجام میدهد. هر چیزی که به سوییچ دست بزند به آن سپرده و نتیجهاش گزارش میشود.
این جداسازی معماری برای خودش نیست. هاست مانیتورینگی که یک بار کند شد، همهٔ ورکرهای وب یک پنل را نگه داشت تا کل آن از جوابدادن ایستاد؛ این چیدمان آن را ناممکن میکند، نه بعید.
چه کاری نمیکند
فاکتور صادر نمیکند. اندازه میگیرد که مشتری چه مصرف کرده و بر چه مبنایی فاکتور میشود؛ سیستم صورتحساب همان میماند که دارید.
به عامل روی ماشین مشتری نیاز ندارد. همهچیز از تجهیزات شبکه خوانده میشود.
تا وقتی اعمال محدودیت را روشن نکنید روی مشتری کاری نمیکند، و با همان خاموش تحویل میشود.
نصب
چه میخواهد، با چه دو هویتی اجرا میشود، و نسخهٔ جدید چطور اعمال میشود.
پیشنیازها
- لینوکس، PHP نسخهٔ ۸.۳ یا بالاتر با افزونهٔ SNMP
- PostgreSQL نسخهٔ ۱۶ یا بالاتر — شمای پایگاه داده از پارتیشنبندی اعلانی و سلب دسترسی استفاده میکند که قابل انتقال نیست، و قرار هم نیست باشد
- دسترسی شبکه به تجهیزاتی که خوانده میشوند، مستقیم یا از راه پروکسی
دو هویت
برنامه با دو حساب با دسترسی متفاوت اجرا میشود، و همین تفاوت اصل ماجراست.
www-data که HTTP را سرو میکند و نمیتواند کلید اصلی را بخواند.- حساب ورکر که زمانبند و صف را اجرا میکند و میتواند.
کلید اصلی هر اعتبارنامهٔ ذخیرهشدهٔ دستگاه را باز میکند. چون لایهٔ وب نمیتواند بخواندش، صفحهای که به خطر افتاده نمیتواند رمز عبورِ سوییچ بیرون بدهد، و هیچ درخواستی را نمیشود وادار کرد سوکتی به دستگاه باز نگه دارد.
صفحهای که میگوید نمیتواند اعتبارنامهٔ ذخیرهشده را باز کند خراب نیست. فراخوانی است که از مسیر صف نگذشته.
اعمال نسخهٔ جدید
فایلها با سرور همگام میشوند و اسکریپت apply بقیه را انجام میدهد: مالکیت را برمیگرداند، مهاجرت میکند، کشها را پاک میکند، پروسهٔ وب و ورکر را ریاستارت میکند، بعد هر ثابت را بررسی میکند و اگر یکی خراب باشد با کد غیرصفر خارج میشود.
ریاستارت ورکر اختیاری نیست. عمر بلندی دارد و کلاسهایی را که بار کرده نگه میدارد، پس دیپلویی که آن را در حال اجرا رها کند، همچنان کد نسخهٔ قبلی را اجرا میکند.
ترافیک چطور اندازه گرفته میشود
چه چیزی خوانده میشود، وقتی خوانشی از دست برود چه ثبت میشود، و یک رقم چطور به سطر فاکتور تبدیل میشود.
جمعآوری
واحد کار، دستگاه است نه پورت. کالکتور یک درخواست را از روی شمارههای اینترفیسی که از قبل میشناسد میسازد، بهجای پیمودن کل جدول اینترفیس — روی شاسی با ۳۴۹ اینترفیس، این تفاوت دو ثانیه و یکهفتم ثانیه است.
شمارندهها هرجا دستگاه بدهد ۶۴ بیتیاند. شمارندهای که دور بزند یا صفر شود تشخیص داده و همانطور ثبت میشود، نه اینکه قله بسازد.
شکاف و کیفیت
هر نمونه کیفیتی با خود دارد: قابلاستفاده، پوشانندهٔ شکاف، پس از صفرشدن، یا مشکوک. بازهای که کسی ندیده هیچ گزارش میکند نه صفر، و پوشش توصیف میکند چه چیزی واقعاً دیده شده نه چه چیزی استنتاج شده.
این لحظهای اهمیت پیدا میکند که کسی به صورتحسابی اعتراض کند. رقمی که نتواند بگوید چه بخشی از بازهاش را واقعاً دیده، شاهد نیست.
مبنای صورتحساب
یک سرویس بر دانلود، بر آپلود، یا بر هر دو فاکتور میشود. این تنظیم از خود سرویس گرفته میشود و در نبودش به سرور و بعد سایت میرسد، و صدک روی همان جهت گرفته میشود.
گرفتن بزرگترِ دو جهت میانبُر رایجی است و برای هرکس که ترانزیت میفروشد غلط است: مشتری را بابت ترافیکی که هرگز برایش فاکتور نشده بدهکار میکند.
مانیتورینگ بیرونی
اجرای سیستم موجود در کنار این یکی، و اینکه چرا خودِ مقایسه اصل ماجراست.
چرا هر دو
یک سیستم اندازهگیری تازه از روز اول میخواهد که به آن برای فاکتور اعتماد شود. نباید بشود. ثبتکردن سیستمی که همین حالا دارید بهعنوان منبع، اجازه میدهد یک پورت دو بار خوانده و دو رقم در طول یک دورهٔ کامل مقایسه شوند.
وقتی موافق باشند، شاهد دارید. وقتی نباشند، پرسشی دارید که ارزش دارد پیش از رسیدن به مشتری پاسخ داده شود.
افزودن منبع
منبع یعنی یک نشانی، یک اعتبارنامه، و اینکه چطور ارائه شود. سنسورهایش محلی کش میشوند تا رابط هرگز وقتی کسی منتظر است چیزی از سیستم دور نپرسد، و سنسورهای ترافیک با تطبیق چیزی که هر دو سیستم بر آن توافق دارند به پورتها وصل میشوند.
تطبیق عمداً تنگ است. سنسور بیتطبیق دستنخورده میماند و شمرده میشود، چون ستون خالی میگوید «نمیدانیم» و ستون غلط چیزی مطمئن دربارهٔ مشتری اشتباه میگوید.
وقتی جواب نمیدهد
پس از خطاهای پیاپی اتصال، پلتفرم دیگر نمیپرسد. بعد هم منتظر تایمر نمیماند: یک سوکت لخت باز میکند — بدون رمزنگاری، بدون اعتبارنامه، بدون API — و فقط اگر آن جواب داد درخواست واقعی میفرستد. در برابر هاستی که مسیری ندارد، این حدود یک میلیثانیه هزینه دارد.
خطایی که خطای اتصال نباشد به این حساب نمیآید. سیستمی که «مجاز نیست» جواب میدهد در دسترس است و مشکل اعتبارنامه دارد، و پنهانکردن آن پشت یک timeout کسی را بهسراغ چیز اشتباه میفرستد.
پروکسیها
رسیدن به رنجی که پلتفرم مسیری به آن ندارد، و اینکه پروکسی چه چیزی را حمل نمیکند.
کِی لازم میشود
کنترلرهای مدیریت معمولاً روی رنج خصوصیای هستند که سرور مدیریت مسیری به آن ندارد. هیچ اعتبارنامهای این را درست نمیکند؛ چیزی که کم است مسیر است.
پروکسی یک بار ثبت میشود و تجهیزاتی که از آن مسیر گرفته میشوند نامش را میبرند. تجهیزی که هیچکدام را نام نبرد مستقیم وصل میشود، که کار همهٔ چیزهای روی زیرشبکهٔ خود پلتفرم است.
انواع
- SOCKS5 — پاسخ معمول، با اعتبارنامهٔ اختیاری و حل نام در سمت مقابل.
- SOCKS4 — برای تجهیزات قدیمیتر؛ وقتی بهجای نشانی یک نام گرفته میشود، خودکار SOCKS4a استفاده میشود.
- HTTP CONNECT — تونلزدن از دل یک پروکسی وب.
- GRE — تونل کرنل به جامپهاست. رنجهای آن رکورد مسیر میشوند. SNMP و ICMP و HTTPS همه از آن میروند. وقتی تونل پایین باشد SOCKS مسیر جایگزین است.
حل نام در خود پروکسی برای SOCKS معمولاً لازم است: نامی که فقط روی رنج خصوصی وجود دارد، نامی است که پلتفرم راهی برای یافتنش ندارد.
چه چیزی را حمل نمیکند
SNMP از SOCKS یا HTTP CONNECT عبور نمیکند. آن UDP است از دل افزونهای در PHP که هیچ سوکتی نمیدهد، پس چیزی نیست که پروکسی استریم زیرش گذاشته شود.
تونل GRE مسیر است، نه پروکسی استریم، پس SNMP و ICMP و HTTPS همه از آن میروند. SOCKS را هم نگه دارید: وقتی تونل پایین است HTTPS هنوز مسیر دارد و SNMP ندارد تا تونل برگردد.
راهاندازی
هر سرور SOCKS5 کار میکند. اینجا از Dante استفاده شده، چون هم احراز هویت دارد و هم — که مهمترش همین است — میتواند مقصد را رد کند؛ همین است که سوراخی در مرز شبکه را میکند دری که قفل دارد.
روی ماشینی بگذاریدش که همین حالا به رنج مدیریت میرسد: معمولاً یک jump host یا سرور مانیتورینگ، نه خود پلتفرم. اگر پلتفرم به آن رنج میرسید که پروکسی لازم نداشت.
۱. نصب، و ساختن یک حساب برای پلتفرم. این حساب نه شل لازم دارد نه خانه — یک نام است و یک رمز.
apt install dante-server
useradd --system --no-create-home --shell /usr/sbin/nologin dcmanage-proxy
passwd dcmanage-proxy
۲. نوشتن قواعد. این تمام /etc/danted.conf است. eth1 را با اینترفیسی که رو به رنج مدیریت دارد عوض کنید و 185.81.96.142 را با نشانی خود پلتفرم.
logoutput: /var/log/sockd.log
internal: 0.0.0.0 port = 1080
external: eth1
# نام کاربری و رمز، از روی حسابهای سیستم.
socksmethod: username
user.privileged: root
user.unprivileged: nobody
# چه کسی اصلاً حق حرف زدن با این پروکسی را دارد: فقط پلتفرم.
client pass {
from: 185.81.96.142/32 to: 0.0.0.0/0
log: connect disconnect error
}
client block {
from: 0.0.0.0/0 to: 0.0.0.0/0
log: connect error
}
# و بعدش کجا حق رفتن دارد. هر رنج مقصد یک قاعده — بلوک را کپی کنید،
# CIDR و پورت را عوض کنید، بقیه را نزنید. یک قاعده به 0.0.0.0/0 پروکسی باز است.
socks pass {
from: 185.81.96.142/32 to: 172.16.30.0/24 port = 443
command: connect
socksmethod: username
log: connect disconnect error
}
socks pass {
from: 185.81.96.142/32 to: 172.16.31.0/24 port = 443
command: connect
socksmethod: username
log: connect disconnect error
}
socks pass {
from: 185.81.96.142/32 to: 10.0.0.0/24 port = 22
command: connect
socksmethod: username
log: connect disconnect error
}
# باقی همه چیز، رد و ثبت.
socks block {
from: 0.0.0.0/0 to: 0.0.0.0/0
log: connect error
}
۳. راه انداختنش، و زنده ماندنش بعد از ریبوت.
systemctl enable --now danted
systemctl status danted
دو چیز در یونیتِ آماده گاز میگیرد و هر دو بیصدا هستند.
یونیت ReadOnlyDirectories=/var میگذارد، پس خط logoutput بالا فایلش را نمیتواند باز کند و دیمن اصلاً بدون لاگ کار میکند — یعنی قاعدههای block رد میکنند بیآنکه چیزی بنویسند، و ردی که دیده نمیشود ردی است که آن را ایراد شبکه خواهید خواند. ضمناً فقط منتظر network.target میماند، که پیش از گرفتن آدرس روی اینترفیس میرسد؛ اگر internal یک آدرس نام ببرد و نه 0.0.0.0، بوت سرد به bind نمیرسد و یونیت میمیرد و پروکسی تا وقتی کسی متوجه شود پایین است.
mkdir -p /etc/systemd/system/danted.service.d
cat > /etc/systemd/system/danted.service.d/override.conf <<'EOF'
[Unit]
After=network-online.target
Wants=network-online.target
[Service]
ReadWritePaths=/var/log/sockd.log
Restart=on-failure
RestartSec=5s
EOF
touch /var/log/sockd.log
systemctl daemon-reload && systemctl restart danted
tail /var/log/sockd.log
خط آخر خودِ تست است. فایل خالی بعد از restart یعنی لاگ هیچوقت باز نشده.
روی اوبونتو ممکن است تا وقتی خط file:///cdrom در /etc/apt/sources.list مانده باشد، apt هیچ چیزی نصب نکند. کامنتش کنید.
پورت 1080 نباید از جایی جز پلتفرم دیده شود. قاعدهٔ client pass نیمهٔ Dante است؛ فایروال هاست روی 1080 نیمهٔ دیگر. هر دو. آن دو قاعدهٔ block تزئینی نیستند. وقتی هیچ قاعدهای تطبیق نکند Dante خودش رد میکند، ولی نوشتن رد باعث میشود در لاگ بیفتد — و پروکسیای که بیصدا رد میکند، پروکسیای است که یک بعدازظهر را از سمت اشتباه دنبالش میگردید.
اعلام رنجها، دو جا
همان رنجها در دو جا نوشته میشوند، و این عمدی است.
در خود پروکسی سرور، به شکل قواعد socks pass بالا. مرز واقعی همین است: برنامهای دیگر روی ماشینی دیگر آن را اعمال میکند، و حتی اگر این پلتفرم کاملاً از دست برود سر جایش میماند. پورت مال همینجاست — HTTPS به رنج iLO همان SSH به رنج پرش نیست.
در این پلتفرم، روی رکورد خود پروکسی، هر CIDR در یک خط، مطابق همان قواعد. این یکی امنیت نیست — چیزی است که نشانی اشتباه تایپشده را پیش از باز شدن اتصال میگیرد، با پیامی که نام پروکسی و رنجهای اعلامشدهاش را میگوید، به جای یک timeout که بیست دقیقه وقت میگیرد.
روی فهرست پروکسیها همان فایل کنار رکوردها چاپ میشود تا دو نسخه را بدون ترک صفحه بشود مقایسه کرد. پروکسیای که اینجا هیچ رنجی برایش اعلام نشده به هر چیزی که به سمتش نشانه بروید میرسد، و فهرست پروکسیها میگوید کدامها اینطورند. هر پروکسیای که پیش از این قابلیت ساخته شده در همین حالت است؛ خطا نیست، ولی ارزش درست کردن دارد.
یک نکته: پروکسیای که رنج اعلامشده دارد، نام را هم مثل نشانی بیرون از رنج رد میکند. نام در آن سر resolve میشود، پس از اینجا نمیشود فهمید به چه تبدیل میشود — و دانستن اینکه درخواست کجا مینشیند تمام هدف این رنجهاست.
آزمودنش
پیش از افزودن اینجا، پروکسی را از روی خود ماشین پلتفرم و با همان حسابی که قرار است استفاده کند تست کنید. پروکسیای که از لپتاپ شما کار میکند و از پلتفرم نه، رایجترین راه از دست دادن یک ساعت است.
# باید جواب بدهد: یک کنترلر روی رنج اعلامشده.
curl -sk --socks5-hostname dcmanage-proxy:PASSWORD@proxy.example:1080 \
https://172.16.30.119/redfish/v1/Systems/1 | head
# باید رد شود — توسط پروکسی، نه توسط پلتفرم.
curl -sk --socks5-hostname dcmanage-proxy:PASSWORD@proxy.example:1080 \
https://example.com/
اگر اولی جواب داد و دومی نه، قواعد درستاند. اگر هر دو جواب دادند، یا قاعدهٔ socks block نیست یا یکی از socks passها بازتر از آن است که میخواستید.
وقتی اینجا اضافه شد، فهرست پروکسیها دکمهٔ دسترسی دارد. فقط یک سوکت خالی به پروکسی باز میکند و بس — نمیتواند اعتبارنامه را تست کند، چون لایهٔ وب کلید اصلی را نمیخواند و رمز ذخیرهشده را باز نمیکند. این خاصیت طراحی است نه کمبود دکمه، و دقیقاً برای همین آن curl بالا ارزش دارد.
دسترسی و حسابرسی
چه کسی چه اجازهای دارد، و سابقهٔ آنچه کرده.
نقشها و استثناها
مجوزها در یک ثبت واحد اعلام میشوند که سه مصرفکننده را میراند: دروازهٔ احراز دسترسی، رابط کاربری، و ویرایشگر نقش. همین است که نمیگذارد از هم فاصله بگیرند — دکمهای که رندر شده همیشه دکمهای است که فشرده میشود، چون دیدهشدن و مجوز یک کلید را میخوانند.
نقش یک مجموعهٔ نامدار است. استثناهای فردی روی خودِ مدیر و بالای نقشهایش مینشینند، و سلب همیشه بر نقشی که همان را میدهد غلبه میکند.
گزارش حسابرسی
هر اقدامی که چیزی را تغییر داده، و هر مورد ردشده. این ثبتها را هیچکس نمیتواند ویرایش یا حذف کند، حتی مدیر کل: دسترسی UPDATE و DELETE در سطح پایگاه داده سلب شده، نه اینکه فقط در کد نباشد.
مقادیری که ممکن است رازی حمل کنند پیش از ذخیره پوشانده میشوند. گزارش حسابرسیای که رمز عبورِ سوییچ را لو بدهد، انباری از اعتبارنامه است با یک رابط جستجو.
از کجا میشود به آن رسید
پنل را میشود به فهرستی از نشانیهای مبدأ محدود کرد، و تلاش ردشده مثل هر اقدام دیگری ثبت میشود. آن فهرست پیش از احراز هویت اعمال میشود، پس نشانیای که در آن نیست اصلاً به فرم ورود نمیرسد.
امنیت
اعتبارنامهها چطور ذخیره میشوند، چرا لایهٔ وب نمیتواند بخواندشان، و چه چیزی خاموش میماند.
اعتبارنامههای ذخیرهشده
اعتبارنامههای دستگاه با XChaCha20-Poly1305 و زیر یک کلید اصلی که بیرون از پوشهٔ برنامه نگهداری میشود مهروموم میشوند. جدول، ردیف و فیلد بخشی از چیزی هستند که هر مقدار به آن مقید میشود، پس متن رمزی که از یک ردیف به ردیف دیگر کپی شود باز نمیشود.
اعتبارنامه پس از ذخیره دیگر نمایش داده نمیشود. رابط گزارش میکند که یکی نگهداری میشود، که جملهای متفاوت از نشاندادنش است.
جدا بر پایهٔ هویت
لایهٔ وب نمیتواند کلید اصلی را بخواند. این با مالکیت فایل اعمال و در هر دیپلوی بررسی میشود، و همین دلیل آن است که دستگاهی کند یا خصمانه نمیتواند استخر پروسههای وب را تمام کند: آن پروسهها راهی برای بازکردن اتصال به یک دستگاه ندارند.
اعمال محدودیت خاموش میماند
پلتفرم در حالت مشاهده تحویل میشود. حساب میکند که چه تصمیمی میگرفت و مینویسدش، و چیزی را تغییر نمیدهد. فعالکردنش مدیر کل و یک عبارت تأیید تایپشده میخواهد.
اینکه دو سامانه از روی دو تصویر متفاوت روی یک دستگاه عمل کنند، همان راهی است که مشتری پولی را از دسترس خارج میکند، پس پلتفرم تا وقتی خلافش گفته نشود فرض میکند دومی است.