📘 سیستم Update Shecan IP

کامپوننت سبک مبتنی بر systemd برای همگام‌سازی خودکار IP عمومی با سرویس DDNS شِکن

📌 ۱. معرفی

سیستم Update Shecan IP یک سرویس سبک مبتنی بر systemd است که وظیفه دارد:

این سیستم برای محیط‌هایی طراحی شده که:

مفاهیم پایه به زبان کاملاً ساده (اگر با سرور و شبکه آشنا نیستید، بخوانید)

دنیای لینوکس و سرور پر از اصطلاحات سخت است. بیایید این مفاهیم را با مثال‌های ساده دنیای واقعی بررسی کنیم تا متوجه شوید این سیستم دقیقاً چه مشکلی را حل می‌کند:

آی‌پی عمومی (Public IP) چیست؟

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

سرویس DDNS چیست؟

سرویس دی‌ان‌اس پویا مانند یک دفترچه تلفن هوشمند است. به جای حفظ کردن کدهای سخت (آی‌پی)، یک نام ثابت (مانند my-server.shecan.ir) دارید. هر بار آدرس خانه شما تغییر کرد، این دفترچه تلفن باید بلافاصله از آدرس جدید مطلع شود تا بقیه شما را گم نکنند.

سیستم‌دی (systemd) چیست؟

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

سرویس (Service) چیست؟

سرویس مانند یک کارگر متخصص است که یک کار خاص را بلد است. سرویس ما در این پروژه، کارش این است که بیدار شود، رمز عبور را بخواند، آدرس جدید را با ابزار curl به شکن ارسال کند و وقتی کارش تمام شد دوباره بخوابد (به این حالت تک‌مرحله‌ای یا oneshot می‌گویند).

تایمر (Timer) چیست؟

تایمر دقیقاً مثل یک ساعت زنگ‌دار (آلارم) عمل می‌کند. به جای اینکه کارگر ما (سرویس) مدام بیدار بماند و انرژی (پردازنده و رم) مصرف کند، او را می‌خوابانیم و ساعت زنگ‌دار را کوک می‌کنیم تا هر ۵ دقیقه یک‌بار او را بیدار کند تا کارش را انجام دهد.

اسکریپت شل (Shell Script) چیست؟

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

🧱 ۲. معماری سیستم

🔷 دیاگرام معماری

graph TD A[systemd Timer] --> B[systemd Service] B --> C[اسکریپت شل] C --> D[فایل متغیرهای محیطی] C --> E[درخواست curl] E --> F[API سرویس Shecan] B --> G[Sandbox امنیتی systemd] G --> C

🔷 جریان مفهومی

🧩 ۳. اجزای سیستم

۳.۱ فایل تنظیمات محیطی

مسیر: /etc/shecan-ipupdate.env

SHECAN_PASSWORD=your_password_here

امنیت دسترسی:

chmod 600 /etc/shecan-ipupdate.env
chown root:root /etc/shecan-ipupdate.env
💡 کلاس درس لینوکس: چرا فایل با مجوز ۶۰۰ و مالکیت root تعریف می‌شود؟ (کلیک کنید)

در لینوکس، مدیریت دسترسی به فایل‌ها بر اساس یک مدل امنیتی بسیار مستحکم به نام DACL (Discretionary Access Control) بنا شده است. هر فایل دارای سه سطح دسترسی به ازای سه نهاد مختلف است:

  1. Owner (مالک): کاربری که فایل را ساخته یا صاحب فعلی آن است.
  2. Group (گروه): مجموعه‌ای از کاربران که دسترسی مشترک گروهی دارند.
  3. Others (دیگران): هر کاربر متفرقه‌ی دیگری در سیستم‌عامل.

وقتی دستور chmod 600 را اجرا می‌کنید، این عدد در مبنای هشت (Octal) خوانده می‌شود:

  • عدد ۶ (مربوط به مالک): به صورت باینری برابر است با 110. بیت اول یعنی خواندن (r) فعال، بیت دوم نوشتن (w) فعال، و بیت سوم اجرا (x) غیرفعال است (۴ + ۲ = ۶).
  • عدد ۰ اول (مربوط به گروه): تمام بیت‌ها غیرفعال (---).
  • عدد ۰ دوم (مربوط به دیگران): تمام بیت‌ها غیرفعال (---).

چرا مالکیت root:root؟ دستور chown root:root فایل را به کاربر ممتاز سیستم (super-user) واگذار می‌کند. در نتیجه، حتی اگر یک مهاجم بتواند از سد وب‌سرور شما (مثلا Nginx با کاربر www-data) عبور کند و دسترسی شل بگیرد، به دلیل ساختار حفاظتی چندکاربره لینوکس، کرنل اجازه خواندن این فایل و سرقت رمز عبور را به او نخواهد داد؛ زیرا او عضو گروه یا مالک فایل نیست.

۳.۲ اسکریپت اجرا

مسیر: /usr/local/bin/shecan-ipupdate.sh

#!/usr/bin/env sh
set -eu

. /etc/shecan-ipupdate.env

exec curl -fsS "https://ddns.shecan.ir/update?password=$SHECAN_PASSWORD"
💡 کلاس درس لینوکس: پشت پرده فلگ‌های شل و جادوی سیستم هماهنگی پروسس‌ها با exec (کلیک کنید)

اسکریپت‌های شل سنتی فاقد مکانیزم‌های خطایابی خودکار هستند. این اسکریپت با رعایت استانداردهای پوزیکس (POSIX sh) نوشته شده و از فلگ‌های زیر استفاده می‌کند:

تحلیل خط‌به‌خط مهندسی اسکریپت:

  • set -e (Exit on Error): به طور پیش‌فرض، اگر یک دستور در اسکریپت شل با شکست مواجه شود، شل خط بعدی را اجرا می‌کند! با فعال کردن -e، شل بلافاصله پس از دریافت هر کد وضعیت (Exit Code) غیر صفر، به کار خود پایان می‌دهد و مانع از خرابی‌های زنجیره‌ای می‌شود.
  • set -u (Treat Unset Variables as Error): شل به طور پیش‌فرض متغیرهای تعریف نشده را خالی ("") در نظر می‌گیرد. فعال‌سازی -u مانع از این فاجعه می‌شود؛ به طور مثال اگر به اشتباه بنویسید $SHECAN_PASSWRD، اسکریپت متوقف می‌شود تا آدرس با رمز خالی به سرورهای شکن ارسال نشود.
  • نقطه (Sourcing) . /etc/...: این کار متغیرهای درون فایل کانفیگ را مستقیماً به محیط پردازش فعلی شل تزریق می‌کند، بدون اینکه پروسه فرزند جدیدی ساخته شود.
  • دستور exec: در ساختار پروسس‌های یونیکس، برای اجرای یک برنامه معمولاً سیستم‌عامل از ترکیب fork (تکثیر پروسه جاری) و exec (بارگذاری برنامه جدید در فرزند) استفاده می‌کند. با نوشتن مستقیم exec curl، ما از شبیه‌سازی بیهوده پروسس جلوگیری می‌کنیم. پروسه sh فعلی در حافظه رم مستقیماً با برنامه curl جایگزین می‌شود؛ در نتیجه شناسه پروسس (PID) تغییر نکرده و حافظه اختصاص یافته به مفسر شل فوراً آزاد می‌شود.

۳.۳ سرویس systemd

مسیر: /etc/systemd/system/shecan-ipupdate.service

[Unit]
Description=سرویس به‌روزرسانی IP در Shecan
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
User=root
Group=root
ExecStart=/usr/local/bin/shecan-ipupdate.sh

# سخت‌سازی امنیتی
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
RemoveIPC=yes
💡 کلاس درس لینوکس: ساختار درونی Units و لایه‌های عمیق سندباکس در لینوکس مدرن (کلیک کنید)

یونیت‌فایل‌های سیستم‌دی از یک ساختار فایل‌های پیکربندی شبیه به INI استفاده می‌کنند. بیایید معماری این بخش را از نظر آکادمیک بررسی کنیم:

بخش [Unit] - هماهنگی زنجیره نیازمندی‌ها:

  • Wants=network-online.target: یک نیازمندی ضعیف (Weak Dependency) ایجاد می‌کند. سیستم‌دی تلاش می‌کند همزمان با راه‌اندازی این سرویس، شبکه آنلاین را هم بالا بیاورد، اما اگر شبکه لغو شود، این سرویس لزوماً از کار نمی‌افتد.
  • After=network-online.target: ترتیب زمانی را مشخص می‌کند. این سرویس حتماً و قطعاً باید بعد از بالا آمدن کامل شبکه و پایداری آدرس‌های آی‌پی اجرا شود تا وب‌هوک به خطا نخورد.

بخش [Service] - نوع پردازش:

  • Type=oneshot: این مدل برای کارهایی است که رفتار طولانی‌مدت (دیمون) ندارند. کار تمام می‌شود و پروسه بسته می‌شود. سیستم‌دی تا زمانی که دستور ExecStart به طور کامل پایان نیابد، این یونیت را در وضعیت activating نگه می‌دارد؛ این موضوع برای خطایابی عالی است.

تشریح عمیق سندباکس‌های امنیتی (Security Sandboxing):

  • PrivateTmp=yes: یک دایرکتوری کاملاً مجازی و ایزوله برای پوشه‌های موقت سیستم (/tmp و /var/tmp) ایجاد می‌کند. پروسه ما فایل‌های موقت سیستم اصلی را نمی‌بیند و برعکس؛ این کار جلوی حملات خرابکاری فایل‌های اشتراکی موقت را می‌گیرد.
  • LockPersonality=yes: قفل کردن معماری سیستم‌عامل؛ مانع از این می‌شود که یک مهاجم از طریق فراخوانی سیستمی personality() بتواند حالت پردازنده را مثلاً از ۶۴ بیت به ۳۲ بیت تغییر دهد تا کدهای مخرب قدیمی خود را اجرا کند.
  • RestrictSUIDSGID=yes: هر نوع تلاش برای استفاده از بیت‌های امنیتی SUID (مانند تغییر موقت هویت به روت) را در فایل‌های درون پروسه عقیم می‌سازد.

۳.۴ تایمر systemd

مسیر: /etc/systemd/system/shecan-ipupdate.timer

[Unit]
Description=تایمر اجرای دوره‌ای آپدیت IP

[Timer]
OnBootSec=1min
OnUnitInactiveSec=5min
Persistent=true

[Install]
WantedBy=timers.target
💡 کلاس درس لینوکس: معماری رویدادمحور و زمان‌بندی دقیق با لایه‌های انباشت انرژی کرنل (کلیک کنید)

تایمرهای سیستم‌دی بسیار فراتر از کرون‌جاب‌های کلاسیک یونیکس عمل می‌کنند. آن‌ها مستقیم با زمان‌بند هسته لینوکس (Linux Kernel Scheduler) پیوند خورده‌اند تا تداخل پردازشی را به حداقل برسانند:

انواع مدل‌های زمان‌بندی:

  • تایمرهای مونوکلونیک (Monotonic Timers): به تایمرهایی گفته می‌شود که زمان را بر اساس یک مبدا پویا (مانند روشن شدن سیستم یا غیرفعال شدن یونیت) می‌سنجند. در کدهای بالا، دستور OnBootSec و OnUnitInactiveSec از این نوع هستند. این تایمرها به نوسانات ساعت سیستم (تغییر ساعت رسمی یا NTP) حساس نیستند و همیشه دقیق عمل می‌کنند.
  • تایمرهای بلادرنگ (Realtime/Calendar Timers): بر اساس ساعت واقعی و تاریخ تقویمی کار می‌کنند (مثلا شنبه‌ها ساعت ۱۲ شب). کرون‌جاب‌ها از این نوع هستند و بسیار در برابر تغییرات ساعت رسمی آسیب‌پذیرند.

مزیت بزرگ Persistent=true:

سیستم‌دی یک فایل در مسیر /var/lib/systemd/timers/ ایجاد کرده و آخرین زمان اجرای موفق را در آن هک می‌کند. اگر سرور شما به مدت ۱ ساعت به دلیل ارتقای سخت‌افزاری خاموش باشد، در زمان روشن شدن، سیستم‌دی می‌فهمد که اجرای تایمر عقب افتاده است و بلافاصله پس از بوت، یک‌بار سرویس را به عنوان جبران اجرا می‌کند تا مطمئن شود آدرس آی‌پی شما بدون فوت وقت با شکن همگام شده است.

🔁 ۴. جریان اجرا

۱. بوت سیستم عامل لینوکس
۲. فعال شدن و آغاز شمارش تایمر (shecan-ipupdate.timer)
۳. راه‌اندازی سرویس تک‌مرحله‌ای (oneshot shecan-ipupdate.service)
۴. اجرای امن پوسته شل (shecan-ipupdate.sh)
۵. فراخوانی فایل متغیرهای محیطی با دسترسی ۶۰۰
۶. شلیک درخواست شبکه توسط curl در محیط ایزوله
۷. دریافت پاسخ موفقیت‌آمیز و خاتمه کامل پردازش (oneshot)
۸. مدیریت و زمان‌بندی خودکار اجرای بعدی توسط systemd

🔐 ۵. مدل امنیتی

  1. جداسازی اطلاعات حساس:
    • رمز عبور در فایل جداگانه ذخیره می‌شود.
    • دسترسی فقط برای root مجاز است.
  2. مکانیزم Sandbox:
    • محدودسازی دسترسی به فایل‌ها.
    • جلوگیری از دسترسی به home کاربران.
    • جلوگیری از تغییرات حساس کرنل.
  3. حداقل وابستگی‌ها:
    • فقط systemd و curl.

📊 ۶. مانیتورینگ

بررسی وضعیت سرویس:

systemctl status shecan-ipupdate.service

مشاهده لاگ‌ها:

journalctl -u shecan-ipupdate.service

بررسی تایمرها:

systemctl list-timers
💡 کلاس درس لینوکس: مانیتورینگ پیشرفته، کنترل ژورنال و سیستم جاب سیستم‌دی (کلیک کنید)

سیستم‌عامل لینوکس ابزارهای قدرتمندی برای ردیابی خطاها در اختیار ما می‌گذارد:

  • سیستم کنترل ژورنال (Journald): برخلاف سیستم‌های قدیمی که لاگ‌ها را در فایل‌های متنی ساده درون /var/log رها می‌کردند، سیستم‌دی از یک ساختار باینری بسیار سریع و امن استفاده می‌کند. با دستور journalctl -u shecan-ipupdate.service، سیستم‌دی لاگ‌های مربوط به شناسه یونیت ما را فیلتر کرده و به ترتیب تاریخ نمایش می‌دهد.
  • فلگ‌های کاربردی ژورنال:
    • journalctl -u shecan-ipupdate.service -f: فلگ -f (مخفف Follow) ژورنال را در حالت لایو نگه می‌دارد؛ یعنی به محض اینکه آی‌پی آپدیت شد، لاگ آن در همان ثانیه روی مانیتور شما چاپ می‌شود.
    • journalctl -u shecan-ipupdate.service -n 50 --no-pager: ۵۰ خط آخر لاگ را بدون درگیر کردن ابزار نمایش پیش‌فرض صفحه به نمایش درمی‌آورد.

🚀 ۷. سخت‌سازی در محیط Production

🔒 پیشنهادهای امنیتی پیشرفته

محدودسازی شبکه:

IPAddressDeny=any
IPAddressAllow=ddns.shecan.ir

محدودسازی syscall:

SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM

محدودسازی منابع:

CPUQuota=10%
MemoryMax=50M
TasksMax=10

ایزولاسیون بیشتر:

RestrictAddressFamilies=AF_INET AF_INET6
💡 کلاس درس لینوکس: پشت صحنه سیستمی هاردنینگ پیشرفته، eBPF و لایه‌های کنترل منابع (کلیک کنید)

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

فایروال پیشرفته لایه کارت شبکه (IPAddressDeny/Allow):

سیستم‌دی برای اعمال این فیلتر از فایروال‌های سنتی iptables استفاده نمی‌کند. سیستم‌دی با استفاده از برنامه‌های بومی eBPF (Extended Berkeley Packet Filter)، کدهایی را مستقیماً به داخل سوکت‌های کارت شبکه در داخل هسته کرنل تزریق می‌کند. به محض اینکه برنامه بخواهد بسته‌ای ارسال کند، در عمیق‌ترین لایه کرنل آدرس مقصد چک شده و اگر با آدرس مجاز همخوانی نداشته باشد، دیسکارد می‌شود. این روش عملاً صفر درصد بار پردازشی روی پردازنده دارد.

کنترل منابع با Cgroups (CPUQuota/MemoryMax):

در هسته لینوکس قابلیتی به نام Cgroups (Control Groups) وجود دارد (که تکنولوژی پایه داکر نیز هست). این قابلیت منابع سخت‌افزاری را دسته‌بندی و سهمیه‌بندی می‌کند:

  • CPUQuota=10%: اگر به هر دلیلی کلاینت شما دچار حلقه تکرار بی‌نهایت شود، زمان‌بند سی‌پی‌یو بیش از ۱۰٪ از زمان پردازشی یک هسته را به این پروسه اختصاص نخواهد داد و از کرش کردن بقیه سرویس‌های سرور جلوگیری می‌شود.
  • MemoryMax=50M: اگر مصرف رم این سرویس از ۵۰ مگابایت بالاتر برود، کرنل با استفاده از مکانیزم OOM Killer (Out Of Memory) فوراً پروسه را متوقف می‌کند تا حافظه سرور شما بیهوده هدر نرود.

📦 ۸. استقرار

دستورات زیر را برای نصب، ایجاد فایل‌ها و پیکربندی نهایی به ترتیب روی ترمینال لینوکس اجرا کنید:

sudo cp shecan-ipupdate.sh /usr/local/bin/
sudo chmod +x /usr/local/bin/shecan-ipupdate.sh

sudo cp shecan-ipupdate.service /etc/systemd/system/
sudo cp shecan-ipupdate.timer /etc/systemd/system/

sudo systemctl daemon-reload
sudo systemctl enable --now shecan-ipupdate.timer
💡 کلاس درس لینوکس: کالبدشکافی خط‌به‌خط فرآیند استقرار در سرور (کلیک کنید)

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

  1. دستور sudo cp ... /usr/local/bin/: پوشه /usr/local/bin بر اساس استاندارد ساختار دایرکتوری لینوکس (FHS)، مکان استاندارد برای برنامه‌ها و اسکریپت‌هایی است که به صورت دستی توسط مدیر سیستم نصب شده‌اند و جزئی از پکیج‌های پیش‌فرض توزیع نیستند.
  2. دستور chmod +x: در متادیتای سیستم‌فایل لینوکس (مانند ext4)، هر فایل یک بیت به نام "Execute Bit" دارد. بدون فعال‌سازی این بیت با دستور فوق، کرنل لینوکس این فایل را به عنوان متن ساده می‌بیند و اجازه لود شدن آن در فضای آدرس پردازنده را به عنوان یک فایل اجرایی صادر نمی‌کند.
  3. دستور systemctl daemon-reload: سیستم‌دی پیکربندی تمام یونیت‌ها را در زمان بوت درون حافظه موقت (RAM) خود بارگذاری می‌کند. اگر فایل جدیدی بسازید یا ویرایش کنید، سیستم‌دی متوجه تغییرات دیسک سخت نمی‌شود. این دستور به دیمون سیگنال فرستاده تا مجدداً دایرکتوری‌های پیکربندی را اسکن و جدول پردازش خود را بازسازی کند.
  4. دستور enable --now ...: فعال‌سازی معمولی (enable) پیوندهای نمادین (Symlinks) را در مسیر اجراهای خودکار سیستم می‌سازد تا بعد از ریبوت اجرا شود. اضافه کردن فلگ --now سیستم‌دی را مجبور می‌کند بدون نیاز به ریبوت یا دستور استارت مجزا، همین حالا تایمر را بیدار و فعال کند.

⚠️ ۹. محدودیت‌ها

این سیستم مناسب نیست برای:

🧠 ۱۰. فلسفه طراحی