SELinux is a recently added security system that’s installed by default with CentOS 5.1 (and Red Hat Enterprise Linux 5, and others). Since it’s newer than the classic “Discretionary Access Control” Unix security model, it’s not nearly as well documented, and unfamiliar to many. I had never even heard of it until this week.
After a lot of reading about it, and debating disabling it entirely, I figured out how to do some minor SELinux customization to fit my needs for a MySQL database server. Hopefully this will help folks who are in a similar situation.
Fortunately, although SELinux is sophisticated, it’s not too obtrusive as implemented in CentOS 5.1. In configuring it, Red Hat has picked an admirable position somewhere between ironclad security with a huge administrative burden, and toothless security that is easy to use because it isn’t doing anything to protect you. This is important, because if the configuration process were too odious from the point of view of a typical junior sysadmin, it’s very likely that people would get in the habit of just turning it off entirely. As it is, SELinux on RHEL 5 / CentOS 5.1 is now becoming part of the landscape of what a modern Linux looks like; based on what I’ve read on relevant forums lately, admins are taking the time to try and customize its default configuration to their needs (with some success) rather than just turning it off.
The nicely balanced default configuration that Red Hat has chosen is called the Targeted Policy, which means that if the SELinux configuration files know about a specific daemon, then it will be subject to specific rules; otherwise, the classic Unix security model applies. So if you stay with the standard configuration of those targeted daemons, SELinux is providing an additional level of security containment around them, and as long as it does what it’s supposed to, you’ll never notice it.
In my case, I’m running MySQL and OpenSSH, and have configured them to listen on nonstandard ports. SSH is not targeted, so this was trivial to do. MySQL is targeted, so it didn’t work right away.
Specifically, MySQL wouldn’t start, and in /var/log/messages I saw something like this:
1 2 3 |
kernel: audit(1206710000.178:12): avc: denied { name_bind } \ for pid=8591 comm="mysqld" src=1234 scontext=user_u:system_r:mysqld_t:s0 \ tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket |
In plain English, “I denied process 8591’s request to bind to port 1234”. So SELinux needs to be told that MySQL should be allowed to bind to port 1234.
Here’s what I had to do: (assuming a mysqld port number of 1234, and that the iptables firewall is already adjusted for this)
1 |
sudo /usr/sbin/semanage port -a -t mysqld_port_t -p tcp 1234 |
This means “Change the SELinux policy for ports by adding one, of mysqld_port_t type, protocol TCP, port number 1234.”
Now you should be able to see the standard port (3306) and the new one (1234) with this:
sudo /usr/sbin/semanage port -l | grep mysql
That should output something like “mysqld_port_t tcp 1234,3306”.
(These changes are persisted in /etc/selinux/targeted/modules/active/ports.local
, so they will still be active after a reboot.)
Now, MySQL starts happily and I can connect and use it as I had expected. But I didn’t have to disable SELinux, which means that this and other daemons are still running inside a security container that will help to limit the damage if their security is compromised.
Very nice, thanks.
Thanks a lot. You saved me hours :)