细聊MySQL的安全机制

    MySQL作为系统的数据库,在安全性方面有非常高的要求。如果一个系统的数据库被非法进入或窃听,则系统的数据将受到非常严重的威胁,轻则数据、密码被盗,重则导致整个系统瘫痪。所以数据库的安全对于系统来说是非常重要的。


    本文将从MySQL的服务器启动与客户端访问、操作及链路三方面来阐述MySQL的安全机制。


    一、MySQL的服务器启动与客户端访问。
        1、服务器启动,启动服务器在安全方面的影响主要是启动它的用户。默认情况下,MySQL不允许使用root账号启动。我们应该建立一个只能操作MySQL安装目录与数据目录的非交互式账号来运行mysqld服务器。另外,服务器最好针对指定客户机开放,应将服务器置于iptables后,如果过让任意主机都能通过telnet的方式连线到服务器,也将是不安全的。telnet的测试方式为shell > telnet ip(服务器的ip)3306(服务器的默认端口)
        2、客户端访问,使用bin/mysql客户端工具登录时可以通过配置文件及直接在命令行添加参数两种方式。在登录时,我们需要使用密码才能进入,然而MySQL在安装后默认root账号是没有密码的。所以我们首先需要为root设置密码。如果root没有设置密码,那么可以通过以下方式设置:
        2.1 shell > bin/mysql —user=root —host=127.0.0.1,回车后应该进入到mysql客户端的交互界面。
        2.2 mysql > set password for ‘root’@‘127.0.0.1’ = password(’你设置的明文密码’)。这样127.0.0.1下的root密码就设置好了。需要注意的是,MySQL的登入账号不仅仅是用户名,而是用户名+IP或域名的方式确认唯一一个连线的。所以,如果该服务器的IP是192.168.1.5,在设置密码时我只设置了’root’@‘127.0.0.1’的密码,那么当用mysql —host=192.168.1.5 —user=root —password=’你设置的明文密码’登录时,会提示错误。所以,如果我们不在服务器本地登陆,那么我们还需要设置密码set password for ‘root’@‘192.168.1.5’=password(’你设置的明文密码’)。 另外一个需要注意的是,在设置密码时,我们使用了password()函数,password函数将明文密码转换成41个字节长的hash值。增加了密码的安全性。
        如果我们将密码放置在配置文件中,记得将配置文件的访问权限设置成600或400,你也不想其它用户能够轻易的读到它吧。

    二、MySQL操作的授权管理系统安全机制
        2.1 MySQL权限管理系统的主要功能是验证客户端用户的登入以及验证该用户具体的对MySQL的操作权限,比如该用户可能只对某个数据库的其中某个表具有update权限和insert权限,那么系统将会禁止TA对其它的表进行写操作。但,以下的事情是权限系统办不到的:
        2.1.1、你不能指定具体拒绝登入的用户。
        2.1.2、你不能指定一个用户创建或删除一个数据库里的表,但又不让TA创建或删除该表所属的数据库。
        2.1.3、用户的密码是全局性的,你不能针对数据库或表来设置密码。

        2.2 MySQL将权限分为全局权限与对象权限。所谓的全局权限是与数据库、表、视图等不相干的权限,如密码的设置、用户的创建等。对象权限是相对于全局权限的,也就是与数据库、表、视图、列、索引等一切对象相关的权限。
        关于权限的信息存储在mysql数据库中的user、db、tables_priv、columns_priv和prods_priv表里,在服务器启动后,程序会将权限表载入到内存里,客户端连入时会根据权限表验证用户的合法性,当客户端发出请求时,也会根据权限表验证用户操作的合法性。
        下面我们可以大致看下我们能控制的具体权限以及这些权限作用的范围和控制权限的列名。


        

权限控制权限的列名作用范围
CREATECreate_priv数据库、表、索引
DROPDrop_priv数据库、表、视图
LOCK TABLESLock_tables_priv数据库
REFERENCESReferences_priv数据库、表
EVENTEvent_priv数据库
ALTERAlter_priv
DELETEDelete_priv
INDEXIndex_priv
INSERTInsert_priv表、列
SELECTSelect_priv表、列
UPDATEUpdate_priv表、列
CREATE TEMPORARY TABLESCreate_tmp_table_priv
TRIGGERTrigger_priv
CREATE VIEWCreate_view_priv视图
SHOW VIEWShow_view_priv视图
CREATE TABLESPACECreate_tablespace_priv全局
CREATE USERCreate_user_priv全局
PROCESSProcess_priv全局
PROXYsee proxies_priv table全局
RELOADReload_priv全局
REPLICATION CLIENTRepl_client_priv全局
REPLICATION SLAVERepl_slave_priv全局
SHOW DATABASESShow_db_priv全局
SHUTDOWNShutdown_priv全局
SUPERSuper_priv全局
ALL [PRIVILEGES]

全局
USAGE
全局


        我们可以根据上表进行相应的权限设置。要设置权限,首先得知道我们设置的用户的当前的权限。利用下面的命令可知:
mysql > show grants for ‘user’@‘ip’;
再次强调下,虽然使用show grants for ‘user’;也可以显示,但’user’@‘ip’才代表mysql的一个唯一用户。调用命令后将显示如下结果:
GRANT USAGE ON *.* TO ‘wangwei‘@‘%‘ IDENTIFIED BY PASSWORD ‘*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9‘ WITH MAX_QUERIES_PER_HOUR 20

        USAGE是上表中的最后一行的值,是一个全局权限,只是代表能够进入到数据库。
        *.*第一个*代表数据库名,第二个*代表表名。
        IDENTIFIED BY后是密码
        WITH后是权限参数,这里是限制每小时最多查询20次

        然后开始设置我们自己的权限,如想设置某个表某列的查询权限则命令如下:
        mysql > grant select(列名) on 数据库名.表名 to ‘用户名’@‘IP’;
        这样,该用户即有指定列的查询权限了。

        2.3 密码过期策略。如果你想让mysql用户隔一段时间设置一次密码,可用以下方法。
        mysql > alter user ‘user’@‘ip’ password expire;    使该用户密码立即失效
        mysql > alter user ‘user’@‘ip’ password expire interval 90 day;    每隔90天密码需要重设一次
        mysql > alter user ‘user’@‘ip’ password expire never;    密码永不过期
        还可以通过配置文件设置密码的默认过期时间如:
        [mysqld]
        default_password_lifetime=180

    三、链路通讯安全。客户端通过网路与服务器通讯,除传输登录验证信息外还请求具体的数据库操作。所以服务器与客户端之间数据的保密性与完整性是非常重要的。这里,我们通过SSL来保证数据的安全性。
        要使用SSL,需要MySQL服务器支持SSL协议。使用mysql > show variables like ‘have_ssl’;可以查询MySQL是否支持SSL。如果显示YES则该服务器正以SSL协议在运行。如果显示DISABLED则表示服务器支持SSL,但是没有开启SSL。如果显示其它,则表示MySQL服务器不支持SSL。需要重新下载新版本的MySQL或重新编译,启动SSL功能。本人所用的是MySQL 5.6的二进制版本,默认是支持SSL的。下面介绍下具体的配置方法。
        配置SSL只需要四个参数ssl、ssl-ca、ssl-cert、ssl-key。ssl表明启动SSL功能。ssl-ca为CA证书的位置。ssl-cert为由CA签名的服务器证书所在位置。ssl-key为服务器的私钥位置。如果对CA及X509比较熟悉的朋友应该很好理解,这几个参数的作用。对不不理解的朋友最好去学习下CA认证与SSL协议的原理。不管你是否熟悉SSL。按照以下步骤应该也可以配置好安全链路的MySQL通讯。
        下面介绍下具体的实现步骤:
        1、下载和安装openssl。下载地址为http://www.openssl.org/source/。可以下载最新版openssl-1.0.1j.tar.gz。我就是用的最新版本。
              安装方法:
                shell > tar zxvf openssl-1.0.1j.tar.gz
        shell > cd openssl-1.0.1j && ./config --prefix=/usr/local —    openssldir=/usr/local/openssl
        shell > make
        shell > make install
    安装后在/usr/local/bin下可找到openssl的命令。上面是很简单的源码编译安装方法,不用详细解释了。按照以上步骤应该可以安装好openssl。

        2、建立CA证书
            shell > mkdir newcerts && cd newcerts
            shell > openssl genrsa 2048 > ca-key.pem 建立CA私钥
            shell > openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca-cert.pem    建立CA根证书
        
        3、建立CA签名的服务器证书及私钥
            shell > openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem -out server-req.pem    建立服务器证书请求文件及服务器私钥
            shell > openssl rsa -in server-key.pem -out server-key.pem    加密私钥
            shell > openssl x509 -req -in server-req.pem -days 3600 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem 签名服务器证书

        生成的ca-cert.pem用于ssl-ca参数
        生成的server-cert.pem用于ssl-cert参数
        生成的server-key.pem用于ssl-key参数

        服务器运行命令如下
        mysqld —user=mysql —ssl —ssl-ca=/path/ca-cert.pem —ssl-cert=/path/server-cert.pem —ssl-key=/path/server-key.pem
        
        客户端也可以创建SSL证书进行双向验证,也可以不做设置直接连接到服务器。运行后可用mysql > show variables like ‘have_ssl’;验证。如果结果显示YES。代表SSL设置成功。否则需要调试看看是什么问题。
        如果出现问题,首先可以用shell> openssl verify -CAfile ca-cert.pem server-cert.pem看看证书是否正确生成。如果仍然有问题需要看下mysqld运行用户是否有权限读取证书。


       

本文出自 “架构师之路” 博客,请务必保留此出处http://wangweiak47.blog.51cto.com/2337362/1588015

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。