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的方法,不過,你如今應該不會那麼作了吧?你已經手持完美的手術刀了,何須還去用什麼錘子呢?