从8.0.14版本开始,MySQL可以加密磁盘上binlog文件和relay文件。这样保证binlog泄露导致的安全问题。为此,需要启用binlog_encryption参数(并确保有一个密钥环keyring)。
mysql> SET GLOBAL binlog_encryption=ON;
ERROR 3794 (HY000): Unable to recover binlog encryption master key, please check if keyring is loaded.
配置binlog加密方式如下文件设置密钥环:
[mysqld]
early-plugin-load=keyring_file.so
keyring_file_data=/opt/data8.0/keyring_file/keyring
binlog_encryption=ON
读取binlog内容
当开启加密属性之后,会马上切换新的binlog文件,之后通过mysqlbinlog方式本地读取,会提示无法读取“ERROR: Reading encrypted log files directly is not supported.”错误提示:
shell# mysqlbinlog mysql-bin.000002 | grep "^# at "
ERROR: Reading encrypted log files directly is not supported.
从上述内容中说明,当binlog文件被加密后,mysqlbinlog无法直接读取,按照官方指导可以使用–read from remote server选项从服务器读取。
1.使用read-from-remote-server参数读取
shell# mysqlbinlog --user=root --password=123456 --socket=/opt/data8.0/data/mysql.sock \
--read-from-remote-server --base64-output=DECODE-ROWS -v -v \
mysql-bin.000002
BEGIN
。。。
### INSERT INTO `w1`.`t1`
### SET
### @1=3 /* LONGINT meta=0 nullable=0 is_null=0 */
### @2='C' /* VARSTRING(1020) meta=1020 nullable=1 is_null=0 */
# at 509
#241217 14:21:21 server id 129 end_log_pos 540 CRC32 0x9256dac0 Xid = 26
COMMIT/*!*/;
。。。
2.使用SHOW BINLOG命令行读取
SHOW BINLOG EVENTS命令可以以列表的形式显示日志中的事件信息。
mysql> SHOW BINLOG EVENTS IN 'mysql-bin.000002';
+------------------+-----+----------------+-----------+-------------+-----------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------------+-----+----------------+-----------+-------------+-----------------------------+
| mysql-bin.000002 | 4 | Format_desc | 129 | 126 | Server ver: 8.0.40, Binlog ver: 4 |
| mysql-bin.000002 | 126 | Previous_gtids | 129 | 197 | 8f789b76-4024-11ef-b562-00163e23e2cc:1 |
| mysql-bin.000002 | 197 | Gtid | 129 | 276 | SET @@SESSION.GTID_NEXT= '8f789b76-4024-11ef-b562-00163e23e2cc:2' |
| mysql-bin.000002 | 276 | Query | 129 | 349 | BEGIN |
| mysql-bin.000002 | 349 | Rows_query | 129 | 410 | # insert into t1(id,Name) values(3,'C') |
| mysql-bin.000002 | 410 | Table_map | 129 | 462 | table_id: 116 (w1.t1) |
| mysql-bin.000002 | 462 | Write_rows | 129 | 509 | table_id: 116 flags: STMT_END_F |
| mysql-bin.000002 | 509 | Xid | 129 | 540 | COMMIT /* xid=26 */ |
+------------------+-----+----------------+-----------+-------------+-----------------------------+
8 rows in set (0.00 sec)
3.使用mysqlbinlog备份导出文件读取
如果使用mysqlbinlog备份加密的binlog文件,生成的文件副本是以未加密的格式存储的。
shell# mysqlbinlog --user=root --password=123456 --socket=/opt/data8.0/data/mysql.sock \
--read-from-remote-server --base64-output=DECODE-ROWS -v -v mysql-bin.000002\
--result-file=/tmp/mysqlbin.sql
shell# less /tmp/mysqlbin.sql
#241217 14:21:21 server id 129 end_log_pos 509 CRC32 0xb1d88abf Write_rows: table id 116 flags: STMT_END_F
### INSERT INTO `w1`.`t1`
### SET
### @1=3 /* LONGINT meta=0 nullable=0 is_null=0 */
### @2='C' /* VARSTRING(1020) meta=1020 nullable=1 is_null=0 */
# at 509
#241217 14:21:21 server id 129 end_log_pos 540 CRC32 0x9256dac0 Xid = 26
COMMIT/*!*/;
4.离线加密binlog文件读取
需要原主库的keyring文件。
1.把原主库的keyring文件,拷贝到新节点。
2.把binlog文件拷贝的新的节点。
3.新节点mysql-bin.index文件,注册拷贝的binlog文件。
4.重新启动新节点MySQL服务。
可以通过mysqlbinlog 和 show event命令行,可以解读binlog内容了。
5.如何判断binlog是否加密
当然可以通过命令行查询参数 或 直接mysqlbinlog查看时候能正常显示。按照一些互网上研究,可以通过查看binlog文件的header (的前四个字节),可以判断出对binlog和relay文件是否进行加密。总结出未加密的文件已0xFE62696E的header信息,但加密文件已0xFD62696E的header信息。
shell# echo $( hexdump -v -e '/1 "%02X"' mysql-bin.000001 -n 4 )
FE62696E
shell# echo $( hexdump -v -e '/1 "%02X"' mysql-bin.000002 -n 4 )
FD62696E
总结
虽然MySQL的binlog文件进行加密了。但可以通过hexdump命令研究规则,反解析binlog文件,并进行破解。
参考
http://mysql.taobao.org/monthly/2019/12/02/
https://dev.mysql.com/blog-archive/binary-log-encryption-at-rest/
https://dev.mysql.com/blog-archive/how-to-manually-decrypt-an-encrypted-binary-log-file/




