前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >优雅!!! 30行原生python代码(无依赖)实现对mysql的SQL监控

优雅!!! 30行原生python代码(无依赖)实现对mysql的SQL监控

原创
作者头像
大大刺猬
发布2023-12-01 18:01:09
4320
发布2023-12-01 18:01:09
举报
文章被收录于专栏:大大刺猬大大刺猬

背景

之前有对mysql的审计需求,

最开始是使用中间件的方式来实现, 但太繁琐了,还影响性能.

之后使用 旁挂的方式来做升级, 但依赖 scapy的抓包功能.

最近 有需要查看mysql流量的需求, 就又要抓包了, 但老使用第三方软件, 总感觉差了点啥, 都是python代码写的. 那就自己实现吧.

原理

使用socket读取主机数据包流量, 解析IP/TCP协议, 然后匹配目标端口是否复合要求. 若符合要求, 则解析mysql包. 并打印出来.

具体实现都在代码里面, 都有相关注释, 代码也非常优雅, 方便阅读. (如果不熟悉TCP/IP协议的话, 可以先去看下TCP/IP协议)

代码语言:javascript
复制
IP --> TCP --> MYSQL PROTOCOL

IP PROC

TCP PROC

MYSQL PROC

SOURCE/DEST IP

SOURCE/DEST PORT

mysql query pack

当然也不支持SSL流量. 不过业务连接数据库 通常不会使用SSL

测试

把脚本放到数据库服务器上, 直接启动脚本即可, 不需要啥参数, 都是代码里面写好了的. 主要是为了简单, 没有解析mysql返回的流量. 也没有匹配IP信息. 可根据需求自己实现.

代码语言:javascript
复制
python Grace_AuditMySQL.py

我这里有mysqld_export, 所以一启动就有数据进来了. 可以自己加if条件取过滤掉不需要的流量

未匹配IP地址
未匹配IP地址

总结

python的socket模块还是太强大了.

当前基础知识也很重要(TCP,IP mysql protocol).

python虽然有很多第三方包, 但建议尽量使用内部模块

socket 不绑定 ip端口的话, 就能读取所有流量. 从而实现抓包(需要权限). 当然也可以这样绑定

代码语言:javascript
复制
s.bind((socket.gethostname(), 0))

啊, 优雅! -_-

附源码

Grace_AuditMySQL.py

注意: 脚本里面使用的端口是3308, 实际使用的时候需要修改为真实的端口. 我这里为了优雅, 就没写参数解析了

代码语言:python
复制
#!/usr/bin/env python3
#audit mysql, write by ddcw @https://github.com/ddcw
import socket,struct

def main():
	s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0800))
	try:
		while True:
			packet = s.recvfrom(65565)[0] #(bytes, address)
			ip_header = struct.unpack('!BBHHHBBH4s4s', packet[14:34]) #IP PRO
			source_ip,dest_ip = socket.inet_ntoa(ip_header[8]),socket.inet_ntoa(ip_header[9])
			iph_length = (ip_header[0] & 0xF) * 4

			if ip_header[6] == socket.IPPROTO_TCP: #ONLY FOR TCP
				tcp_header = struct.unpack('!HHLLBBHHH', packet[14+iph_length:14+iph_length+20]) #TCP PRO
				source_port,dest_port = tcp_header[0],tcp_header[1]
				tcp_length = (tcp_header[4] >> 4) * 4
				data_offset = 14 + iph_length + tcp_length
				data = packet[data_offset:]
				if dest_port == 3308 and data and data[4:5] == b'\x03': #match PORT and mysql query pack
					print(f"{source_ip}:{source_port} --> {dest_ip}:{dest_port}\t{data[5:].decode()}")

	except KeyboardInterrupt:
		pass

	finally:
		s.close()

if __name__ == "__main__":
	main()

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 原理
  • 测试
  • 总结
  • 附源码
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档