سروس کو unprivileged user کے طور پر چلانے کا طریقہ
root کے طور پر چلنے والی سروس کا ایک bug پورے server تک رسائی دے سکتا ہے۔ ہر سروس کے لیے الگ unprivileged account بنائیں یا systemd میں DynamicUser استعمال کریں۔
صرف ہر چیز کو root کے طور پر کیوں نہ چلائیں
root مشین پر کچھ بھی کر سکتا ہے: ہر فائل پڑھ سکتا ہے، ہر setting تبدیل کر سکتا ہے، اور پورا system حذف کر سکتا ہے۔ جب آپ کوئی service root کے طور پر چلاتے ہیں تو یہ تمام اختیارات اس service کو دے دیتے ہیں۔ اگر service میں ایسا bug ہو جس سے attacker فائدہ اٹھا سکے تو اسے صرف service تک رسائی نہیں ملتی، بلکہ root تک رسائی مل جاتی ہے، اور root کا مطلب پورے server تک رسائی ہے۔ غیر مراعات یافتہ user کے طور پر چلانے سے نقصان محدود رہتا ہے۔ محدود account کے طور پر چلنے والی service میں موجود bug سے attacker کو صرف ان وسائل تک رسائی ملتی ہے جنہیں وہ account استعمال کر سکتا ہے، اور یہ رسائی تقریباً کسی چیز تک نہیں ہونی چاہیے۔
یہ کم سے کم مراعات کا اصول ہے: system کے ہر حصے کو اپنا کام کرنے کے لیے بالکل درکار access دیں، اس سے زیادہ نہیں۔ compromise کے اثرات کو محدود کرنے کے لیے یہ سب سے مؤثر عادت ہے، اور جدید server پر اسے نافذ کرنے کی لاگت تقریباً کچھ نہیں۔
ہر سروس کے لیے الگ dedicated account
روایتی طریقہ یہ ہے کہ ہر سروس کے لیے الگ system user بنایا جائے۔ اس user کی ملکیت صرف اسی سروس کی فائلیں ہوں اور وہ login نہ کر سکے۔ web app کے لیے system account اس طرح بنایا جا سکتا ہے:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin appsvcہر flag اہم ہے۔ --system اسے انسانی login کے بجائے service account بناتا ہے۔ --no-create-home اس home directory کو چھوڑ دیتا ہے جس کی اسے ضرورت نہیں۔ --shell /usr/sbin/nologin کا مطلب ہے کہ اگر attacker کسی طرح اس account تک رسائی حاصل بھی کر لے، تب بھی وہ اس account سے shell نہیں کھول سکتا۔ یہ account صرف process اور اس کی فائلوں کی ملکیت کے لیے موجود ہوتا ہے۔
اس user کو صرف مطلوبہ فائلوں تک رسائی دیں، اس سے زیادہ نہیں:
sudo chown -R appsvc:appsvc /opt/myappاب سروس اپنی directory کو پڑھ اور لکھ سکتی ہے، لیکن disk پر کسی اور جگہ اس کا کوئی کام نہیں۔ اگر اس سروس میں کبھی security exploit ہو جائے تو attacker جن فائلوں میں تبدیلی کر سکتا ہے، وہ /opt/myapp تک محدود رہتی ہیں۔ account world-readable تمام فائلیں پڑھ سکتا ہے، لیکن system کے باقی حصے میں تبدیلی نہیں کر سکتا۔
systemd سے اسے اسی user کے طور پر چلائیں
اکاؤنٹ بن جانے کے بعد systemd کو ہدایت دیں کہ service اسی کے طور پر چلائے۔ unit file میں ایک سطر کافی ہے:
[Service]
ExecStart=/opt/myapp/bin/server
User=appsvc
Group=appsvcUser=appsvc کا مطلب ہے کہ process، root کے اختیارات کے بجائے اس اکاؤنٹ کے محدود اختیارات کے ساتھ شروع ہوتا ہے۔ systemd کے تحت application چلانے کا یہ معمول کا اور آزمودہ طریقہ ہے، اور ہر اس service کے لیے ایسا کرنا مفید ہے جس کی unit آپ لکھتے ہیں۔ تاہم اگر systemd غلط process کو monitor کر رہا ہو تو privileges کم کرنے سے مدد نہیں ملے گی۔ اگر daemon خاموشی سے exit ہونے کے بعد بھی unit active ظاہر کرے تو تصدیق کریں کہ آپ نے process کے شروع ہونے کے طریقے کے مطابق درست Type= منتخب کیا ہے۔
یا DynamicUser کے ذریعے اکاؤنٹ کو مکمل طور پر چھوڑ دیں
systemd اس سے بھی آگے جا کر آپ کے لیے ایک عارضی صارف بنا سکتا ہے۔ یہ صارف صرف اس وقت موجود رہتا ہے جب سروس چل رہی ہو۔ `DynamicUser=yes` سیٹ کریں اور آپ کو کسی اکاؤنٹ کا انتظام نہیں کرنا پڑے گا:
[Service]
ExecStart=/opt/myapp/bin/server
DynamicUser=yes
StateDirectory=myappشروع کے وقت systemd ایک غیر استعمال شدہ user ID مختص کرتا ہے، اور رکنے کے وقت اسے واپس جاری کر دیتا ہے۔ سروس کو ایک نجی `/tmp بھی ملتا ہے، پورے filesystem کا زیادہ تر حصہ read-only صورت میں دکھائی دیتا ہے، اور StateDirectory= کے ذریعے /var/lib/myapp کے تحت ایک writable state directory تیار کر کے سروس کے حوالے کی جاتی ہے۔ SysV init میں ایسا ممکن نہیں تھا۔ وہاں privileges کم کرنا ہر سروس کی اپنی start script کے طریقہ کار پر منحصر تھا۔ یہی خلا ان اہم وجوہات میں شامل ہے [[history-of-systemd|جن کی وجہ سے distributions نے ابتدا ہی میں systemd اختیار کیا]]۔ ایسی self-contained سروس کے لیے جسے صرف اپنی state directory درکار ہو، DynamicUser=yes` مضبوط isolation حاصل کرنے کا کم سے کم محنت والا طریقہ ہے، کیونکہ کوئی مستقل اکاؤنٹ موجود ہی نہیں ہوتا جسے attacker نشانہ بنا سکے۔
Units کو ہاتھ سے لکھنا مشکل ہو سکتا ہے، اور hardening directives درست طور پر ترتیب دینا ہی زیادہ تر فائدہ فراہم کرتا ہے۔ systemd service اور timer guide میں موجود generator یہ options آپ کے لیے پُر کر سکتا ہے، تاکہ unit پہلی مرتبہ ہی درست ہو۔
یہ مجموعی نظام کے ساتھ کیسے مربوط ہے
کم سے کم مراعات دفاع کی ایک تہہ ہیں، اور یہ دوسری تہوں کی جگہ لینے کے بجائے ان کے ساتھ کام کرتی ہیں۔ default-deny firewall یہ کنٹرول کرتا ہے کہ سروس تک کیا پہنچ سکتا ہے؛ سروس کو غیر مراعات یافتہ صارف کے طور پر چلانے سے یہ محدود ہوتا ہے کہ سروس کے breached ہونے کی صورت میں وہ کیا کر سکتی ہے؛ اور hardened SSH حملہ آوروں کو ابتدا ہی میں سرور سے باہر رکھتا ہے۔ ان میں سے کوئی ایک اقدام کافی نہیں ہے۔ مل کر یہ یقینی بناتے ہیں کہ ایک سروس میں موجود bug پورے سرور کے compromise کا سبب نہ بنے۔ ایسی چیز host کرنا جو secrets کی حفاظت کرتی ہو، یہ واضح کرتا ہے کہ یہ تہیں کہاں تک مؤثر ہیں: restricted account اس چیز کو محدود کرتا ہے جس تک breached process رسائی حاصل کر سکتا ہے، لیکن Vaultwarden جیسا self-hosted password manager اب بھی اس بات پر منحصر رہتا ہے کہ آپ اس کے admin token اور backup file کی حفاظت کیسے کرتے ہیں؛ user isolation ان دونوں کا احاطہ نہیں کرتی۔
آگے بڑھنے سے پہلے، پورے سرور کے لیے hardening checklist مکمل کریں اور کام کے لیے اپنی ضروریات کے مطابق ایک copy تیار کریں:
FAQ
میں service کو root کے طور پر کیوں نہ چلاؤں؟
کیونکہ root مشین پر ہر کام کر سکتا ہے، اس لیے root کے طور پر چلنے والی service exploit ہو جائے تو attacker کو صرف service نہیں بلکہ پورے server کا اختیار مل جاتا ہے۔ service کو محدود، غیر مراعات یافتہ account کے طور پر چلانے سے نقصان اس account کی قابل رسائی چیزوں تک محدود رہتا ہے۔ root کو administration کے لیے مخصوص رکھیں، اور ہر طویل مدت تک چلنے والی service کو restricted user کے طور پر چلائیں۔
میں ایسا user کیسے بناؤں جو log in نہ کر سکے؟
sudo useradd --system --no-create-home --shell /usr/sbin/nologin NAME چلائیں۔ nologin shell کا مطلب ہے کہ credentials چوری ہونے کے باوجود account interactive session نہیں کھول سکتا، --system اسے service account کے طور پر نشان زد کرتا ہے، اور --no-create-home غیر ضروری home directory بنانے سے گریز کرتا ہے۔ chown کے ذریعے اسے صرف اپنی files کی ownership دیں۔
systemd DynamicUser کیا ہے؟
DynamicUser=yes systemd کو ہدایت دیتا ہے کہ service کے لیے ایک عارضی user بنائے جو صرف service کے چلنے تک موجود رہے۔ اس طرح آپ کو مستقل account manage نہیں کرنا پڑتا۔ یہ service کو private /tmp، زیادہ تر read-only filesystem view، اور managed state directory بھی دیتا ہے۔ کم سے کم محنت کے ساتھ self-contained service کو عارضی، کم مراعات والے identity کے تحت چلانے کا یہ آسان ترین طریقہ ہے۔
کیا non-root user کے طور پر چلانا firewall کی جگہ لے لیتا ہے؟
نہیں۔ دونوں مختلف چیزوں کا تحفظ کرتے ہیں۔ غیر مراعات یافتہ user کے طور پر service چلانے سے breach کی صورت میں service کے ممکنہ اقدامات محدود رہتے ہیں، جبکہ firewall اس بات کو محدود کرتا ہے کہ service تک کوئی چیز پہنچ بھی سکتی ہے یا نہیں۔ hardened SSH کے ساتھ دونوں استعمال کریں تاکہ ہر layer ان خطرات کو سنبھالے جنہیں دوسری layers محدود نہیں کر سکتیں۔
service user کو کن files کی ownership دینی چاہیے؟
صرف ان files کی جن کی service کو حقیقتاً ضرورت ہو، اور اس سے زیادہ کسی کی نہیں۔ account کو اس کی اپنی working directory اور data کی ownership دیں، جبکہ باقی سب کچھ root کی ملکیت رہنے دیں۔ ایک اچھا طریقہ یہ ہے کہ application directory کے لیے sudo chown -R svc-app:svc-app /opt/svc-app استعمال کیا جائے، جبکہ /etc کے تحت configuration root کی ملکیت رہے اور service کے لیے صرف readable ہو۔ مقصد یہ ہے کہ اگر process کبھی compromised ہو جائے تو وہ جن files میں تبدیلی کر سکتا ہے، وہ صرف اس کے اپنے data تک محدود ہوں، پورے system تک نہیں۔