数据库做异地容灾是一个很常见的现象,既然信息要跨地域传递,要么就很土豪的打通机房之间的链路或者动用×××,要不然就不可避免的走公网网络传输信息。既然选择了公网,那么数据库的语句就很容易被人监听到,所以把那些明文加密是必不可少的环节。


mysql支持tls/ssl加密方法对信息进行加密,这个方法的配置也很简单,就是两边各加上一个nginx,一个是正向代理一个是反向代理,配上ssl证书,然后就像配置网站https协议那样,在nginx.conf里开启ssl监听即可。


但是这种方法有一点小问题,就是在进行SSL握手之前,mysql 会发送Server Greeting和Login Request数据包,然后才有可能使用SSL握手。这样步骤就多了一步鉴权,对访问性能有所影响。所以这个时候,我选择了另一个用于加密client和server之间链路通信的工具----Qtunnel,因为它直接加密,速度更快。


Git的地址在这里:https://github.com/arstercz/qtunnel ,感谢arstercz大神的再加工!


上面说过了Qtunnel是不需要认证的,默认加密方法是RC4,以字节流的方式加密明文的每一个字节,而且密钥长度最长支持256位,可以很好的抵御暴力搜索密钥的***,总而言之,Qtunnel是一个轻量且快速的加解密工具,而且还可以搭配atlas等数据库中间件使用。


下面我们就做一个实验,看一下Qtunnel实现加密的全过程。


由于Qtunnel是用go语言写的,所以需要先安装golang,centos服务器的yum安装方法如下: 

rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
yum install -y golang


go语言安装完毕之后,我们就#git clone https://github.com/arstercz/qtunnel.git  ,获得qtunnel文件夹,文件夹内容如下:

2f0eb90107146fed8316322b753b37c6.png


#make,如果没有任何报错,那么就是安装成功了,使用#./bin/qtunnel -h语句验证一番:

cb9ba17921261fd5280da7dd667dddbe.png


本次实验的计划是这样的:用A机器访问B机器的mysql,并且插入数据,在B机器上的3306端口抓包,查看数据是否是明文;然后再在A机器和B机器上都安装qtunnel并且启动,然后重新插入数据,在B机器上的端口抓包,查看数据是否被加密。流程图如下:

image.png

A机器和B机器都是使用阿里云虚拟服务器,版本都是6.4,现在我们的加密实验正式开始。


首先A和B机器上都不启动qtunnel,然后我们在A机器上登陆B机器的数据库,如果之前没有授权,那么授权语句是:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'A机器的IP地址' IDENTIFIED BY '密码' WITH GRANT OPTION;


登陆之后,我们随意的插一个语句,然后通过抓包发现无论这个语句还是数据库的反馈都是以明文的形式呈现,如图:

4e62e0add15765590eb13a02b0d6f204.png


这种让数据裸奔的行为无疑于找死,那么这个时候我们就要配置一下qtunnel,来看一下它的加密效果。


在A服务器上,我们设定qtunnel是客户端,手动建立一个conf文件,比如#vim /etc/conn.conf,内容如下:

[client1]
faddr = 10.252.215.108:3309    #这里是qtunnel客户端的IP
baddr = 10.175.193.239:3310    #这里是qtunnel服务端的IP
cryptoMethod = rc4             #这里选用rc4的方式加密
secret = 3301_test%Iad      #rc4密钥,服务端的密码必须跟这个一致!
clientmode = true              #表示这端是客户端


然后使用#./bin/qtunnel -conf=/etc/conn.conf -daemon -logto=syslog启动qtunnel,看一下进程和端口情况,如图:

18a5c05388b29da9bcf2c80795f2bd0e.png


在B服务器上,同样手动建立一个配置文件,假设也叫conn.conf,内容如下:

[server1]
faddr = 10.175.193.239:3310    #这里是qtunnel服务端的IP
baddr = 10.175.193.239:3306    #这里是数据库的地址,由于在同一台机器上,所以地址一样
cryptoMethod = rc4    
secret = 3301_test%Iad      #rc4密钥,跟client密钥一致
clientmode = false             #表示这是服务器端


也用同样的语句启动,查看3310这个端口已经被监听了:

24a4092d481b77965589d0c079fe3e37.png


现在,我们在A服务器上来重新连接B数据库,是要注意!这个时候mysql里的-h不能再是B的IP地址了,而是A的地址!因为qtunnel现在已经打通了一个通道,访问qtunnel的3310端口就等于是访问B数据库的3306端口(有点类似atlas的意思)。


连上之后,我们随意插入一些语句,看一下qtunnel的能力:

1e575af52757454a6ef0ed4b975f6b5b.png


可见这个时候,抓包显示都是加密的文字了,实验成功!


总结一下:qtunnel 采用 rc4加密,在算法强度和速度方面是很好的选择,不会引起 slave 太大的延迟,对管理员或开发而言数据都是透明的(如果在上面的实验启动了qtunnel之后,不监听3310端口,而是监听3306端口,得到的依旧是明文),只是在两端传输的过程中增加了加解密处理。核心的业务(比如用户和充值)在做异地架构的时候可以考虑该方式增强数据的安全性。


《mysql使用ssl简析》:https://hsulei.com/2017/10/19/mysql%E4%BD%BF%E7%94%A8ssl%E7%AE%80%E6%9E%90/ 

《使用ssl加密mysql 5.6的官方文档》:

https://dev.mysql.com/doc/refman/5.6/en/encrypted-connections.html 



最后的最后,如果您觉得本文对您升职加薪有帮助,那么请不吝赞助之手,刷一下下面的二维码,赞助本人继续写更多的博文!

wKioL1l16m3BMYDKAACPHEqd55Q687.jpg