48

My system is running CentOS 6.4 with apache2.2.15. SElinux is enforcing and I'm trying to connect to a local instance of redis through my python/wsgi app. I get Error 13, Permission denied. I could fix this via the command:

setsebool -P httpd_can_network_connect

However, I don't exactly want httpd to be able to connect to all tcp ports. How can I specify which ports/networks httpd is allowed to connect to? If I could make a module to allow httpd to connect to port 6379 ( redis ) or any tcp on 127.0.0.1, that would be preferable. Not sure why my paranoia is so strong on this, but hey...

Anyone know?

savagecitizen
  • 481
  • 1
  • 4
  • 3
  • Would it not be better to force it to go out through a proxy? That way you can a) have better control over what can be accessed b) have better auditing over what happened and when. – Cameron Kerr May 13 '15 at 09:56

3 Answers3

61

By default, the SELinux policy will only allow services access to recognized ports associated with those services:

# semanage port -l | egrep '(^http_port_t|6379)'
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
# curl http://localhost/redis.php
Cannot connect to redis server.

- add Redis port (6379) to SELinux policy

# semanage port -a -t http_port_t -p tcp 6379
# semanage port -l | egrep '(^http_port_t|6379)'
http_port_t                    tcp      6379, 80, 81, 443, 488, 8008, 8009, 8443, 9000
# curl http://localhost/redis.php
Connected successfully.

You can also install setroubleshoot-server RPM and run: sealert -a /var/log/audit/audit.log - it will give you a nice report with useful suggestions (including command above).

PHP script to test connection:

# cat redis.php 
<?php

$redis=new Redis();
$connected= $redis->connect('127.0.0.1', 6379);

if(!$connected) {
        die( "Cannot connect to redis server.\n" );
}

echo "Connected successfully.\n";

?>
HTF
  • 3,050
  • 14
  • 49
  • 78
  • 3
    I had the problem on Fedora 23 to send e-mail (by connecting to 127.0.0.1 on port 25) from a perl script (using Net::SMTP) started from httpd. "Permission for httpd to connect to port 25" is not what one is looking for in that case. Indeed adding port 25 to SELinux type `http_port_t` fails because port 25 is already used (for another SELinux type): `ValueError: Port tcp/25 already defined`. The correct way to allow httpd to connect to port 25 is to set the corresponding SELinux policy boolean on: `setsebool -P httpd_can_sendmail on` (see `getseebool -a`). (continued in part 2) – David Tonhofer Jan 03 '16 at 18:10
  • 1
    (continued from part 1) But if you want to send from a perl script, you have to explicitly create a SELinux module that allows that: `sealert -b; sealert -a /var/log/audit/audit.log; grep perl /var/log/audit/audit.log | audit2allow -M mypol; semodule -v -i mypol.pp`. Then it works! – David Tonhofer Jan 03 '16 at 18:11
  • @DavidTonhofer Minor typo in the `getsebool -a` command (one fewer `e`). – davidjb Jun 22 '18 at 00:33
  • 1
    @DavidTonhofer you don't have to create a new policy for existing port, you can modify it instead: `semanage port -m -t http_port_t -p tcp 25`, see `semanage port --help` – HTF Jun 22 '18 at 05:54
  • For zabbix, there already is a specual boolean on CentOS 7.5: `setsebool -P httpd_can_connect_zabbix true` – David Tonhofer Feb 21 '19 at 17:49
  • Thanks. This was helpful in adding another port for postfix to listen to: semanage port -a -t smtp_port_t -p tcp 2525 – Jimbo Nov 11 '21 at 20:41
  • How to restrict this change only to one specific user? I have different apache users for each website and don't want to open Redis port for each user. – Tristan CHARBONNIER Feb 28 '22 at 05:46
21

You may need to use

semanage port -m -t http_port_t -p tcp 6379

If semanage is missing then add the package policycoreutils-python

yum install policycoreutils-python
Tom Hallam
  • 385
  • 3
  • 6
3

You could temporary put selinux in permissive mode and let httpd connect to redis, then generate and build a custom policy module using audit2allow

A. M.
  • 39
  • 2