nginx 403: permissions درست ہیں مگر SELinux روک رہا ہے
nginx کا 403 تب حل کریں جب permissions درست ہوں: SELinux denial پڑھیں، semanage سے درست label لگائیں، restorecon چلائیں اور enforcing فعال رکھیں۔
فائل کی permissions درست ہونے کے باوجود nginx 403 کیوں واپس کرتا ہے
جس فائل کے permission bits درست ہوں، اس پر nginx کا 403 واپس کرنا تقریباً ہمیشہ SELinux (security-enhanced Linux) کی جانب سے read سے انکار کی وجہ سے ہوتا ہے۔ عام permissions کی جانچ کامیاب ہونے کے بعد SELinux قواعد کے ایک دوسرے مجموعے کو بھی لاگو کرتا ہے۔ web server صرف وہ فائلیں پڑھ سکتا ہے جن پر web content label موجود ہو۔ آپ کی فائل پر مختلف label ہے، اس لیے open ناکام ہو جاتا ہے اور nginx کے پاس بھیجنے کے لیے کچھ نہیں ہوتا۔
صرف mode نہیں، label بھی دیکھیں:
ls -ldZ /data/www /data/www/index.htmldrwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /data/www
-rw-r--r--. root root unconfined_u:object_r:default_t:s0 /data/www/index.htmldrwxr-xr-x کے بعد چھاپا جانے والا dot ظاہر کرتا ہے کہ فائل پر SELinux label موجود ہے۔ default_t وہ label ہے جو کسی path کو اس وقت ملتا ہے جب policy اس path سے کبھی واقف نہ رہی ہو۔ web server کے قواعد میں اس type کو پڑھنے کی اجازت نہیں ہوتی۔ error log عام Unix error دکھاتا ہے، اسی لیے یہ permissions کے مسئلے جیسا معلوم ہوتا ہے:
2026/08/11 09:14:02 [error] 1183#1183: *1 open() "/data/www/index.html" failed (13: Permission denied), client: 203.0.113.9, server: _, request: "GET / HTTP/1.1"kernel دونوں طرح کے انکار، عام انکار اور SELinux والے انکار، کے لیے 13: Permission denied واپس کرتا ہے۔ اس لیے پہلا کام یہ معلوم کرنا ہے کہ انکار کس layer نے کیا۔ setenforce 0 سے شروع نہ کریں۔
ماڈل کا وہ حصہ جس کی آپ کو ضرورت ہے
SELinux لازمی access control ہے، جسے عموماً MAC لکھا جاتا ہے۔ ہر process ایک domain میں چلتا ہے، جیسے web server کے لیے httpd_t۔ ہر file اور ہر network port ایک type رکھتا ہے، جیسے httpd_sys_content_t۔ Policy، domain، type اور action کے مجاز امتزاجوں کی فہرست ہوتی ہے، اور جو کچھ اس فہرست میں شامل نہ ہو اسے deny کر دیا جاتا ہے۔ یہ classic Unix check کے بعد نافذ ہوتی ہے، اس لیے drwxr-xr-x میں permission bits کو پہلے access کی اجازت دینی ہوتی ہے۔ دونوں layers کو اجازت دینی ضروری ہے۔
مکمل context میں colon سے جدا چار fields ہوتی ہیں، جیسے system_u:system_r:httpd_t:s0: SELinux user، role، type اور level۔ Server پر آپ تقریباً سارا وقت تیسرے field، یعنی type، کے ساتھ کام کرتے ہیں۔ دو commands موجودہ values دکھاتی ہیں:
ps -eZ | grep nginx
id -Znginx workers کا context httpd_t پر ختم ہوتا ہے۔ آپ کے login shell کا context unconfined_u:unconfined_r:unconfined_t:s0 دکھاتا ہے، کیونکہ default targeted policy services کو محدود کرتی ہے اور interactive users کو اس پابندی سے باہر رکھتی ہے۔ یہ بات جاننا اہم ہے، کیونکہ SELinux services کو least-privilege users کے تحت چلانے کا متبادل نہیں ہے۔ جب کوئی service breach ہو جائے تو یہ اس کے بعد بھی محدود کرتی ہے کہ وہ کن resources تک پہنچ سکتی ہے۔
تین modes، اور SELinux کن images میں موجود ہے
sestatus
getenforceEnforcing رسائی کو روکتا اور اسے log کرتا ہے۔ Permissive ہر چیز کی اجازت دیتا ہے اور ان کارروائیوں کو log کرتا ہے جنہیں یہ روکتا۔ Disabled کوئی policy load نہیں کرتا۔ getenforce موجودہ mode دکھاتا ہے۔ sestatus /etc/selinux/config سے mode بھی دکھاتا ہے، اور reboot کے بعد یہی mode دوبارہ فعال ہوتا ہے۔
Rocky Linux، AlmaLinux، Fedora اور RHEL، targeted policy کے ساتھ SELinux کو enforcing mode میں فراہم کرتے ہیں۔ یہ مشترکہ default محض اتفاق نہیں، بلکہ اس مشترکہ Red Hat سلسلے کا ورثہ ہے جو Rocky Linux اور AlmaLinux کے وجود میں آنے سے پہلے CentOS تک پہنچتا تھا۔ آپ دونوں میں سے کون سا استعمال کرتے ہیں، اس صفحے کی کسی بات پر اثر نہیں پڑتا، کیونکہ دونوں ایک ہی policy اور وہی tools فراہم کرتے ہیں۔ اس لیے Rocky Linux اور AlmaLinux میں انتخاب security defaults کے بجائے ان کے compatibility promises اور پرانے CPU support پر منحصر ہوتا ہے۔ Ubuntu اور Debian اس کے بجائے AppArmor فراہم کرتے ہیں، جو مختلف mechanism کے ذریعے یہی کام کرتا ہے (آخری section میں اس کا احاطہ کیا گیا ہے)۔ اسی لیے ایک ہی application آپ کے ایک server پر cleanly install ہو سکتی ہے اور دوسرے پر 403 واپس کر سکتی ہے۔
ضرورت پیش آنے سے پہلے ٹولز انسٹال کریں
sudo dnf install -y policycoreutils-python-utils setroubleshoot-serversemanage: command not found کا کم سے کم image پر موجود نہ ہونا اس بات کی علامت ہے کہ policycoreutils-python-utils غائب ہے۔ اس package میں semanage اور audit2allow شامل ہیں۔ setroubleshoot-server، sealert شامل کرتا ہے اور ہر denial کا سادہ انگریزی خلاصہ journal میں لکھتا ہے۔ دونوں کو نئے server پر پہلے ہی انسٹال کریں، کیونکہ جب ان کی ضرورت پڑتی ہے تو عموماً کوئی چیز پہلے ہی خراب ہو چکی ہوتی ہے۔
SELinux denial کو audit log میں کیسے پڑھیں
ہر refusal کو audit daemon، AVC (access vector cache) message کے طور پر record کرتا ہے:
sudo ausearch -m AVC,USER_AVC,SELINUX_ERR -ts recenttype=AVC msg=audit(1754896442.881:412): avc: denied { read } for pid=1183 comm="nginx" name="index.html" dev="vda1" ino=17203 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0چار fields پوری صورتِ حال بیان کرتی ہیں۔ comm وہ program ہے جسے block کیا گیا۔ scontext source context ہے، یعنی وہ domain جس میں process چل رہا تھا۔ tcontext target context ہے، یعنی اس چیز پر لگا ہوا label جس تک process نے رسائی کی کوشش کی۔ tclass object کی قسم ہے، یہاں file۔ انہیں ملا کر مفہوم یہ بنتا ہے: httpd_t میں چلنے والے process نے default_t label والی file پڑھنے کی کوشش کی، اور permissive=0 بتاتا ہے کہ request واقعی block ہوئی، صرف log نہیں کی گئی۔
اگر ausearch کچھ بھی print نہ کرے تو audit daemon شاید چل نہیں رہا۔ ایسی صورت میں denials kernel ring buffer میں درج ہوتی ہیں:
sudo journalctl -k | grep -i avcاب record کو انگریزی کے ایک جملے میں تبدیل کریں:
sudo ausearch -m AVC -ts recent | audit2why
sudo journalctl -t setroubleshoot --since today
sudo sealert -a /var/log/audit/audit.logaudit2why وہی records پڑھتا ہے اور اپنی شناخت کے مطابق وجہ بتاتا ہے: کوئی boolean بند ہے، کوئی label policy سے match نہیں کرتا، یا کوئی rule موجود ہی نہیں۔ sealert پوری log کا جائزہ لیتا ہے اور ہر denial کے لیے ایک تجویز کردہ command print کرتا ہے۔ اس تجویز کو صرف hint سمجھیں۔ مختلف releases میں wording بدل سکتی ہے، اور sealert کبھی کبھی custom policy module تجویز کرتا ہے، حالانکہ درست حل صرف ایک سطری label fix ہوتا ہے۔
ایک اور بات بھی جاننا ضروری ہے۔ Policy میں dontaudit rules شامل ہوتے ہیں جو بے ضرر سمجھی جانے والی denials کو چھپا دیتے ہیں۔ اس لیے program غلط کام کر سکتا ہے جبکہ log خالی رہے۔ ایک test کے دورانیے تک انہیں ظاہر کریں:
sudo semodule -DB
# reproduce the problem, then read the log again
sudo semodule -Bsemanage fcontext اور restorecon سے غلط label والے path کی درستی
دو commands ہیں، اور ترتیب اہم ہے۔ semanage fcontext -a یہ record کرتا ہے کہ کسی path کا label کیا ہونا چاہیے۔ restorecon اس record شدہ default کو disk پر موجود files پر apply کرتا ہے۔
sudo semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?"
sudo restorecon -Rv /data/www
ls -ldZ /data/www/index.htmlیہ path ایک regular expression ہے۔ (/.*)? خود directory اور اس کے اندر موجود ہر چیز کو شامل کرتا ہے، جو document root کے لیے ضروری ہے۔ تبدیلی سے پہلے دیکھیں کہ کیا بدلے گا: sudo restorecon -Rvn /data/www planned relabels دکھاتا ہے، کیونکہ -n کا مطلب ہے کہ کوئی action نہ لیا جائے۔ حقیقی restorecon کے بعد label httpd_sys_content_t دکھاتا ہے اور 403 ختم ہو جاتا ہے، کسی service restart کے بغیر۔
chcon کو صرف test کے طور پر استعمال کریں۔ chcon -t httpd_sys_content_t index.html label براہِ راست set کرتا ہے، اور اگلا restorecon، package update یا full relabel اسے reset کر دیتا ہے، کیونکہ policy اب بھی کہتی ہے کہ path کا label کچھ اور ہونا چاہیے۔ جس machine پر dnf-automatic مقررہ وقت پر security updates apply کرتا ہے، وہاں یہ reset آپ کے سامنے machine ہونے کے بجائے اپنے schedule کے مطابق ہوتا ہے، اس لیے آخری تبدیلی کے کئی گھنٹے بعد site خراب ہو جاتی ہے۔ semanage fcontext وہ version ہے جو برقرار رہتا ہے۔ sudo semanage fcontext -l | grep '^/data' سے درج کیے گئے labels کی فہرست دیکھیں۔
جس content پر service کو write کرنا ہو، اس کے لیے مختلف type درکار ہوتی ہے۔ upload directory یا cache کے لیے httpd_sys_rw_content_t استعمال کریں، اور اسے صرف انہی paths تک محدود رکھیں: writable type کے تحت read-only site application کی ضرورت سے زیادہ access فراہم کرتی ہے۔
Label آخر غلط کیوں تھا؟ تقریباً ہمیشہ وجہ یہ ہوتی ہے کہ files کیسے پہنچی تھیں۔ mv file کا موجودہ label برقرار رکھتا ہے، اس لیے /root سے منتقل کی گئی site admin_home_t label کے ساتھ پہنچتی ہے اور اسی طرح رہتی ہے۔ سادہ cp نئی file کو destination directory کا default label دیتا ہے، جو عموماً مطلوب ہوتا ہے، جبکہ cp -a اور rsync -X source labels کو بھی file کے ساتھ copy کرتے ہیں۔ نئی top-level directory میں git clone کرنے سے default_t بنتا ہے۔ جب page /usr/share/nginx/html سے درست load ہو لیکن آپ کی اپنی directory سے fail ہو، تو یہی وجہ ہوتی ہے۔
بولین سے ایک مخصوص طرزِ عمل درست کریں
ہر خرابی label کا مسئلہ نہیں ہوتی۔ نئے Rocky یا AlmaLinux server پر reverse proxy، 502 واپس کرتا ہے، اور error log میں یہ درج ہوتا ہے:
2026/08/11 10:02:55 [crit] 1183#1183: *3 connect() to 127.0.0.1:3000 failed (13: Permission denied) while connecting to upstreamآپ کا upstream درست ہے۔ httpd_t domain کو default طور پر outbound network connections کھولنے کی اجازت نہیں ہوتی، اس لیے connect() call loopback interface تک پہنچنے سے پہلے ہی مسترد ہو جاتی ہے۔ ایک switch اس پورے طرزِ عمل کو کنٹرول کرتا ہے:
getsebool -a | grep httpd_can_network
sudo setsebool -P httpd_can_network_connect on-P وہ flag ہے جو اہم ہے: یہ value کو disk پر لکھتا ہے۔ -P کے بغیر اگلے reboot پر یہ تبدیلی ختم ہو جاتی ہے، اور service صرف اس وقت تک کام کرتی ہے جب تک machine restart نہ ہو۔ semanage boolean -l | grep httpd_can_network_connect سے تصدیق کریں؛ یہ running value کو stored value کے ساتھ دکھاتا ہے۔
جب موجود ہو تو خود لکھی ہوئی rule کے بجائے boolean استعمال کریں۔ Booleans distribution policy کے ساتھ جاری ہوتے ہیں، اس لیے ان کی دیکھ بھال کی جاتی ہے، documentation دستیاب ہوتی ہے، اور اگلے administrator کے لیے انہیں تلاش کرنا آسان ہوتا ہے۔ getsebool -a system پر موجود تمام booleans کی فہرست دکھاتا ہے۔
سروس کو غیر معیاری port پر listen کروائیں
ports کو label بھی کیا جاتا ہے۔ nginx کو 8081 پر منتقل کرنے کی کوشش کریں تو یہ start ہونے سے انکار کر دیتا ہے:
nginx: [emerg] bind() to 0.0.0.0:8081 failed (13: Permission denied)httpd_t صرف ان ports پر bind کر سکتا ہے جنہیں http_port_t label کیا گیا ہو، اور 8081 ان میں شامل نہیں ہے۔ اسے شامل کریں:
sudo semanage port -l | grep -w http_port_t
sudo semanage port -a -t http_port_t -p tcp 8081پہلے فہرست دیکھیں۔ کئی high ports پہلے ہی مجاز ہیں، جن میں 8008 اور 8443 شامل ہیں، اور کسی port کو دوسری بار شامل کرنے سے ValueError: Port tcp/8081 already defined ناکام ہو جاتا ہے۔ اگر port پہلے ہی کسی مختلف type سے متعلق ہو تو اسے شامل کرنے کے بجائے semanage port -m -t http_port_t -p tcp 8081 سے تبدیل کریں۔
یہی command منتقل کیے گئے SSH port کو بھی کام کرنے کے قابل بناتی ہے۔ journalctl -u sshd میں Bind to port 2222 on 0.0.0.0 failed: Permission denied کا مطلب ہے کہ 2222، ssh_port_t میں موجود نہیں ہے۔ اس لیے daemon restart کرنے اور اپنا session بند کرنے سے پہلے sudo semanage port -a -t ssh_port_t -p tcp 2222 چلائیں۔ Red Hat family image پر VPS پر SSH کو harden کرنے کی عمومی guide پر عمل کرتے وقت لوگ عموماً یہی مرحلہ چھوڑ دیتے ہیں۔ SELinux firewall بھی نہیں ہے، اس لیے port کو پھر بھی open کرنا ہوگا: یہاں sudo firewall-cmd --permanent --add-port=8081/tcp && sudo firewall-cmd --reload، یا Debian یا Ubuntu image پر ufw استعمال کریں۔ --permanent flag میں وہی reboot trap ہے جو boolean پر -P میں ہوتا ہے، اور یہ سمجھنے کے لیے کہ کون سے interfaces پر کوئی rule لاگو ہوتا ہے، ان zones کو ایک بار پڑھ لینا مفید ہے جن کی وضاحت Rocky یا AlmaLinux VPS پر firewalld کی بنیادی باتیں میں کی گئی ہے۔
جب تبدیل کرنے کے لیے کوئی boolean یا label موجود نہ ہو
عام سرور پر یہ صورت حال کم ہی پیش آتی ہے، اور اسی موقع پر لوگ نقصان کر بیٹھتے ہیں۔ audit2allow لاگ میں موجود denials سے policy module بنا سکتا ہے:
sudo ausearch -m AVC -ts recent -c nginx | audit2allow -M nginx_local
cat nginx_local.te
sudo semodule -i nginx_local.ppاسے install کرنے سے پہلے nginx_local.te پڑھیں۔ اسے محفوظ رکھنے کے لیے دو عادتیں اپنائیں۔ -c کے ذریعے input کو صرف اسی program تک محدود کریں جسے آپ درست کر رہے ہیں، کیونکہ ایک ہفتے کے غیر متعلقہ denials کو audit2allow میں pipe کرنے سے وہ سب ایک ساتھ grant ہو جاتے ہیں۔ اور ایسا module کبھی install نہ کریں جس میں موجود denial کی آپ وضاحت نہ کر سکیں: ایسی rule بنانا آسان ہے جو httpd_t کو پورے system کی ہر file پڑھنے دے، لیکن کئی ماہ بعد اسے تلاش کرنا مشکل ہوتا ہے۔ sudo semodule -r nginx_local کے ذریعے module remove کریں۔
تشویقاتی موڈ تشخیص کے لیے ہے، مسئلے کے حل کے لیے نہیں
sudo setenforce 0
# reproduce the problem once, all the way through
sudo ausearch -m AVC -ts recent
sudo setenforce 1تشویقاتی موڈ رسائی کی اجازت دیتا ہے اور اسے log میں درج کرتا ہے۔ اس کی اصل افادیت مکمل معلومات فراہم کرنا ہے۔ enforcing موڈ میں سروس پہلی denial پر رک جاتی ہے۔ آپ اسے درست کرتے ہیں، سروس دوبارہ شروع کرتے ہیں، اور دوسری denial سامنے آ جاتی ہے۔ تشویقاتی موڈ میں عمل جاری رہتا ہے اور log ایک ہی مرحلے میں تمام denials جمع کر لیتا ہے۔ اس کے بعد آپ موڈ دوبارہ تبدیل کر کے تمام مسائل ایک ساتھ درست کر سکتے ہیں۔
setenforce، /etc/selinux/config کو تبدیل نہیں کرتا۔ اس لیے reboot کے بعد سسٹم دوبارہ enforcing موڈ میں آ جاتا ہے۔ یہ ایک حفاظتی انتظام ہے۔ اسی وجہ سے setenforce 0 پر مبنی عارضی "حل" بدترین ممکنہ وقت پر دوبارہ ظاہر ہو جاتا ہے۔ اگر کسی ایک سروس کو کام کے دوران اضافی گنجائش درکار ہو تو پوری مشین کے بجائے صرف اس domain کو نشان زد کریں: sudo semanage permissive -a httpd_t باقی تمام سروسز کو enforcing موڈ میں رکھتا ہے، جبکہ sudo semanage permissive -d httpd_t اسے واپس سابقہ حالت میں لے آتا ہے۔
لیبل درست کرنے کے بجائے SELinux کو غیر فعال کرنا زیادہ مہنگا کیوں پڑتا ہے
/etc/selinux/config میں SELINUX=disabled مقرر کرنے سے ایک سطر کی label درستگی کے بدلے سرور مستقل طور پر کم محفوظ ہو جاتا ہے۔ اس فرق کا اندازہ اس دن ہوتا ہے جب کوئی web application compromised ہو جائے۔ enforcing حالت میں حملہ آور کا code httpd_t میں چلتا ہے، اس لیے وہ web content پڑھ سکتا ہے، لیکن policy کے مطابق /etc/shadow پڑھنے یا systemd unit لکھنے کی اجازت نہیں ملتی، خواہ Unix user کو اس کی اجازت حاصل ہو۔ جب کوئی policy loaded نہ ہو تو یہی code service account کو حاصل تمام اختیارات استعمال کر لیتا ہے۔
SELinux کو غیر فعال کرنے کی ایک قیمت بعد میں ادا کرنا پڑتی ہے۔ جب کوئی policy loaded نہ ہو تو نئی files بغیر label کے بنائی جاتی ہیں، اس لیے filesystem policy کے ساتھ مطابقت کھو دیتا ہے۔ SELinux دوبارہ فعال کرنے پر مکمل relabel درکار ہوتا ہے، ورنہ بیک وقت بہت سی services fail ہو سکتی ہیں:
sudo fixfiles -F onboot
sudo rebootیہ /.autorelabel لکھتا ہے اور اگلے boot کے دوران ہر filesystem کو relabel کرتا ہے۔ بڑی disk پر اس میں کافی وقت لگتا ہے اور console رکی ہوئی دکھائی دے سکتی ہے، اس لیے اسے اس وقت شروع کریں جب آپ انتظار کر سکیں۔ چونکہ machine ویسے بھی shutdown ہونے والی ہے، اس لیے پہلے یہ دیکھ لینا مفید ہے کہ restart کے لیے اور کیا کچھ queued ہے۔ یہی کام dnf update کے بعد memory میں موجود پرانے kernels اور libraries کے بارے میں needs-restarting رپورٹ کرتا ہے۔ Rocky Linux اور AlmaLinux 9 میں config file اب خود kernel کے حصے کو غیر فعال نہیں کرتی، اور SELinux کو مکمل طور پر غیر فعال کرنے کا دستاویزی طریقہ kernel argument (sudo grubby --update-kernel ALL --args selinux=0) استعمال کرنا ہے۔ جب آپ کسی اور کا server سنبھالیں تو یہ command معلوم ہونا مفید ہے۔ یہ 403 کا حل نہیں ہے۔
Containers ایک اضافی label شامل کرتے ہیں
Red Hat family کے host پر container processes container_t میں چلتے ہیں اور صرف container_file_t سے label کردہ files پڑھ سکتے ہیں۔ Host سے bind mount کرنے پر container کے اندر Permission denied آتا ہے، جبکہ host پر ls -l بالکل درست دکھائی دیتا ہے۔ :Z suffix runtime کو mount پر دوبارہ label لگانے کی ہدایت دیتا ہے:
docker run -d -v /data/appdata:/var/lib/app:Z myimage:Z directory کو صرف اس container کے لیے label کرتا ہے۔ :z اسے containers کے درمیان sharing کے لیے label کرتا ہے۔ :Z کو ایسی directory پر لگانے سے جسے دوسری services استعمال کرتی ہوں، وہ directory recursively relabel ہو جاتی ہے اور ان services میں خرابی پیدا ہو جاتی ہے، اس لیے containers کے لیے الگ paths استعمال کریں۔ اگر engine ابھی box پر موجود نہیں ہے تو یاد رکھیں کہ ان distributions پر docker command اکثر podman کے نام سے جواب دیتی ہے۔ یہ ایک اضافی پیچیدگی ہے جسے Rocky اور AlmaLinux کی installation steps اس مرحلے سے پہلے حل کر دیتی ہیں۔ Setup کی باقی تمام تفصیلات کسی بھی دوسری image جیسی ہی ہیں، جیسا کہ VPS پر Docker چلانے میں بیان کیا گیا ہے۔
Ubuntu اور Debian آپ کو AppArmor دیتے ہیں
کام وہی ہے، ڈیزائن مختلف ہے۔ AppArmor کسی پروگرام کو اس کی executable کے path کی بنیاد پر محدود کرتا ہے۔ اس کے لیے /etc/apparmor.d/ کے تحت profile استعمال ہوتی ہے، disk پر موجود files کو label کرنے کے بجائے۔ relabel کرنے کے لیے کچھ نہیں ہوتا اور نہ ہی restorecon ہوتا ہے۔ ابتدا یہاں سے کریں:
sudo aa-status
sudo journalctl -k | grep -i apparmorانکار apparmor="DENIED" operation="open" profile="/usr/sbin/nginx" name="/data/www/index.html" requested_mask="r" کے طور پر ظاہر ہوتا ہے۔ طریقۂ کار کی بنیادی ساخت وہی ہے: denial پڑھیں، profile تلاش کریں، rule تبدیل کریں۔ sudo apt install apparmor-utils آپ کو aa-complain فراہم کرتا ہے، جو ایک profile کے لیے permissive mode ہے، اور aa-enforce اسے دوبارہ فعال کرنے کے لیے ہے۔ Ubuntu packaged services کے منتخب مجموعے کو محدود کرتا ہے اور باقی کو unconfined چھوڑ دیتا ہے۔ اس لیے یہ فرض کرنے کے بجائے کہ حقیقت میں کیا active ہے، aa-status پڑھیں۔
ایک عادت دونوں systems میں کارآمد رہتی ہے۔ جب کوئی service ایسی چیز پر Permission denied report کرے جو درست معلوم ہوتی ہو، تو permissions تبدیل کرنے سے پہلے security log پڑھیں۔ ایک ہی مسئلے کی وجہ عموماً دوبارہ file permissions نہیں ہوتیں۔
FAQ
درست file permissions کے باوجود nginx 403 کیوں واپس کرتا ہے؟
کیونکہ SELinux نے read کو deny کیا، permission bits نے نہیں۔ web server httpd_t domain میں چلتا ہے اور صرف وہی files read کر سکتا ہے جن پر web content کے لیے درست label لگا ہو۔ اس لیے default_t یا admin_home_t label والی file کو refuse کر دیا جاتا ہے، اور nginx کے پاس serve کرنے کے لیے کچھ نہیں رہتا۔ sudo ausearch -m AVC -ts recent سے تصدیق کریں۔ یہ scontext کو httpd_t پر ختم ہوتا ہوا دکھاتا ہے، جبکہ tcontext پر غلط type موجود ہوتی ہے۔ پھر درست label record کر کے apply کریں: sudo semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?"، اس کے بعد sudo restorecon -Rv /data/www۔
کیا service کو چلانے کے لیے setenforce 0 چلانا محفوظ ہے؟
setenforce 0 تشخیصی قدم ہے، حل نہیں۔ مسئلے کو ایک بار reproduce کرنے کے لیے اسے استعمال کریں تاکہ log ایک ہی pass میں تمام denials جمع کر لے۔ انہیں sudo ausearch -m AVC -ts recent سے پڑھیں، پھر sudo setenforce 1 چلائیں اور وجوہات درست کریں۔ permissive حالت میں چھوڑا گیا server ہر denial کو log کرتا ہے اور کسی کو block نہیں کرتا۔ یوں شور برقرار رہتا ہے اور protection ختم ہو جاتی ہے۔ اگر کام کے دوران کسی ایک service کو عارضی گنجائش درکار ہو تو sudo semanage permissive -a httpd_t چلائیں تاکہ باقی machine enforcing حالت میں رہے۔
SELinux کو enforcing حالت میں رکھتے ہوئے non-standard port پر service کیسے چلاؤں؟
port کو اس type میں شامل کریں جس پر وہ service bind کر سکتی ہے۔ 8081 پر web server کے لیے: sudo semanage port -a -t http_port_t -p tcp 8081۔ 2222 پر SSH کے لیے: sudo semanage port -a -t ssh_port_t -p tcp 2222۔ پہلے sudo semanage port -l | grep -w http_port_t سے موجودہ list دیکھیں، کیونکہ پہلے سے درج port ValueError: Port tcp/8081 already defined کے ساتھ fail ہو جاتا ہے۔ یہ قدم نہ ہو تو daemon startup کے وقت bind() ... Permission denied کے ساتھ exit کر دیتا ہے، چاہے کوئی دوسرا process اس port کو hold نہ کر رہا ہو۔
کیا Ubuntu میں SELinux موجود ہے؟
نہیں۔ Ubuntu اور Debian میں AppArmor شامل ہوتا ہے۔ یہ files پر labels کے بجائے executable کے path سے وابستہ profile نافذ کرتا ہے۔ اسے sudo aa-status سے check کریں اور sudo journalctl -k میں apparmor="DENIED" lines تلاش کریں۔ Ubuntu منتخب packaged services کو محدود کرتا ہے، اس لیے بہت سے programs default طور پر unconfined چلتے ہیں۔ Rocky Linux اور AlmaLinux میں SELinux عموماً out of the box enforcing حالت میں ملتا ہے، اسی طرح Fedora اور RHEL میں بھی۔