When running Apache (httpd) under enforcing SELinux on CentOS/RHEL systems, you might encounter "Error 13: Permission denied" when your web applications attempt to make outbound network connections. While disabling SELinux entirely or using setsebool -P httpd_can_network_connect=1
would work, these solutions create unnecessary security risks by granting blanket network access.
SELinux implements Type Enforcement (TE) rules that control which domains (like httpd_t) can access which ports. To view current port assignments:
semanage port -l | grep http
# Output typically shows:
# http_port_t tcp 80, 443, 8080, 8009
For Redis running on default port 6379:
semanage port -a -t http_port_t -p tcp 6379
# Verify the change:
semanage port -l | grep http_port_t
For more granular control when you can't modify existing port types:
# 1. Generate policy module template
audit2allow -a -M httpd_redis
# Review the generated httpd_redis.te file
# 2. Compile and load the module
make -f /usr/share/selinux/devel/Makefile httpd_redis.pp
semodule -i httpd_redis.pp
To restrict connections to only localhost (127.0.0.1):
# 1. Create a custom boolean
semanage boolean --modify --on --name httpd_connect_local
# 2. Create corresponding policy module
# (Example .te file contents)
module httpd_local 1.0;
require {
type httpd_t;
class tcp_socket name_connect;
}
allow httpd_t self:tcp_socket name_connect;
corenet_tcp_connect_http_port(httpd_t)
After making changes:
# Check SELinux denials
ausearch -m avc -ts recent
# Test connection from Apache
curl -v localhost:6379
# Temporary logging for debugging
semanage permissive -a httpd_t
- Always test in permissive mode first:
setenforce 0
- Document all SELinux modifications for audit purposes
- Consider creating custom SELinux types for sensitive services
- Regularly review
/var/log/audit/audit.log
for new denials
When running a Python/WSGI application on CentOS 6.4 with Apache 2.2.15 under enforcing SELinux, you might encounter "Error 13: Permission denied" when trying to connect to Redis (port 6379) or other specific services. While the quick fix is:
setsebool -P httpd_can_network_connect=1
This grants Apache permission to connect to all network ports, which isn't ideal for security-conscious environments.
SELinux provides finer-grained control through port labeling. First, check current port assignments:
semanage port -l | grep http_port_t
To allow HTTPD to connect specifically to Redis (6379):
semanage port -a -t http_port_t -p tcp 6379
For connections only to 127.0.0.1, create a custom SELinux policy module:
cat << EOF > local_httpd_redis.te
module local_httpd_redis 1.0;
require {
type httpd_t;
type unreserved_port_t;
class tcp_socket name_connect;
}
allow httpd_t unreserved_port_t:tcp_socket name_connect;
EOF
checkmodule -M -m -o local_httpd_redis.mod local_httpd_redis.te
semodule_package -o local_httpd_redis.pp -m local_httpd_redis.mod
semodule -i local_httpd_redis.pp
After making changes, verify with:
sealert -a /var/log/audit/audit.log
And test your connection. If issues persist, temporarily set SELinux to permissive mode for debugging:
setenforce 0
Remember that:
- Port 6379 should still be firewalled appropriately
- Redis should be configured with authentication
- Consider using Unix domain sockets for local connections