nginx 403 பிழை: SELinux அனுமதிகளை சரிசெய்வது எப்படி?
nginx 403 பிழை மற்றும் கோப்பு அனுமதிகள் சரியாக இருந்தும் வரும் சிக்கல்களை தீர்க்கவும். semanage மற்றும் restorecon கட்டளைகள் மூலம் SELinux லேபிள்களை சரிசெய்து சர்வரை இயக்கவும்.
nginx ஏன் கோப்பின் அனுமதிகள் சரியாக இருந்தும் 403 பிழையைத் தருகிறது
கோப்பின் அனுமதி பிட்கள் (permission bits) சரியாக இருந்தும் nginx 403 பிழையைத் தருகிறது என்றால், அது பெரும்பாலும் SELinux (security-enhanced Linux) அந்த கோப்பை வாசிக்க அனுமதி மறுப்பதால்தான் நிகழ்கிறது. சாதாரண அனுமதி சோதனைகள் முடிந்த பிறகு, SELinux இரண்டாவது அடுக்கு விதிகளைச் சரிபார்க்கும். இணைய சேவையகம் (web server) இணைய உள்ளடக்க லேபிளைக் (web content label) கொண்ட கோப்புகளை மட்டுமே வாசிக்க அனுமதிக்கப்படும். உங்கள் கோப்பு வேறு லேபிளைக் கொண்டிருப்பதால், அதைத் திறக்க முடியாமல் போகிறது; இதனால் nginx-ஆல் எதையும் அனுப்ப முடிவதில்லை.
கோப்பின் பயன்முறை (mode) மட்டுமின்றி, அதன் லேபிளையும் கவனியுங்கள்:
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 லேபிள் இருப்பதைக் குறிக்கிறது. default_t என்பது கொள்கையில் (policy) வரையறுக்கப்படாத ஒரு பாதைக்குக் கிடைக்கும் லேபிள் ஆகும். இணைய சேவையகத்தின் விதிகளில் அந்த வகையை வாசிக்க அனுமதி இல்லாததால், இந்த பிழை ஏற்படுகிறது. பிழைப் பதிவில் (error log) சாதாரண Unix பிழை காட்டப்படுவதால், இது அனுமதி தொடர்பான பிழையாகத் தோன்றுகிறது:
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 என்ற பிழையையே தருகிறது. எனவே, எந்த அடுக்கு அனுமதி மறுத்தது என்பதைக் கண்டறிவதே முதல் வேலை. setenforce 0 கட்டளையுடன் தொடங்க வேண்டாம்.
நீங்கள் கவனிக்க வேண்டிய மாதிரியின் பகுதி
SELinux என்பது கட்டாய அணுகல் கட்டுப்பாடு (Mandatory Access Control), இது பொதுவாக MAC என்று அழைக்கப்படுகிறது. ஒவ்வொரு process-ம் ஒரு domain-ல் இயங்குகிறது, உதாரணமாக web server-க்கு httpd_t. ஒவ்வொரு கோப்பும் (file) மற்றும் ஒவ்வொரு network port-ம் ஒரு type-ஐக் கொண்டிருக்கும், உதாரணமாக httpd_sys_content_t. இந்த policy என்பது domain, type மற்றும் action ஆகியவற்றின் அனுமதிக்கப்பட்ட சேர்க்கைகளின் பட்டியலாகும்; இந்தப் பட்டியலில் இல்லாத அனைத்தும் மறுக்கப்படும். இது வழக்கமான Unix சோதனைகளுக்குப் பிறகு இயங்குகிறது, எனவே drwxr-xr-x-ல் உள்ள permission bits முதலில் அணுகலை அனுமதிக்க வேண்டும். இரண்டு அடுக்குகளும் (layers) அனுமதி அளித்தால் மட்டுமே செயல்பாடு நடக்கும்.
முழுமையான context நான்கு புலங்களைக் (fields) கொண்டிருக்கும், அவை பெருங்குறிகளால் (colons) பிரிக்கப்பட்டிருக்கும், உதாரணமாக system_u:system_r:httpd_t:s0: SELinux user, role, type, மற்றும் level. ஒரு server-ல் நீங்கள் பெரும்பாலான நேரத்தை மூன்றாவது புலமான type-ஐக் கையாள்வதிலேயே செலவிடுவீர்கள். நேரடி மதிப்புகளைக் காட்ட இரண்டு கட்டளைகள் உள்ளன:
ps -eZ | grep nginx
id -Znginx workers-ன் context httpd_t என்று முடிவடையும். உங்கள் login shell unconfined_u:unconfined_r:unconfined_t:s0 என்று காட்டும், ஏனெனில் இயல்பான targeted policy சேவைகளை (services) மட்டுமே கட்டுப்படுத்துகிறது, interactive பயனர்களை விட்டுவிடுகிறது. இதைத் தெரிந்துகொள்வது அவசியம், ஏனெனில் SELinux என்பது குறைந்தபட்ச சலுகை கொண்ட பயனர்களின் கீழ் சேவைகளை இயக்குவதற்கு மாற்றாகாது. ஒரு சேவையை யாராவது ஊடுருவினால் (break into), அந்தச் சேவை எதை அணுக முடியும் என்பதை இது கட்டுப்படுத்துகிறது.
மூன்று முறைகள் மற்றும் SELinux கொண்ட images
sestatus
getenforceEnforcing முறையில் செயல்பாடுகள் தடுக்கப்பட்டு, அவை log செய்யப்படுகின்றன. Permissive முறையில் அனைத்து செயல்பாடுகளும் அனுமதிக்கப்படுகின்றன, ஆனால் தடுக்கப்பட வேண்டியவை log செய்யப்படுகின்றன. Disabled முறையில் எந்தவொரு policy-யும் ஏற்றப்படுவதில்லை. getenforce தற்போதைய முறையைக் காட்டும். sestatus ஆனது /etc/selinux/config-ல் உள்ள முறையையும் காட்டும்; இதுவே reboot-க்கு பிறகு அமலுக்கு வரும் முறையாகும்.
Rocky Linux, AlmaLinux, Fedora மற்றும் RHEL ஆகியவை SELinux-ஐ targeted policy-உடன் enforcing நிலையில் வழங்குகின்றன. Ubuntu மற்றும் Debian ஆகியவை அதற்குப் பதிலாக AppArmor-ஐ வழங்குகின்றன; இது வெவ்வேறு வழிமுறைகளைப் பயன்படுத்தினாலும் அதே பணியைச் செய்கிறது (இதனை கடைசிப் பகுதியில் காணலாம்). எனவே, ஒரே application உங்கள் ஒரு server-ல் சரியாக நிறுவப்படலாம், ஆனால் மற்றொன்றில் 403 பிழையைத் தரலாம்.
தேவைப்படுவதற்கு முன்பே கருவிகளை நிறுவுதல்
sudo dnf install -y policycoreutils-python-utils setroubleshoot-serversemanage: command not found ஒரு minimal image-ல் இருந்தால், policycoreutils-python-utils விடுபட்டுள்ளது என்று அர்த்தம்: அந்த package-ல் தான் semanage மற்றும் audit2allow உள்ளன. setroubleshoot-server ஆனது sealert-ஐச் சேர்க்கிறது, மேலும் ஒவ்வொரு denial பற்றிய சுருக்கமான விளக்கத்தை plain-English-ல் journal-ல் எழுதுகிறது. புதிய server-ல் இவை இரண்டையும் உடனே நிறுவிவிடவும், ஏனெனில் இவை தேவைப்படும் தருணத்தில் ஏதோ ஒன்று ஏற்கனவே பழுதடைந்திருக்கும்.
SELinux மறுப்பை audit log-ல் வாசிப்பது எப்படி
ஒவ்வொரு மறுப்பும் audit daemon-ஆல் AVC (access vector cache) செய்தியாகப் பதிவு செய்யப்படுகிறது:
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நான்கு புலங்கள் முழு விவரத்தையும் கொண்டுள்ளன. comm என்பது தடுக்கப்பட்ட நிரல் ஆகும். scontext என்பது source context, அதாவது அந்த process இயங்கிக்கொண்டிருந்த domain. tcontext என்பது target context, அதாவது அது அணுக முயன்ற பொருளின் label. tclass என்பது பொருளின் வகை, இங்கே அது ஒரு file. இவற்றைச் சேர்த்து வாசித்தால்: httpd_t-ல் உள்ள process, default_t என்று label செய்யப்பட்ட file-ஐ வாசிக்க முயன்றது, மேலும் permissive=0 அந்த வேண்டுகோள் வெறும் log-ஆக மட்டும் பதியப்படாமல், உண்மையில் தடுக்கப்பட்டதைக் குறிக்கிறது.
ausearch எதையும் காட்டவில்லை என்றால், audit daemon இயங்காமல் இருக்கலாம். அப்போது மறுப்புகள் kernel ring buffer-ல் பதிவாகும்:
sudo journalctl -k | grep -i avcஇப்போது அந்தப் பதிவை ஒரு வாக்கியமாக மாற்றவும்:
sudo ausearch -m AVC -ts recent | audit2why
sudo journalctl -t setroubleshoot --since today
sudo sealert -a /var/log/audit/audit.logaudit2why அதே பதிவுகளை வாசித்து, அது கண்டறியும் காரணத்தைக் குறிப்பிடும்: அணைக்கப்பட்டிருக்கும் ஒரு boolean, policy-உடன் பொருந்தாத label, அல்லது எந்த விதியும் இல்லாத நிலை. sealert முழு log-ஐயும் ஆய்வு செய்து, ஒவ்வொரு மறுப்பிற்கும் ஒரு பரிந்துரைக்கப்பட்ட command-ஐ அச்சிடும். அந்தப் பரிந்துரையை ஒரு குறிப்பாய் மட்டும் எடுத்துக்கொள்ளவும். software releases-க்கு இடையே அதன் வாசகங்கள் மாறலாம், மேலும் sealert சில நேரங்களில் custom policy module-ஐப் பரிந்துரைக்கும், ஆனால் ஒரு வரியில் label-ஐச் சரிசெய்வதே சரியான தீர்வாக இருக்கலாம்.
தெரிந்துகொள்ள வேண்டிய மற்றொரு விஷயம். Policy-ல் dontaudit விதிகள் உள்ளன, இவை பாதிப்பில்லாத மறுப்புகளை மறைத்துவிடும், எனவே log காலியாக இருந்தாலும் ஒரு நிரல் தவறாகச் செயல்படலாம். ஒரு சோதனைக்காக அவற்றை வெளிப்படுத்த:
sudo semodule -DB
# reproduce the problem, then read the log again
sudo semodule -Bsemanage fcontext மற்றும் restorecon மூலம் தவறான path label-ஐ சரிசெய்தல்
இரண்டு கட்டளைகள் உள்ளன, அவற்றின் வரிசை முக்கியமானது. semanage fcontext -a ஒரு path-க்கான label என்னவாக இருக்க வேண்டும் என்பதைப் பதிவு செய்கிறது. restorecon அந்தப் பதிவு செய்யப்பட்ட default மதிப்பை வட்டில் உள்ள கோப்புகளுக்குப் பயன்படுத்துகிறது.
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 திட்டமிடப்பட்ட relabel விவரங்களை அச்சிடும், ஏனெனில் -n என்பது எந்தச் செயலும் செய்யக்கூடாது என்பதைக் குறிக்கிறது. உண்மையான restorecon கட்டளைக்குப் பிறகு, label httpd_sys_content_t என மாறும், மேலும் service-ஐ restart செய்யாமலேயே 403 பிழை நீங்கிவிடும்.
chcon கட்டளையைச் சோதனைக்கு மட்டுமே பயன்படுத்தவும். chcon -t httpd_sys_content_t index.html label-ஐ நேரடியாக அமைக்கும், ஆனால் அடுத்த restorecon, package update அல்லது முழுமையான relabel செயல்முறை அதை மீண்டும் பழைய நிலைக்குக் கொண்டுவரும், ஏனெனில் அந்த path-க்கான label என்னவாக இருக்க வேண்டும் என்று கொள்கை (policy) இன்னும் பழைய நிலையிலேயே இருக்கும். semanage fcontext மட்டுமே நிரந்தரமான மாற்றத்தை வழங்கும். நீங்கள் பதிவு செய்துள்ள விவரங்களை sudo semanage fcontext -l | grep '^/data' மூலம் பட்டியலிடலாம்.
Service எழுத வேண்டிய கோப்புகளுக்கு வேறு ஒரு type தேவைப்படும். Upload directory அல்லது cache-க்கு httpd_sys_rw_content_t-ஐப் பயன்படுத்தவும், அந்தப் பாதைகளுக்கு மட்டும் இதைக் கட்டுப்படுத்தவும்: read-only தளத்தை writable type-ன் கீழ் வைப்பது, application-க்குத் தேவையானதை விட அதிக அனுமதியை வழங்கிவிடும்.
Label ஏன் தவறாக இருந்தது? பெரும்பாலும் கோப்புகள் வந்த விதமே இதற்குக் காரணம். /root-லிருந்து நகர்த்தப்பட்ட தளம் admin_home_t என்ற label-உடன் வந்து அப்படியே தங்கிவிடுகிறது, ஏனெனில் mv கோப்பின் தற்போதைய label-ஐ அப்படியே வைத்திருக்கும். ஒரு சாதாரண cp புதிய கோப்பிற்கு இலக்கு directory-யின் default label-ஐ வழங்கும், இதுவே பொதுவாகத் தேவைப்படுவது. அதேசமயம் cp -a மற்றும் rsync -X ஆகியவை கோப்புடன் சேர்த்து source label-களையும் நகலெடுக்கும். ஒரு புதிய top-level directory-க்குள் git clone செய்வது default_t-ஐ உருவாக்கும். /usr/share/nginx/html-லிருந்து ஒரு பக்கம் சரியாகத் திறக்கும்போது, உங்கள் சொந்த directory-யிலிருந்து திறக்கத் தவறினால், அதற்கு இதுவே காரணம்.
Boolean மூலம் ஒரு வகை செயல்பாட்டுப் பிழையைச் சரிசெய்தல்
சில தோல்விகள் லேபிள் (label) தொடர்பானவை அல்ல. புதிய Rocky அல்லது AlmaLinux கணினியில் இயங்கும் 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-க்கு வெளிச்செல்லும் network இணைப்புகளை ஏற்படுத்த அனுமதி இல்லை. எனவே, connect() அழைப்பு loopback interface-ஐ அடைவதற்கு முன்பே நிராகரிக்கப்படுகிறது. இந்த முழு செயல்பாட்டையும் ஒரு சுவிட்ச் (switch) கட்டுப்படுத்துகிறது:
getsebool -a | grep httpd_can_network
sudo setsebool -P httpd_can_network_connect on-P என்பது முக்கியமான flag ஆகும்: இது மதிப்பை வட்டில் (disk) சேமிக்கிறது. -P இல்லாமல் மாற்றங்களைச் செய்தால், அடுத்த முறை reboot செய்யும்போது அவை அழிந்துவிடும்; இதனால் கணினி restart ஆகும் வரை மட்டுமே service வேலை செய்யும். semanage boolean -l | grep httpd_can_network_connect மூலம் இதை உறுதிப்படுத்தவும்; இது சேமிக்கப்பட்ட மதிப்புடன் தற்போது இயங்கும் மதிப்பையும் அச்சிடும்.
எப்போதெல்லாம் ஒரு boolean வசதி உள்ளதோ, அப்போதெல்லாம் கைமுறையாக விதிகளை (hand-written rule) எழுதுவதற்குப் பதிலாக அதையே பயன்படுத்தவும். Booleans அந்தந்த distribution கொள்கையுடன் வருவதால், அவை முறையாகப் பராமரிக்கப்பட்டு, ஆவணப்படுத்தப்பட்டிருக்கும்; மேலும் அடுத்ததாகப் பணிபுரிபவர்களுக்கு அவற்றைக் கண்டறிவது எளிது. getsebool -a கட்டளை கணினியில் உள்ள அனைத்து boolean-களையும் பட்டியலிடும்.
ஒரு service-ஐ standard அல்லாத port-ல் இயங்கச் செய்தல்
Ports-க்கும் labels வழங்கப்பட்டுள்ளன. Nginx-ஐ 8081 port-க்கு மாற்றினால், அது தொடங்க மறுக்கும்:
nginx: [emerg] bind() to 0.0.0.0:8081 failed (13: Permission denied)httpd_t, http_port_t என்று பெயரிடப்பட்ட ports-ஐ மட்டுமே bind செய்ய முடியும்; 8081 அவற்றில் ஒன்று அல்ல. எனவே அதைச் சேர்க்கவும்:
sudo semanage port -l | grep -w http_port_t
sudo semanage port -a -t http_port_t -p tcp 8081முதலில் பட்டியலைச் சரிபார்க்கவும். 8008 மற்றும் 8443 உள்ளிட்ட பல high ports ஏற்கனவே அனுமதிக்கப்பட்டுள்ளன; ஏற்கனவே உள்ள ஒன்றை மீண்டும் சேர்த்தால் ValueError: Port tcp/8081 already defined பிழை ஏற்படும். ஒரு port ஏற்கனவே வேறொரு வகையைச் சேர்ந்ததாக இருந்தால், அதைச் சேர்ப்பதற்குப் பதிலாக semanage port -m -t http_port_t -p tcp 8081 மூலம் மாற்றவும்.
மாற்றப்பட்ட SSH port வேலை செய்வதற்கு இதே கட்டளைதான் தேவை. journalctl -u sshd-ல் Bind to port 2222 on 0.0.0.0 failed: Permission denied இருப்பது, 2222 port ssh_port_t-ல் இல்லை என்பதைக் குறிக்கிறது. எனவே, daemon-ஐ restart செய்து உங்கள் session-ஐ முடிக்கும் முன் sudo semanage port -a -t ssh_port_t -p tcp 2222 கட்டளையை இயக்கவும். Red Hat குடும்பத்தைச் சேர்ந்த image-களில் VPS-ல் SSH-ஐ பாதுகாத்தல் குறித்த பொதுவான வழிகாட்டிகளைப் பின்பற்றுபவர்கள் பெரும்பாலும் இந்த முக்கியமான படியைத் தவிர்க்கிறார்கள். SELinux என்பது firewall அல்ல, எனவே port-ஐத் திறக்க வேண்டும்: அதற்கு sudo firewall-cmd --permanent --add-port=8081/tcp && sudo firewall-cmd --reload கட்டளையைப் பயன்படுத்தவும் அல்லது Debian அல்லது Ubuntu image-ல் ufw-ஐப் பயன்படுத்தவும்.
Boolean அல்லது label இல்லாத சூழல்
சாதாரண server-களில் இது அரிதானது, ஆனால் இங்கேயே பயனர்கள் தவறு செய்து பாதிப்புகளை ஏற்படுத்துகின்றனர். log-ல் உள்ள denials-ஐக் கொண்டு audit2allow ஒரு policy module-ஐ உருவாக்க முடியும்:
sudo ausearch -m AVC -ts recent -c nginx | audit2allow -M nginx_local
cat nginx_local.te
sudo semodule -i nginx_local.ppஅதை நிறுவும் முன் nginx_local.te-ஐப் படிக்கவும். பாதுகாப்பாக இருக்க இரண்டு பழக்கங்களைக் கடைப்பிடிக்கவும். நீங்கள் சரிசெய்யும் குறிப்பிட்ட program-ன் denials-ஐ மட்டும் -c மூலம் வடிகட்டவும்; ஏனெனில், ஒரு வார காலத் தொடர்பற்ற denials-ஐ audit2allow-க்கு pipe செய்தால், அவை அனைத்தும் ஒரே நேரத்தில் அனுமதிக்கப்பட்டுவிடும். மேலும், உங்களால் விளக்க முடியாத denial-லிருந்து உருவாக்கப்பட்ட module-ஐ ஒருபோதும் நிறுவ வேண்டாம்: server-ல் உள்ள அனைத்து கோப்புகளையும் httpd_t படிக்க அனுமதிக்கும் ஒரு விதியை உருவாக்குவது எளிது, ஆனால் சில மாதங்களுக்குப் பிறகு அதைக் கண்டறிவது கடினம். sudo semodule -r nginx_local மூலம் ஒரு module-ஐ நீக்கலாம்.
Permissive என்பது ஒரு கண்டறியும் முறை, தீர்வாகாது
sudo setenforce 0
# reproduce the problem once, all the way through
sudo ausearch -m AVC -ts recent
sudo setenforce 1Permissive mode அணுகலை அனுமதித்து, அதை log செய்கிறது. இதன் உண்மையான மதிப்பு முழுமையான தகவல்களைத் தருவதில்தான் உள்ளது. Enforcing முறையில், முதல்முறை அனுமதி மறுக்கப்படும்போதே service நின்றுவிடும்; எனவே நீங்கள் அதைச் சரிசெய்து, restart செய்து, அடுத்த தடையைச் சந்திக்க வேண்டியிருக்கும். Permissive முறையில், service தொடர்ந்து இயங்கும் மற்றும் அனைத்து மறுப்புகளையும் ஒரே முறையில் log-ல் சேகரிக்கும். அதன் பிறகு நீங்கள் மீண்டும் enforcing முறைக்கு மாறி, அனைத்தையும் ஒரே நேரத்தில் சரிசெய்யலாம்.
setenforce என்பது /etc/selinux/config-ஐ மாற்றாது, எனவே reboot செய்த பிறகு கணினி மீண்டும் enforcing முறைக்குத் திரும்பிவிடும். இது ஒரு பாதுகாப்பு வளையம். இதனால்தான் setenforce 0 மூலம் செய்யப்படும் ஒரு "தீர்வு", மிக மோசமான தருணத்தில் மீண்டும் பிரச்சினையாக வெளிப்படுகிறது. நீங்கள் ஒரு service-ல் பணிபுரியும்போது அதற்கு மட்டும் அனுமதி தேவைப்பட்டால், முழு கணினியையும் மாற்றாமல் அந்த domain-ஐ மட்டும் குறிக்கவும்: sudo semanage permissive -a httpd_t மற்ற அனைத்தையும் enforcing நிலையிலேயே வைத்திருக்கும், மேலும் sudo semanage permissive -d httpd_t அதை மீண்டும் பழைய நிலைக்கு மாற்றும்.
SELinux-ஐ முடக்குவதை விட, label-ஐ சரிசெய்வது ஏன் சிறந்தது
/etc/selinux/config-ல் SELINUX=disabled-ஐ அமைப்பது, ஒரு வரியில் label-ஐ சரிசெய்வதற்குப் பதிலாக, server-ன் பாதுகாப்பை நிரந்தரமாகக் குறைக்கும் செயலாகும். ஒரு web application ஊடுருவப்படும்போதுதான் இதன் பாதிப்பு வெளிப்படும். Enforcing நிலையில் இருக்கும்போது, தாக்குதல் நடத்துபவரின் code httpd_t-க்குள் மட்டுமே இயங்கும். எனவே, Unix user-க்கு அனுமதி இருந்தாலும், policy-ன் படி அந்த code-ஆல் web content-ஐ மட்டுமே படிக்க முடியும்; /etc/shadow-ஐப் படிக்கவோ அல்லது systemd unit-ஐ எழுதவோ முடியாது. Policy எதுவும் இல்லையென்றால், அந்த service account-க்கு என்னென்ன அனுமதிகள் உள்ளனவோ, அவை அனைத்தையும் அந்த code பெற்றுவிடும்.
SELinux-ஐ முடக்குவதால் எதிர்காலத்தில் சிக்கல்கள் ஏற்படும். Policy எதுவும் இல்லாதபோது, உருவாக்கப்படும் புதிய கோப்புகளுக்கு label இருக்காது; இதனால் filesystem-ன் நிலை policy-லிருந்து மாறுபடும். மீண்டும் SELinux-ஐச் செயல்படுத்தும்போது, முழுமையாக relabel செய்ய வேண்டியிருக்கும், இல்லையெனில் பல சேவைகள் ஒரே நேரத்தில் செயலிழந்துவிடும்:
sudo fixfiles -F onboot
sudo rebootஇது /.autorelabel-ஐ உருவாக்கி, அடுத்த முறை boot செய்யும்போது ஒவ்வொரு filesystem-ஐயும் relabel செய்யும். பெரிய disk-களில் இதற்கு அதிக நேரம் எடுக்கும் மற்றும் console இயங்காதது போலத் தோன்றும், எனவே காத்திருக்கக்கூடிய நேரத்தில் இதைச் செய்யவும். 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 குடும்பத்தைச் சேர்ந்த host-ல், container process-கள் container_t-ல் இயங்குகின்றன; அவை container_file_t என்று label செய்யப்பட்ட கோப்புகளை மட்டுமே படிக்க முடியும். Host-லிருந்து செய்யப்படும் bind mount, container-க்குள் Permission denied பிழையைத் தருகிறது, ஆனால் host-ல் ls -l சரியாகவே உள்ளது. :Z suffix, அந்த mount-ஐ மீண்டும் label செய்யுமாறு runtime-க்கு அறிவுறுத்துகிறது:
docker run -d -v /data/appdata:/var/lib/app:Z myimage:Z அந்த directory-ஐ இந்த குறிப்பிட்ட container-க்காக மட்டும் label செய்கிறது. :z அதை container-களுக்கு இடையே பகிர்வதற்காக label செய்கிறது. பிற சேவைகள் பயன்படுத்தும் ஒரு directory-ஐ :Z மூலம் குறிப்பிட்டால், அது அந்த directory-ஐ recursively மீண்டும் label செய்துவிடும்; இதனால் அந்தச் சேவைகள் பாதிக்கப்படும். எனவே, container-களுக்குத் தனித்தனி path-களை வழங்கவும். இந்த அமைப்பின் பிற அம்சங்கள் அனைத்தும், VPS-ல் Docker-ஐ இயக்குதல் பகுதியில் விவரிக்கப்பட்டுள்ளபடி, மற்ற image-களைப் போலவே இருக்கும்.
Ubuntu மற்றும் Debian-ல் AppArmor உள்ளது
ஒரே பணி, ஆனால் வெவ்வேறு வடிவமைப்பு. AppArmor ஒரு நிரலை அதன் executable கோப்பின் பாதையைக் கொண்டு கட்டுப்படுத்துகிறது. இது /etc/apparmor.d/-ன் கீழ் உள்ள profile-களைப் பயன்படுத்துகிறது; வட்டில் உள்ள கோப்புகளை label செய்வதில்லை. இதில் label செய்ய எதுவும் இல்லை, 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" எனத் தோன்றும். பணிமுறை ஒரே மாதிரியானது: மறுப்பைப் படியுங்கள், profile-ஐக் கண்டறியுங்கள், விதியை மாற்றியமைக்கவும். sudo apt install apparmor-utils உங்களுக்கு aa-complain (ஒரு profile-க்கு மட்டும் permissive mode) மற்றும் அதை மீண்டும் பழைய நிலைக்கு மாற்ற aa-enforce ஆகியவற்றை வழங்குகிறது. Ubuntu தேர்ந்தெடுக்கப்பட்ட சில packaged services-ஐ மட்டுமே கட்டுப்படுத்துகிறது, மற்றவற்றை unconfined நிலையில் விடுகிறது. எனவே, எதைச் செய்ய வேண்டும் என்று ஊகிப்பதற்குப் பதிலாக, உண்மையில் எது செயல்பாட்டில் உள்ளது என்பதைப் பார்க்க aa-status-ஐப் படிக்கவும்.
இரண்டு அமைப்புகளிலும் ஒரு பழக்கம் பொதுவானது. ஒரு service சரியாகத் தோன்றும் ஒன்றின் மீது Permission denied என்று பிழையைக் காட்டினால், permissions-ஐ மாற்றுவதற்கு முன்பு security log-ஐப் படியுங்கள். கோப்பின் bits-ல் பிரச்சினை இருப்பது அரிது.
FAQ
கோப்பு அனுமதிகள் சரியாக இருந்தும் nginx ஏன் 403 பிழையைத் தருகிறது?
ஏனெனில், கோப்பு அனுமதிகள் (permission bits) அல்ல, SELinux தான் வாசிப்பைத் தடுக்கிறது. Web server httpd_t டொமைனில் இயங்குகிறது; இது web content-க்காக லேபிளிடப்பட்ட கோப்புகளை மட்டுமே வாசிக்க முடியும். எனவே, default_t அல்லது admin_home_t என லேபிளிடப்பட்ட கோப்புகளை அது நிராகரிக்கும், nginx-ஆல் எதையும் வழங்க முடியாது. இதை sudo ausearch -m AVC -ts recent மூலம் உறுதிப்படுத்தவும்; இது scontext முடிவில் httpd_t இருப்பதையும், tcontext தவறான வகையைக் கொண்டிருப்பதையும் காட்டும். பிறகு, சரியான லேபிளைக் குறித்து வைத்து அதைச் செயல்படுத்தவும்: sudo semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?" மற்றும் அதைத் தொடர்ந்து sudo restorecon -Rv /data/www.
ஒரு service-ஐ வேலை செய்ய வைக்க setenforce 0-ஐப் பயன்படுத்துவது பாதுகாப்பானதா?
setenforce 0 என்பது ஒரு கண்டறியும் படிநிலை, தீர்வு அல்ல. சிக்கலை ஒருமுறை மீண்டும் உருவாக்கி, அனைத்து நிராகரிப்புகளையும் (denials) ஒரே நேரத்தில் log-ல் சேகரிக்க இதைப் பயன்படுத்தவும். அவற்றை sudo ausearch -m AVC -ts recent மூலம் வாசித்து, பின் sudo setenforce 1-ஐ இயக்கி காரணங்களைச் சரிசெய்யவும். ஒரு server-ஐ permissive நிலையில் விட்டால், அது அனைத்து நிராகரிப்புகளையும் log செய்யும், ஆனால் எதையும் தடுக்காது; இதனால் தேவையற்ற தரவுகள் சேரும், பாதுகாப்பு குறையும். நீங்கள் பணிபுரியும் போது ஒரு service-க்கு மட்டும் அனுமதி தேவைப்பட்டால், sudo semanage permissive -a httpd_t-ஐப் பயன்படுத்தவும், அப்போதுதான் machine-ன் மற்ற பகுதிகள் enforcing நிலையிலேயே இருக்கும்.
SELinux enforcing நிலையில் இருக்கும்போது, ஒரு service-ஐ standard அல்லாத port-ல் எப்படி இயக்குவது?
அந்த service எந்த வகையைச் (type) சார்ந்ததோ, அந்த வகையுடன் port-ஐச் சேர்க்க வேண்டும். 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 மூலம் சரிபார்க்கவும், ஏனெனில் ஏற்கனவே பட்டியலிடப்பட்ட port-ஐச் சேர்க்க முயன்றால் ValueError: Port tcp/8081 already defined பிழை ஏற்படும். இந்தப் படிநிலை இல்லையெனில், வேறு எந்த process-ம் அந்த port-ஐப் பயன்படுத்தாதபோதும், startup-ல் daemon bind() ... Permission denied பிழையுடன் வெளியேறிவிடும்.
Ubuntu-வில் SELinux உள்ளதா?
இல்லை. Ubuntu மற்றும் Debian-ல் AppArmor உள்ளது. இது கோப்புகளின் லேபிள்களை விட, executable-ன் பாதையுடன் இணைக்கப்பட்ட profile-ஐ அமல்படுத்துகிறது. இதை sudo aa-status மூலம் சரிபார்த்து, sudo journalctl -k-ல் apparmor="DENIED" வரிகளைத் தேடவும். Ubuntu தேர்ந்தெடுக்கப்பட்ட சில packaged services-ஐ மட்டுமே கட்டுப்படுத்துகிறது, எனவே பல நிரல்கள் இயல்பாகவே unconfined நிலையில் இயங்குகின்றன. Rocky Linux மற்றும் AlmaLinux ஆகியவற்றில் SELinux இயல்பாகவே enforcing நிலையில் இருக்கும், Fedora மற்றும் RHEL-லும் இது பொருந்தும்.