{"id":610,"date":"2016-01-08T05:06:25","date_gmt":"2016-01-08T13:06:25","guid":{"rendered":"https:\/\/cloudinsidr.com\/content\/?p=610"},"modified":"2018-06-19T09:31:58","modified_gmt":"2018-06-19T17:31:58","slug":"troubleshooting-php-7-tcp-sockets-with-selinux-on-centos-7-rhelfedora","status":"publish","type":"post","link":"https:\/\/www.cloudinsidr.com\/content\/troubleshooting-php-7-tcp-sockets-with-selinux-on-centos-7-rhelfedora\/","title":{"rendered":"Troubleshooting PHP 7 and NGINX when using TCP sockets with SELinux on Fedora\/RHEL\/CentOS"},"content":{"rendered":"<p>If you are having trouble getting your web server to work or starting services on the system, SELinux could be at fault.<\/p>\n<p><!--more--><\/p>\n<h2>Diagnose problems caused by SELinux<\/h2>\n<p>Two major factors can contribute to a service not functioning properly:<\/p>\n<ul>\n<li>inappropriate\u00a0SELinux security labels on files and directories,<\/li>\n<li>inappropriate\u00a0SELinux rules applied to Unix system resources such as TCP sockets.<\/li>\n<\/ul>\n<h3>Get status of the malfunctioning service<\/h3>\n<p>First you need to get the status output for the malfunctioning service (or look up the logs). For example, for PHP 7 that delivers a 404 error in NGINX:<\/p>\n<pre class=\"\"># systemctl status -l php70-php-fpm.service\r\n\u25cf php70-php-fpm.service - The PHP FastCGI Process Manager\r\n Loaded: loaded (\/usr\/lib\/systemd\/system\/php70-php-fpm.service; enabled; vendor preset: disabled)\r\n Active: failed (Result: exit-code) since Fri 2018-01-08 12:03:16 UTC; 5min ago\r\n Process: 13468 ExecStart=\/opt\/remi\/php70\/root\/usr\/sbin\/php-fpm --nodaemonize (code=exited, status=78)\r\n Main PID: 13468 (code=exited, status=78)\r\nJan 08 12:03:18 ip-16-0-0-40 systemd[1]: Starting The PHP FastCGI Process Manager...\r\nJan 08 12:03:18 ip-16-0-0-40 php-fpm[13468]: [08-Jan-2018 12:03:16] ERROR: unable to bind listening socket for address '127.0.0.1:9002': Permission denied (13)\r\nJan 08 12:03:18 ip-16-0-0-40 php-fpm[13468]: [08-Jan-2018 12:03:16] ERROR: FPM initialization failed\r\nJan 08 12:03:18 ip-16-0-0-40 systemd[1]: php70-php-fpm.service: main process exited, code=exited, status=78\/n\/a\r\nJan 08 12:03:18 ip-16-0-0-40 systemd[1]: Failed to start The PHP FastCGI Process Manager.\r\nJan 08 12:03:18 ip-16-0-0-40 systemd[1]: Unit php70-php-fpm.service entered failed state.\r\nJan 08 12:03:18 ip-16-0-0-40 systemd[1]: php70-php-fpm.service failed.<\/pre>\n<p>The system in the above example is\u00a0unable to bind the TCP\u00a0listening socket, as evidenced by this line:<\/p>\n<pre class=\"\">ERROR: unable to bind listening socket for address '127.0.0.1:9002': Permission denied (13)<\/pre>\n<h3>Correct SELinux security labels on the file system<\/h3>\n<p>Navigate to the directory containing the configuration files:<\/p>\n<pre class=\"\">cd \/etc\/opt\/remi\/php70\/php-fpm.d<\/pre>\n<p>View SELinux labels:<\/p>\n<pre class=\"\"># ls -laZ\r\ndrwxr-xr-x. root root system_u:object_r:etc_t:s0 .\r\ndrwxr-xr-x. root root system_u:object_r:etc_t:s0 ..\r\n-rw-r--r--. root root system_u:object_r:etc_t:s0 www.conf\r\n-rw-r--r--. root root unconfined_u:object_r:etc_t:s0 www.website1.tld.conf<\/pre>\n<p>Fix the label on the configuration files of php-fpm pools:<\/p>\n<pre class=\"\">chcon -R system_u:object_r:etc_t:s0 www.website1.tld.conf<\/pre>\n<h3>Troubleshooting access to TCP sockets: build an SELinux module to use TCP sockets<\/h3>\n<p>To figure out the changes that are required\u00a0for SELinux\u00a0to permit legitimate activities of a\u00a0service (such as php-fpm or nginx), switch SELinux to permissive mode and\u00a0build the module it needs\u00a0using\u00a0<strong>audit2allow<\/strong>, a\u00a0utility\u00a0that can generate SELinux allow\/dontaudit rules from logs of denied operations (it is contained in <strong>policycoreutils-devel<\/strong>).\u00a0Here&#8217;s how to do it.<\/p>\n<h4>Step 1. Switch\u00a0SELinux to permissive<\/h4>\n<p>Verify if SELinux is enforcing rules\u00a0using:<\/p>\n<pre class=\"\"># getenforce<\/pre>\n<p>If it is set to enforcing, switch SELinux to the permissive mode using the command:<\/p>\n<pre class=\"\"># setenforce 0<\/pre>\n<p>In this mode of operation, SELinux won&#8217;t be enforcing its rules, but it will log information about activities\u00a0it would have prevented if it had been enforcing existing rules.<\/p>\n<h4>Step 2. Start the service that failed to load in the SELinux enforcing mode<\/h4>\n<p>If the service wasn&#8217;t able to run at all\u00a0because of SELinux,\u00a0start\u00a0it:<\/p>\n<pre class=\"\"># service php70-php-fpm restart\r\n Redirecting to \/bin\/systemctl restart php70-php-fpm.service<\/pre>\n<p>Next, try to trigger the error you saw before. For example, visit the site in a web browser.<\/p>\n<h4>Step 3. Inspect log output of SELinux generated for the service in permissive mode<\/h4>\n<p>Check the audit log:<\/p>\n<pre>tail \/var\/log\/audit\/audit.log | more<\/pre>\n<p>You may find messages like this one that reports that php-fpm was denied access to a TCP socket:<\/p>\n<pre>type=AVC msg=audit(1529375627.092:172): avc: denied { name_bind } for pid=1822 comm=\"php-fpm\" src=9009 scontext=system_u:system_r:httpd_t: s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=1<\/pre>\n<p>Based on the output of tail, you know what to look for when building your SELinux module.<\/p>\n<h4>Step 4. Pipe relevant messages to audit2allow<\/h4>\n<p>Pipe the relevant output of the SELinux audit.log for the service in question to a temporary file for further inspection:<\/p>\n<pre>grep php-fpm \/var\/log\/audit\/audit.log | audit2allow -M phpfpm &gt; phpfpmlocal.tmp<\/pre>\n<p>Inspect the file you created (phpfpmlocal.tmp):<\/p>\n<pre class=\"\"># cat phpfpmlocal.tmp\r\n\r\nmodule phpfpm 1.0;\r\n\r\nrequire {\r\n type tor_port_t;\r\n type unreserved_port_t;\r\n type hugetlbfs_t;\r\n type httpd_t;\r\n type httpd_sys_content_t;\r\n class process execmem;\r\n class tcp_socket name_bind;\r\n class dir write;\r\n class file { write append };\r\n}\r\n\r\n#============= httpd_t ==============\r\n#!!!! This avc can be allowed using the boolean 'httpd_unified'\r\nallow httpd_t httpd_sys_content_t:dir write;\r\n\r\n#!!!! This avc can be allowed using the boolean 'httpd_unified'\r\nallow httpd_t httpd_sys_content_t:file append;\r\nallow httpd_t hugetlbfs_t:file write;\r\n\r\n#!!!! This avc can be allowed using the boolean 'httpd_execmem'\r\nallow httpd_t self:process execmem;\r\nallow httpd_t tor_port_t:tcp_socket name_bind;\r\n\r\n#!!!! This avc can be allowed using the boolean 'nis_enabled'\r\nallow httpd_t unreserved_port_t:tcp_socket name_bind;<\/pre>\n<p>Make any edits to the require directive above that seem necessary.<\/p>\n<p>You have two options at this point. You can either build and activate a SELinux module (Step 5, option 2) or enable the corresponding booleans (Step 5 option 1).<\/p>\n<h4>Step 5, option 1. Set SELinux booleans<\/h4>\n<p>To\u00a0<a href=\"https:\/\/access.redhat.com\/documentation\/en-us\/red_hat_enterprise_linux\/6\/html\/security-enhanced_linux\/sect-security-enhanced_linux-booleans-configuring_booleans\" target=\"_blank\" rel=\"noopener\">set the corresponding boolean<\/a> (following the directions from Step 4), for example:<\/p>\n<pre>semanage boolean -m --on nis_enabled<\/pre>\n<p>Here, nis_enabled is the boolean that was supplied in the output of audit2allow in Step 4 above. The change persists across reboots.<\/p>\n<h4>Step 5, option 2. Build and enable the SELinux module<\/h4>\n<p>Re-run audit2allow to build the module:<\/p>\n<pre class=\"\">grep php-fpm \/var\/log\/audit\/audit.log | audit2allow -M phpfpmlocal\r\n******************** IMPORTANT ***********************\r\nTo make this policy package active, execute:\r\nsemodule -i phpfpmlocal.pp<\/pre>\n<p>(If there is no policy to be activated based on the audit log snippets you supplied in Step 4., audit2allow will fail to create the module and then the command semodule will also fail.)<\/p>\n<p>Activate the module:<\/p>\n<pre class=\"\">semodule -i phpfpmlocal.pp<\/pre>\n<p>(Now you may remove the three phpfpmlocal.* files that were created as the system no longer needs them.)<\/p>\n<h4>Step 6. Reactivate SELinux enforcing mode and restart the service<\/h4>\n<p>Set enforce back on:<\/p>\n<pre class=\"\">setenforce 1<\/pre>\n<p>Verify that SELinux is enforcing:<\/p>\n<pre class=\"\"># getenforce\r\n Enforcing<\/pre>\n<p>Restart the service for which you fixed the rules:<\/p>\n<pre class=\"\">systemctl restart\u00a0nginx php-fpm<\/pre>\n<p>Verify that everything is working as it should for the service:<\/p>\n<pre class=\"\">systemctl status -l php-fpm.service<\/pre>\n<p>You have granted\u00a0php-fpm access\u00a0to a TCP socket so it happily starts without complaints. However,\u00a0NGINX\u00a0may still\u00a0keep giving\u00a0you 404 errors for lack of access to the TCP socket.<\/p>\n<p>A\u00a0TCP socket allows two (or more) services to communicate with one another. For this communication to work, both services need unhindered access to the socket. As a result, you need to repeat the above procedure for NGINX.<\/p>\n<h3>Create a custom\u00a0SELinux module for NGINX\u00a0to use a TCP socket<\/h3>\n<p>Repeat the steps required for SELinux to grant NGINX access tot he TCP socket that PHP-FPM is listening on.<\/p>\n<h4>Step 1. Pipe audit.log messages referring to NGINX to audit2allow<\/h4>\n<p>Use the\u00a0audit2allow utility to view relevant messages in the logs:<\/p>\n<pre class=\"\">grep nginx \/var\/log\/audit\/audit.log | audit2allow<\/pre>\n<p>showing for example this output:<\/p>\n<pre class=\"\">#============= httpd_t ==============<\/pre>\n<pre>#!!!! This avc can be allowed using one of the these booleans:\r\n# nis_enabled, httpd_can_network_connect\r\nallow httpd_t unreserved_port_t:tcp_socket name_connect;<\/pre>\n<p>Pipe relevant SELinux\u00a0AVC messages to audit2allow to create the SELinux module:<\/p>\n<pre class=\"\">grep nginx \/var\/log\/audit\/audit.log | audit2allow -m nginx<\/pre>\n<p>The output may look like this:<\/p>\n<pre class=\"\">module nginx 1.0;\r\n\r\nrequire {\r\n type httpd_t;\r\n type unreserved_port_t;\r\n class tcp_socket name_connect;\r\n}\r\n\r\n#============= httpd_t ==============\r\n\r\n#!!!! This avc can be allowed using one of the these booleans:\r\n# nis_enabled, httpd_can_network_connect\r\nallow httpd_t unreserved_port_t:tcp_socket name_connect;<\/pre>\n<p>Generate a local nginx Type Enforcement policy file (nginx.tmp):<\/p>\n<pre class=\"\">grep nginx \/var\/log\/audit\/audit.log | audit2allow -m nginx &gt; nginx.tmp\r\ncat nginx.tmp<\/pre>\n<p>Use audit2allow to create\u00a0a custom policy module which\u00a0allows NGINX access to\u00a0the TCP socket:<\/p>\n<pre class=\"\">grep nginx \/var\/log\/audit\/audit.log | audit2allow -M nginx<\/pre>\n<p>To load the\u00a0policy package into the kernel, execute:<\/p>\n<pre class=\"\">semodule -i nginx.pp<\/pre>\n<p>Wrap it up by switching\u00a0SELinux back to its enforcing mode:<\/p>\n<pre class=\"\">setenforce 1<\/pre>\n<p>Restart nginx.<\/p>\n<p>Verify that SELinux is enforcing rules:<\/p>\n<pre class=\"\"># getenforce\r\n Enforcing<\/pre>\n<p>List loaded modules<\/p>\n<pre class=\"\">semodule -l<\/pre>\n<p>Congratulations, you are done.<\/p>\n<p><script type=\"text\/javascript\">\namzn_assoc_tracking_id = \"digitalcom02a-20\";\namzn_assoc_ad_mode = \"manual\";\namzn_assoc_ad_type = \"smart\";\namzn_assoc_marketplace = \"amazon\";\namzn_assoc_region = \"US\";\namzn_assoc_design = \"enhanced_links\";\namzn_assoc_asins = \"1787126951\";\namzn_assoc_placement = \"adunit\";\namzn_assoc_linkid = \"57c6f655b04f04a0576424c3430067c4\";\n<\/script><br \/>\n<script src=\"\/\/z-na.amazon-adsystem.com\/widgets\/onejs?MarketPlace=US\"><\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you are having trouble getting your web server to work or starting services on the system, SELinux could be at fault.<\/p>\n","protected":false},"author":101011,"featured_media":76,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","footnotes":""},"categories":[16,17,33,6],"tags":[50,27,70,93],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v14.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Troubleshooting PHP 7 and NGINX when using TCP sockets with SELinux on Fedora\/RHEL\/CentOS - CloudInsidr<\/title>\n<meta name=\"robots\" content=\"index, follow\" \/>\n<meta name=\"googlebot\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<meta name=\"bingbot\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.cloudinsidr.com\/content\/troubleshooting-php-7-tcp-sockets-with-selinux-on-centos-7-rhelfedora\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Troubleshooting PHP 7 and NGINX when using TCP sockets with SELinux on Fedora\/RHEL\/CentOS - CloudInsidr\" \/>\n<meta property=\"og:description\" content=\"If you are having trouble getting your web server to work or starting services on the system, SELinux could be at fault.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.cloudinsidr.com\/content\/troubleshooting-php-7-tcp-sockets-with-selinux-on-centos-7-rhelfedora\/\" \/>\n<meta property=\"og:site_name\" content=\"CloudInsidr\" \/>\n<meta property=\"article:published_time\" content=\"2016-01-08T13:06:25+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-06-19T17:31:58+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.cloudinsidr.com\/content\/wp-content\/uploads\/2015\/11\/cloudinsidr_logo_900px-wide.png\" \/>\n\t<meta property=\"og:image:width\" content=\"900\" \/>\n\t<meta property=\"og:image:height\" content=\"326\" \/>\n<meta name=\"twitter:card\" content=\"summary\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.cloudinsidr.com\/content\/#website\",\"url\":\"https:\/\/www.cloudinsidr.com\/content\/\",\"name\":\"CloudInsidr\",\"description\":\"Cyber security, infotech\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/www.cloudinsidr.com\/content\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.cloudinsidr.com\/content\/troubleshooting-php-7-tcp-sockets-with-selinux-on-centos-7-rhelfedora\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/www.cloudinsidr.com\/content\/wp-content\/uploads\/2015\/11\/cloudinsidr_logo_900px-wide.png\",\"width\":900,\"height\":326,\"caption\":\"cloudinsidr.com logo (900px wide)\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.cloudinsidr.com\/content\/troubleshooting-php-7-tcp-sockets-with-selinux-on-centos-7-rhelfedora\/#webpage\",\"url\":\"https:\/\/www.cloudinsidr.com\/content\/troubleshooting-php-7-tcp-sockets-with-selinux-on-centos-7-rhelfedora\/\",\"name\":\"Troubleshooting PHP 7 and NGINX when using TCP sockets with SELinux on Fedora\/RHEL\/CentOS - CloudInsidr\",\"isPartOf\":{\"@id\":\"https:\/\/www.cloudinsidr.com\/content\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.cloudinsidr.com\/content\/troubleshooting-php-7-tcp-sockets-with-selinux-on-centos-7-rhelfedora\/#primaryimage\"},\"datePublished\":\"2016-01-08T13:06:25+00:00\",\"dateModified\":\"2018-06-19T17:31:58+00:00\",\"author\":{\"@id\":\"https:\/\/www.cloudinsidr.com\/content\/#\/schema\/person\/21ce63bea726ea64da1beed97e63ba84\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.cloudinsidr.com\/content\/troubleshooting-php-7-tcp-sockets-with-selinux-on-centos-7-rhelfedora\/\"]}]},{\"@type\":[\"Person\"],\"@id\":\"https:\/\/www.cloudinsidr.com\/content\/#\/schema\/person\/21ce63bea726ea64da1beed97e63ba84\",\"name\":\"Anna E Kobylinska\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.cloudinsidr.com\/content\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/7a3e9bd152f9d5cd41bf2b92df649857?s=96&d=mm&r=g\",\"caption\":\"Anna E Kobylinska\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/www.cloudinsidr.com\/content\/wp-json\/wp\/v2\/posts\/610"}],"collection":[{"href":"https:\/\/www.cloudinsidr.com\/content\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudinsidr.com\/content\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudinsidr.com\/content\/wp-json\/wp\/v2\/users\/101011"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudinsidr.com\/content\/wp-json\/wp\/v2\/comments?post=610"}],"version-history":[{"count":24,"href":"https:\/\/www.cloudinsidr.com\/content\/wp-json\/wp\/v2\/posts\/610\/revisions"}],"predecessor-version":[{"id":2320,"href":"https:\/\/www.cloudinsidr.com\/content\/wp-json\/wp\/v2\/posts\/610\/revisions\/2320"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudinsidr.com\/content\/wp-json\/wp\/v2\/media\/76"}],"wp:attachment":[{"href":"https:\/\/www.cloudinsidr.com\/content\/wp-json\/wp\/v2\/media?parent=610"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudinsidr.com\/content\/wp-json\/wp\/v2\/categories?post=610"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudinsidr.com\/content\/wp-json\/wp\/v2\/tags?post=610"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}