مستندات

DCManage چطور اندازه می‌گیرد، تصمیم می‌گیرد و امن می‌ماند، چطور نصبش کنید و چرا هر تصمیم طراحی همین‌طور گرفته شده است. به ترتیب بخوانید یا مستقیم سراغ بخشی بروید که لازم دارید.

نمای کلی

این چیست، چه شکلی دارد، و عمداً چه کاری نمی‌کند.

این چیست

DCManage یک پلتفرم مدیریت دیتاسنتر و شبکه است: دارایی‌ها (دیتاسنترها، رک‌ها، سوییچ‌ها، پورت‌ها، سرورها و سرویس‌هایی که روی آن‌ها اجرا می‌شوند) را نگه می‌دارد، ترافیک را بر اساس آن‌ها اندازه می‌گیرد و ثبت می‌کند چه کسی چه چیزی را تغییر داده است.

یک برنامهٔ Laravel با پایگاه دادهٔ PostgreSQL است. روی ماشینی در اختیار خودتان و روی شبکهٔ خودتان نصب می‌شود و تا خودتان تنظیم نکنید، به هیچ‌جای اینترنت عمومی وصل نمی‌شود.

شکل آن

سه فرایند، عمداً جدا از هم:

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

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

چه کاری نمی‌کند

فاکتور صادر نمی‌کند. اندازه می‌گیرد که مشتری چه مصرف کرده و بر چه مبنایی فاکتور می‌شود؛ سیستم صورت‌حساب همان می‌ماند که دارید.

به عاملی روی ماشین مشتری نیاز ندارد. همه‌چیز از تجهیزات شبکه خوانده می‌شود.

تا وقتی اعمال محدودیت را روشن نکنید، روی مشتری هیچ اقدامی نمی‌کند و با همین حالتِ خاموش تحویل می‌شود.

نصب

چه می‌خواهد، با چه دو هویتی اجرا می‌شود، و نسخهٔ جدید چطور اعمال می‌شود.

پیش‌نیازها

  • لینوکس، PHP نسخهٔ 8.3 یا بالاتر با افزونهٔ SNMP
  • PostgreSQL نسخهٔ 16 یا بالاتر؛ شمای پایگاه داده از پارتیشن‌بندی اعلانی و سلب دسترسی استفاده می‌کند که به پایگاه دادهٔ دیگری قابل انتقال نیست و قرار هم نیست باشد
  • دسترسی شبکه به تجهیزاتی که خوانده می‌شوند، مستقیم یا از طریق پروکسی

دو هویت

برنامه با دو حساب کاربری با دسترسی متفاوت اجرا می‌شود و اصل ماجرا همین تفاوت است.

  • www-data درخواست‌های HTTP را پاسخ می‌دهد و نمی‌تواند کلید اصلی را بخواند.
  • حساب کارگر، زمان‌بند و صف را اجرا می‌کند و می‌تواند.

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

صفحه‌ای که می‌گوید نمی‌تواند اعتبارنامهٔ ذخیره‌شده را باز کند خراب نیست؛ فراخوانی است که از مسیر صف نگذشته است.

اعمال نسخهٔ جدید

فایل‌ها با سرور همگام می‌شوند و اسکریپت اعمال (apply) بقیهٔ کار را انجام می‌دهد: مالکیت فایل‌ها را بازمی‌گرداند، مهاجرت‌ها را اجرا می‌کند، کش‌ها را پاک می‌کند، فرایند وب و کارگر را دوباره راه‌اندازی می‌کند، سپس همهٔ شرط‌های ثابت را بررسی می‌کند و اگر یکی برقرار نباشد با کد غیرصفر خارج می‌شود.

راه‌اندازی دوبارهٔ کارگر اختیاری نیست. کارگر مدت طولانی اجرا می‌ماند و کلاس‌هایی را که بارگذاری کرده نگه می‌دارد، پس استقراری که آن را در حال اجرا رها کند، همچنان کد نسخهٔ قبلی را اجرا می‌کند.

ترافیک چطور اندازه گرفته می‌شود

چه چیزی خوانده می‌شود، وقتی خواندنی از دست برود چه ثبت می‌شود و یک رقم چطور به ردیف فاکتور تبدیل می‌شود.

جمع‌آوری

واحد کار، دستگاه است نه پورت. جمع‌آور یک درخواست را از روی اندیس‌های اینترفیسی که از قبل می‌شناسد می‌سازد، به‌جای پیمودن کل جدول اینترفیس‌ها؛ روی شاسی‌ای با ۳۴۹ اینترفیس، این یعنی تفاوت میان دو ثانیه و یک‌هفتم ثانیه.

هرجا دستگاه شمارندهٔ ۶۴ بیتی داشته باشد، از همان استفاده می‌شود. شمارنده‌ای که دور بزند یا صفر شود تشخیص داده و همان‌طور ثبت می‌شود، نه اینکه جهش کاذب بسازد.

شکاف و کیفیت

هر نمونه کیفیتی دارد: قابل‌استفاده، پوشانندهٔ شکاف، پس از صفر شدن، یا مشکوک. بازه‌ای که کسی ندیده «هیچ» گزارش می‌شود، نه صفر، و پوشش نشان می‌دهد چه چیزی واقعاً دیده شده، نه چه چیزی استنتاج شده.

این وقتی اهمیت پیدا می‌کند که کسی به صورت‌حساب اعتراض کند. رقمی که نتواند بگوید چه بخشی از بازه‌اش را واقعاً دیده، مدرک نیست.

مبنای صورت‌حساب

یک سرویس بر اساس دانلود، آپلود یا هر دو فاکتور می‌شود. این تنظیم از خود سرویس خوانده می‌شود و اگر نباشد، از سرور و بعد از دیتاسنتر، و صدک روی همان جهت محاسبه می‌شود.

در نظر گرفتن جهتِ بزرگ‌تر، میان‌بُری رایج است و برای هرکس که ترانزیت می‌فروشد اشتباه است: مشتری را بابت ترافیکی بدهکار می‌کند که هرگز برایش فاکتور نشده است.

مانیتورینگ بیرونی

اجرای سیستم موجود در کنار این یکی، و اینکه چرا خودِ مقایسه اصل ماجراست.

چرا هر دو

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

وقتی هم‌خوان باشند، مدرک دارید. وقتی نباشند، پرسشی دارید که ارزش دارد پیش از رسیدن به مشتری پاسخ داده شود.

افزودن منبع

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

تطبیق عمداً سخت‌گیرانه است. سنسوری که تطبیق پیدا نکند دست‌نخورده می‌ماند و شمرده می‌شود، چون ستون خالی می‌گوید «نمی‌دانیم» و ستون اشتباه با اطمینان دربارهٔ مشتری اشتباه حرف می‌زند.

وقتی پاسخ نمی‌دهد

پس از خطاهای پیاپی اتصال، پلتفرم دیگر نمی‌پرسد. بعد هم منتظر تمام شدن یک تایمر نمی‌ماند: یک سوکت ساده باز می‌کند (بدون رمزگذاری، بدون اعتبارنامه، بدون API) و فقط اگر پاسخ آمد، درخواست واقعی را می‌فرستد. در برابر هاستی که مسیری به آن نیست، این کار حدود یک میلی‌ثانیه طول می‌کشد.

خطایی که خطای اتصال نباشد در این شمارش حساب نمی‌شود. سیستمی که پاسخ می‌دهد «مجاز نیستید» در دسترس است و مشکل اعتبارنامه دارد، و پنهان کردن آن پشت یک خطای پایان مهلت، کسی را سراغ مشکل اشتباه می‌فرستد.

پروکسی‌ها

رسیدن به بازه‌ای که پلتفرم مسیری به آن ندارد، و اینکه پروکسی چه چیزی را حمل نمی‌کند.

کِی لازم می‌شود

کنترلرهای مدیریت معمولاً در بازهٔ خصوصی‌ای هستند که سرور مدیریت مسیری به آن ندارد. هیچ اعتبارنامه‌ای این را حل نمی‌کند؛ آنچه کم است، مسیر است.

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

انواع

  • SOCKS5: پاسخ معمول، با اعتبارنامهٔ اختیاری و تبدیل نام به آدرس در سمت مقابل.
  • SOCKS4: برای تجهیزات قدیمی‌تر؛ وقتی به‌جای آدرس، نام مقصد داده شود، خودکار از SOCKS4a استفاده می‌شود.
  • HTTP CONNECT: تونل زدن از طریق یک پروکسی وب.
  • تونل کرنل (GRE یا WireGuard): مسیری در کرنل تا هاست واسط. بازه‌های آن رکورد به مسیر تبدیل می‌شوند. SNMP و ICMP و HTTPS همه از آن می‌روند. وقتی تونل قطع باشد، SOCKS مسیر جایگزین است.

برای SOCKS معمولاً لازم است نام‌ها در خود پروکسی به آدرس تبدیل شوند: نامی که فقط در بازهٔ خصوصی وجود دارد، از پلتفرم قابل یافتن نیست.

چه چیزی را حمل نمی‌کند

SNMP از SOCKS یا HTTP CONNECT عبور نمی‌کند. روی UDP و از طریق افزونه‌ای از PHP کار می‌کند که سوکتی در اختیار نمی‌گذارد، پس چیزی نیست که بشود پروکسی جریانی زیرش گذاشت.

تونل کرنل یک مسیر است، نه پروکسی جریانی، پس SNMP و ICMP و HTTPS همه از آن می‌روند. SOCKS را هم نگه دارید: وقتی تونل قطع است، HTTPS همچنان مسیر دارد ولی SNMP تا برگشتن تونل مسیری ندارد.

راه‌اندازی

هر سرور SOCKS5 کار می‌کند. این راهنما از Dante استفاده می‌کند، چون احراز هویت دارد و مهم‌تر از آن، می‌تواند مقصد را رد کند؛ همین است که سوراخی در مرز شبکهٔ شما را به دری قفل‌دار تبدیل می‌کند.

آن را روی ماشینی نصب کنید که همین حالا به بازهٔ مدیریت دسترسی دارد: معمولاً یک هاست واسط یا سرور مانیتورینگ، نه خود پلتفرم. اگر پلتفرم به آن بازه دسترسی داشت، به پروکسی نیازی نبود.

۱. نصب و ساختن یک حساب برای پلتفرم. این حساب نه شل لازم دارد نه پوشهٔ خانگی؛ فقط یک نام و یک رمز است.

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 را با آدرس خود پلتفرم جایگزین کنید. بلوک‌های client تعیین می‌کنند که فقط پلتفرم بتواند با این پروکسی ارتباط بگیرد. برای هر بازهٔ مقصد یک قاعدهٔ socks pass بنویسید: بلوک را کپی کنید و فقط CIDR و پورت را عوض کنید. یک قاعده برای 0.0.0.0/0 یعنی پروکسی باز. قاعدهٔ آخر هر مقصد دیگری را رد و در لاگ ثبت می‌کند.

logoutput: /var/log/sockd.log
internal: 0.0.0.0 port = 1080
external: eth1

# Username and password, checked against system accounts.
socksmethod: username
user.privileged: root
user.unprivileged: nobody

# Who may talk to this proxy at all: the platform, and nothing else.
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
}

# Where it may go once it has. One rule per destination range: copy the
# block, change the CIDR and the port, leave the rest. A single rule to
# 0.0.0.0/0 is an open proxy.
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
}

# Everything else, refused and written down.
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

خط آخر همان آزمون است. اگر فایل پس از راه‌اندازی دوباره خالی بود، یعنی لاگ هرگز باز نشده است.

روی اوبونتو، تا وقتی خط file:///cdrom در /etc/apt/sources.list باشد، ممکن است apt اصلاً چیزی نصب نکند. آن خط را غیرفعال کنید.

پورت 1080 نباید از جایی جز پلتفرم در دسترس باشد. قاعدهٔ client pass نیمی از کار است که Dante انجام می‌دهد؛ فایروال هاست روی پورت 1080 نیمهٔ دیگر. هر دو لازم‌اند. دو قاعدهٔ block هم تزئینی نیستند. وقتی هیچ قاعده‌ای تطبیق نکند، Dante خودش رد می‌کند، ولی نوشتن قاعدهٔ رد باعث می‌شود رد در لاگ ثبت شود؛ پروکسی‌ای که بی‌صدا رد می‌کند، یک بعدازظهر شما را به عیب‌یابی از سمت اشتباه می‌کشاند.

اعلام بازه‌ها، در دو جا

همان بازه‌ها در دو جا نوشته می‌شوند و این کار عمدی است.

در خود سرور پروکسی، به شکل قواعد socks pass بالا. مرز واقعی همین است: برنامهٔ دیگری روی ماشین دیگری آن را اعمال می‌کند و حتی اگر این پلتفرم کاملاً نفوذ شود، سر جایش می‌ماند. پورت‌ها هم همین‌جا تعیین می‌شوند؛ HTTPS به بازهٔ iLO با SSH به بازهٔ هاست واسط یکی نیست.

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

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

یک پیامد که خوب است بدانید: پروکسی‌ای که بازهٔ اعلام‌شده دارد، نام را هم مثل آدرسِ بیرون از بازه رد می‌کند. نام در سمت مقابل به آدرس تبدیل می‌شود، پس از اینجا نمی‌توان فهمید به کجا می‌رسد؛ و دانستن مقصد درخواست، تمام هدف این بازه‌هاست.

آزمودن آن

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

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

# Should answer: a controller on the declared range.
curl -sk --socks5-hostname dcmanage-proxy:PASSWORD@proxy.example:1080 \
     https://172.16.30.119/redfish/v1/Systems/1 | head

# Should be refused by the proxy, not by the platform.
curl -sk --socks5-hostname dcmanage-proxy:PASSWORD@proxy.example:1080 \
     https://example.com/

اگر اولی پاسخ گرفت و دومی نه، قواعد درست‌اند. اگر هر دو پاسخ گرفتند، یا قاعدهٔ socks block وجود ندارد یا یکی از قاعده‌های socks pass بازتر از چیزی است که می‌خواستید.

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

دسترسی و حسابرسی

چه کسی چه اجازه‌ای دارد، و سابقهٔ آنچه کرده.

نقش‌ها و استثناها

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

نقش یک مجموعهٔ نام‌دار است. استثناهای فردی روی خود مدیر و علاوه بر نقش‌هایش اعمال می‌شوند و سلب همیشه بر نقشی که همان مجوز را می‌دهد غلبه می‌کند.

لاگ حسابرسی

هر اقدامی که چیزی را تغییر داده و هر مورد ردشده. این ثبت‌ها را هیچ‌کس، حتی مدیر کل، نمی‌تواند ویرایش یا حذف کند: دسترسی UPDATE و DELETE در سطح پایگاه داده سلب شده است، نه اینکه فقط در کد نباشد.

مقادیری که ممکن است اطلاعات محرمانه داشته باشند، پیش از ذخیره پوشانده می‌شوند. لاگ حسابرسی‌ای که رمز سوییچ را لو بدهد، انباری از اعتبارنامه‌هاست با امکان جست‌وجو.

از کجا می‌توان به آن دسترسی داشت

دسترسی به پنل را می‌توان به فهرستی از آدرس‌های مبدأ محدود کرد و هر تلاش ردشده مثل هر اقدام دیگری ثبت می‌شود. این فهرست پیش از احراز هویت اعمال می‌شود، پس آدرسی که در آن نیست اصلاً به فرم ورود نمی‌رسد.

امنیت

اعتبارنامه‌ها چطور ذخیره می‌شوند، چرا لایهٔ وب نمی‌تواند بخواندشان، و چه چیزی خاموش می‌ماند.

اعتبارنامه‌های ذخیره‌شده

اعتبارنامه‌های دستگاه با XChaCha20-Poly1305 و با کلید اصلی‌ای که بیرون از پوشهٔ برنامه نگهداری می‌شود رمزگذاری می‌شوند. جدول، ردیف و فیلد هر مقدار هم در رمزگذاری آن به کار می‌روند، پس متن رمزشده‌ای که از یک ردیف به ردیف دیگر کپی شود رمزگشایی نمی‌شود.

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

جداسازی بر اساس هویت

لایهٔ وب نمی‌تواند کلید اصلی را بخواند. این را مالکیت فایل تضمین می‌کند و در هر استقرار بررسی می‌شود، و به همین دلیل دستگاهی کند یا مهاجم نمی‌تواند همهٔ فرایندهای وب را درگیر کند: این فرایندها اصلاً راهی برای باز کردن اتصال به دستگاه ندارند.

اعمال محدودیت خاموش می‌ماند

پلتفرم در حالت مشاهده تحویل می‌شود: حساب می‌کند چه تصمیمی می‌گرفت، آن را ثبت می‌کند و چیزی را تغییر نمی‌دهد. فعال کردن آن به مدیر کل و یک عبارت تأیید تایپ‌شده نیاز دارد.

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