Qtunnel 加密数据库主从复制通道

2015-11-05

Qtunnel 加密数据库主从复制通道

链接见:

https://github.com/getqujing/qtunnel https://github.com/arstercz/qtunnel

背景

在异地机房的环境下, MySQL 数据同步复制基于 tcp 的明文传输, slave 接收到的 sql 语句可以很容易的被监听到, 对于敏感数据, 这种简单的异地复制是很危险的方式. 当然机房之间如果已经打通或有 vpn 互相通信就可以忽略该文的介绍. 另外也可以通过 MySQL 内置的 tls/ssl 方式实现复制, 不过该方式对应用的访问性能可能造成影响, 也容易影响线上的数据库架构, 详见 https://dev.mysql.com/doc/refman/5.6/en/ssl-connections.html

qtunnel 介绍

qtunnel 是一款用于加密 client 和 server 之间链路通信的工具, 类似的工具有 Stunnel 和 stud . qtunnel 默认使用 rc4 加密算法来加密数据, rc4 是一种类似 DES 的对称加密算法, 它以字节流的方式加密明文中的每一个字节, 解密也是依次对对密文中的每个字节进行解密, 该算法比较简单, 运行速度快, 另外因为 rc4 的密钥长度可变(1-256字节), 所以可以很好的抵御暴力搜索密钥的攻击, 详见 https://en.wikipedia.org/wiki/RC4

另外 Stunnel 和 stud 工具都是基于 ssl/tls 环境配置的工具, 增加了认证配置稍显复杂, qtunnel 则不需要这些, 可以比较轻量且快速的加解密 client 到 server 端之间的数据.

完整的访问如下所示, slave 以明文方式通信,经过 qtunnel client 加密后发送到 qtunnel server, server 端再进行解密, 传到 master; master 的响应也以此方式完成.


      +---------+      +----------------+   qtunnel 加解密     +----------------+      +--------+    
      | slave   | ---> | qtunnel client | ------------------> | qtunnel server | ---> | master |    
      +---------+      +----------------+                     +----------------+      +--------+    


Note: 笔者在原工具的基础上重新 fork 该工程, 增加了配置选项, 可以支持多连接运行, 同时支持了以 daemon 模式运行程序.

qtunnel 使用

qtunnel 常用选项包括:

Usage of qtunnel:
  -backend="127.0.0.1:6400": host:port of the backend
  -clientmode=false: if running at client mode
  -conf="": read connection setup from config file
  -crypto="rc4": encryption method
  -daemon=false: running in daemon mode
  -listen=":9001": host:port qtunnel listen on
  -logto="stdout": stdout or syslog
  -secret="secret": password used to encrypt the data

listen 等同下面的 faddr 选项, 为本地监听地址, 指定 conf 选项后, 其它的加密算法的选项可以忽略.

  1. 在明文环境中, 使用 tcpdump 来监听 MySQL 端口, 可以很方便的看到 sql 语句以及相关的事务语句信息, 如下:
# tcpdump -s 0 -l -w -  port 23301 | strings

SYSTEM
BEGIN
SYSTEMuser_test
insert into user_msg(type, app_id, user_id, title, content, create_time, update_time, expire_time)      values(3, null, 39871, '
', '
 2015-11-05 14:12:14
 iPhone 6 (xxxxxxx) 
 - iOS
', now(), now(), '2015-11-15 14:12:14')
SYSTEM
BEGIN
SYSTEMtest

可以看到在公网环境中, 明文传输方式是很危险的.

  1. 下面来看看 qtunnel 的配置, 我们在一台机器中配置 qtunnel 的 server 模式, 如下:
# cat /etc/conn.con

[server1]
faddr = 10.0.21.5:23301
baddr = 10.0.21.7:3301
cryptoMethod = rc4
secret = 3301_test%Iad      # rc4 密钥
clientmode = false

[server2]
faddr = 10.0.21.5:23302
baddr = 10.0.21.7:3302
cryptoMethod = rc4
secret = 3302_test$sOc
clientmode = false

qtunnel 以转发的方式在本地启动一个监听端口, 转发到后端的数据库主机, 该方式类似传统的 rinetd 工具; 启动 qtunnel:

qtunnel -conf=/etc/conn.conf -daemon -logto=syslog

[root@cz1 ~]# netstat -tunlp|grep qtun
tcp        0      0 10.0.21.5:23301          0.0.0.0:*                   LISTEN      9504/qtunnel        
tcp        0      0 10.0.21.5:23302          0.0.0.0:*                   LISTEN      9504/qtunnel        
  1. 在另一台机器配置 qtunnel 的 client 模式:

因为 rc4 是对称加密, 所以 client 端的密钥需要和 server 端保持一致.

[client1]
faddr = 10.0.21.3:30031
baddr = 10.0.21.5:23301
cryptoMethod = rc4
secret = 3301_test%Iad
clientmode = true

[client2]
faddr = 10.0.21.3:30032
baddr = 10.0.21.5:23302
cryptoMethod = rc4
secret = 3302_test$sOc
clientmode = true

启动 qtunnel

# qtunnel -conf=/etc/conn.conf -daemon -logto=syslog

[root@cz3 test]# netstat -tunlp|grep qtunnel
tcp        0      0 10.0.21.3:30031          0.0.0.0:*                   LISTEN      1519/qtunnel        
tcp        0      0 10.0.21.3:30032          0.0.0.0:*                   LISTEN      1519/qtunnel        

重新修改内网 slave 指向, slave 指到 qtunnel client 端:

# stop slave
# CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=62778,     MASTER_HOST='10.0.21.3', MASTER_PORT=30031, MASTER_CONNECT_RETRY=10;
# start slave
  1. 再看看qtunnel server 端加密后的 tcpdump 监听:
# tcpdump -s 0 -l -w -  port 23301 | strings

#}?P
[~/e
+WlA
TS@F^
?k*L
m=R~
^o}	
{C\1
rsYU
ax&A
u4|.
iN0K
Omv[
u~n	
m=R~
m=R~
]e	,
Out~
QQu@a
#r6) 
*n2"

总结说明 qtunnel 采用 rc4 加密, 在算法强度和速度方面是很好的选择, 不会引起 slave 太大的延迟, 对管理员或开发而言数据都是透明的, 只是在两端传输的过程中增加了加解密处理. 核心的业务(比如用户和充值)在做异地架构的时候可以考虑该方式增强数据的安全性.