A strange error was noticed when migrating a client site to a CentOS server: the client's PHP scripts could no longer connect to their (remotely hosted) database server:
[Tue Feb 23 23:05:36 2010] [error] [client ...] PHP Warning: mysql_pconnect() [<a href='function.mysql-pconnect'>function.mysql-pconnect</a>]: Can't connect to MySQL server on 'remotehost' (13) in ....
The problem, it seems, was due to the selinux mode being enforciny, and having a policy preventing Apache scripts from making remote connections - a very laudable policy. However, remote DB connections is sufficiently often requested to make this something we wanted to allow, so we needed a new policy to explicitly enable that.
A new policy can easily be created by simply taking the "denied" entry from the audit log and converting it into a new module:
grep httpd /var/log/audit/audit.log | grep 3306
Shows entries such as this:
type=AVC msg=audit(1266966336.533:13939026): avc: denied { name_connect } for pid=9404 comm="httpd" dest=3306 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:mysqld_port_t:s0 tclass=tcp_socket
Luckily, selinux provides a handy little command to convert such entries into allowed actions:
grep httpd /var/log/audit/audit.log | grep 3306 | audit2allow -M httpdmysql
This will create a module in the current directory, which can then be installed using semodule:
semodule -i httpdmysql.pp
After which we are able to connect to remote MySQL databases - listening on the default MySQL port - with the rest of our selinux rules intact.