SELinux之于MySQLpython
博客分类: 数据库mysql
========================================================linux
我以前写了一篇《AppArmor and MySQL》的文章,讲了如何在启用AppArmor的状况下改变MySQL的默认文件路径。Ubuntu和SUSE配备了AppArmor,而其余一些发布版本,如Oracle Linux则没有,以及其余一些相关的版本如Red Hat、CentOS及Fedora都没有。相对的,他们使用另外一个托管访问控制(译注:mandatory access control)系统SELinux。 正则表达式
SELinux(安全强化,若是你感兴趣)“是linux中支持安全访问控制策略机制的一种特性”--维基百科。更简单的说,它能阻止好比程序之类的访问他们不该该访问的文件和网络端口等。所谓“不该该访问”这里指的是“还没有被配置为能够访问”。好比说,MySQL容许访问它的数据目录/var/lib/mysql,而且能够读取/etc/my.cnf。它能够打开3306端口,可是SELinux阻止它向/home/Jeremy或者/sbin或者其余任何还没有配置成为MySQL位置的路径进行写操做。 sql
简而言之,若是你想更改MySQL的默认端口为一个非标准端口,或者试图备份或者设置数据文件或日志文件到很是用路径,你就会在MySQL错误日志里面收到不少奇怪的禁止访问类型的错误。另外,你一样会在/var/log/audit/audit.log(若是auditd正在运行,不然在/var/log/messages或者/var/log/syslog里面,这取决于你的系统配置)里收到信息。 数据库
会获得什么错误呢?
我这边采用了MySQL5.6及Oracle Linux 6.3做为样例环境,同时启用了SELinux。当我把datadir这个变量设置为/datadir时(此目录复制了MySQL原数据目录的全部内容,而且设置了正确的权限),就没法启动服务了。看下面的错误。缓存
MySQL错误日志中:
130321 11:50:51 mysqld_safe Starting mysqld daemon with databases from /datadir
...
2013-03-21 11:50:52 2119 [Warning] Can't create test file /datadir/boxy.lower-test
2013-03-21 11:50:52 2119 [Warning] Can't create test file /datadir/boxy.lower-test
...
2013-03-21 11:50:52 2119 [ERROR] /usr/sbin/mysqld: Can't create/write to file
'/datadir/boxy.pid' (Errcode: 13 - Permission denied)
2013-03-21 11:50:52 2119 [ERROR] Can't start server: can't create PID file:
Permission denied
130321 11:50:52 mysqld_safe mysqld from pid file /datadir/boxy.pid ended安全
我很确信如今这个目录的权限是正确的,咱们再来看看/var/log/audit/audit.log:
...
type=AVC msg=audit(1363866652.030:24): avc: denied { write } for pid=2119
comm="mysqld" name="datadir" dev=dm-0 ino=394
scontext=unconfined_u:system_r:mysqld_t:s0
tcontext=unconfined_u:object_r:default_t:s0 tclass=dir
...服务器
若是我更改端口为非默认端口3307时,启动MySQL也会遇到相似的错误。网络
MySQL错误日志中:
2013-03-21 12:12:09 3436 [Note] Server hostname (bind-address): '*'; port: 3307
...
2013-03-21 12:12:09 3436 [ERROR] Can't start server: Bind on TCP/IP port:
Permission denied
2013-03-21 12:12:09 3436 [ERROR] Do you already have another mysqld server
running on port: 3307 ?
2013-03-21 12:12:09 3436 [ERROR] Aborting
audit日志中:
type=AVC msg=audit(1363867929.432:42): avc: denied { name_bind } for pid=3436
comm="mysqld" src=3307
scontext=unconfined_u:system_r:mysqld_t:s0
tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket
很明显这里有点问题。Access Vector Cache(如日志中显示的“avc: denied”)是SELinux用来为内核缓存权限的地方。因此很明显是SELinux阻止了操做。
仅仅关闭它就好!
下面就我会先从锤子开始,而后逐渐打形成手术刀。(译注:这个……我不知道理解的对不对,原文是I'm going to start with the hammer and work my way down to the scalpel. )
锤子以下:
[root@boxy ~]# setenforce 0
[root@boxy ~]# getenforce
Permissive
setenforce 0用来关闭SELinux enforcing,重启则失效。getenforce显示当前状态。若是想要在重启之后仍然生效,想要改写如下配置文件:
[root@boxy ~]# cat /etc/selinux/config
SELINUX=enforcing
SELINUXTYPE=targeted
将enforcing设置为permissive(或者disabled)就ok了。参数的差异以下:
enforcing 阻止SELinux不容许的操做
permissive 并不阻止操做,可是会记录日志(/var/log/audit/audit.log)
disabled 彻底关闭SELinux,甚至你都无法使用setenforce了,除非换成其余参数,并重启
例如,若是服务器的SELinux设置为permissive,那么我能够这么作:
[root@boxy ~]# setenforce 1
[root@boxy ~]# getenforce
Enforcing
可是若是设置为disabled,就会这样:
[root@boxy ~]# setenforce 0
setenforce: SELinux is disabled
[root@boxy ~]# setenforce 1
setenforce: SELinux is disabled
以上就是所谓的锤子。
那么,咱们返回到产生错误的这个例子,我能够这么使用锤子。
[root@boxy ~]# setenforce 0
[root@boxy ~]# service mysql start --datadir=/datadir
Starting MySQL. SUCCESS!
[root@boxy ~]# service mysql stop
Shutting down MySQL.. SUCCESS!
若是这样子你就满意了,那么你能够编辑配置文件,而后在下次重启时禁用SELinux,而且谢谢阅览。下次见~
我仍是有点迷惑。我该怎么配置它而不是禁用呢?
很明显,比起禁用,还有不少事情能够作。并且负责任的管理员(好比你?)想要知道比起禁用,如何更好的使用它。下面,我不会讨论太多细节。
不管如何,咱们能够看看该怎样给好比端口、文件这些对象分配SELinux类型(译注:types),而后可让mysql_t域的成员们(尤为是启动 service mysql start产生的mysqld_safe进程)能够访问这些对象。
如下是手术刀了。首先,咱们配置一下SELinux来启用MySQL的3307端口
[root@boxy ~]# semanage port -a -t mysqld_port_t -p tcp 3307
(注:你须要首先安装policycoreutils-python包来使用semanage工具)
semanage工具能够变动不少SELinux设置。这里,咱们为使3307端口使用TCP做为它的协议(-p tcp)而向端口映射增长了(-a)一种类型(-t mysqld_port_t)。当MySQL(经过mysqld_safe进程)试图访问这个端口时,SELinux从策略(译注:policy)里面识别这个端口匹配一种类型,而且容许进行这样的访问。
一样咱们能够容许MySQL使用/datadir文件夹:
[root@boxy ~]# semanage fcontext -a -t mysqld_db_t "/datadir(/.*)?"
[root@boxy ~]# restorecon -Rv /datadir
restorecon reset /datadir context
unconfined_u:object_r:default_t:s0->unconfined_u:object_r:mysqld_db_t:s0
restorecon reset /datadir/mysql.sock context
system_u:object_r:mysqld_var_run_t:s0->system_u:object_r:mysqld_db_t:s0
在这个例子中,semanage在文件上下文映射(fcontext)中增长了mysqld_db_t的类型,指定了/datadir路径下的全部文件以及子文件(“/datadir(/.*)?”,正则表达式)。这样的文件映射包含在/etc/selinux/targeted/contexts/files/file_contexts.local文件中,为了可以给这个文件设置合适的类型,这个文件必须可以被读取。restorecon工具在系统重启的时候就完成了该操做。若是你想立刻更改文件上下文而且不须要重启之后还生效,那么使用chcon工具就能够了。
若是你想使用其余端口或者文件夹,也可使用一样的方式和语句。不一样类型的文件对应一些相似的类型;我这里使用上面的mysqld_db_t来对应数据库文件夹,可是标准SELinux策略针对MySQL也包含:
mysqld_etc_t 用来匹配配置文件如 /etc/my.cnf
mysqld_log_t 用来匹配日志文件如 /var/log/mysql*
PID文件、tmp文件、/etc/init.d里面的服务启动文件的类型,还有各类各样你想使用的可执行文件。
如你所见,你能够自如的使用你的手术刀来合理的分配权限。就我我的而言,我已经使用像mysql_log_t这样的类型匹配自定义的日志文件路径而获得了混合的效果,不过我会首先使用mysqld_db_t(就像用来匹配数据文件),而后使用自定义的策略文件来搞定。
结语
这篇文章已经够长了,因此我不会讨论更为深刻的SELinux话题了,好比说编译你本身的策略文件以及为SELinux尚不知道的服务配置新的策略。如今,你已经知道如何为SELinux增长一种类型,来让MySQL能够访问并不是默认的端口或者文件了。你也知道了好几种关闭SELinux的方法,不过,你如今应该不会那么作了吧?你已经手持完美的手术刀了,何须还去用什么锤子呢?