Merge pull request #2 from 40t/feature/lang

Feature/lang
This commit is contained in:
Four 2018-10-06 10:52:07 +08:00 committed by GitHub
commit 76d7a00755
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 154 additions and 206 deletions

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2018 Jing Copyright (c) 2018 40t<jtjinggm@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,10 +1,7 @@
# go-sniffer # go-sniffer
> 捕获mysql,redis,http,mongodb等协议...完善中 > Capture mysql,redis,http,mongodb etc protocol...
> - 抓取项目中的数据库请求,如:执行的mysql查询语句
> - 不需要修改项目代码,通过指定端口抓包解析协议
> - 快速预览项目中所有的数据请求,便于程序调试
[![GitHub license](https://img.shields.io/github/license/40t/go-sniffer.svg?style=popout-square)](https://github.com/40t/go-sniffer/blob/master/LICENSE) [![GitHub license](https://img.shields.io/github/license/40t/go-sniffer.svg?style=popout-square)](https://github.com/40t/go-sniffer/blob/master/LICENSE)
@ -24,18 +21,21 @@ $ go-sniffer en0 mysql
``` ```
![image](https://github.com/40t/go-sniffer/raw/master/images/demo.gif) ![image](https://github.com/40t/go-sniffer/raw/master/images/demo.gif)
## Setup: ## Setup:
- 支持 : `MacOS` `Linux` `Unix` - support : `MacOS` `Linux` `Unix`
- 不支持 : `windows` - not support : `windows`
- 依赖:`google/gopacket`库
### 依赖库安装:Centos ### Centos
``` bash ``` bash
$ yum install libcap-devel $ yum install libcap-devel
``` ```
### 依赖库安装: Ubuntu ### Ubuntu
``` bash ``` bash
$ apt-get install libcap-dev $ apt-get install libcap-dev
``` ```
### MacOs
``` bash
All is ok
```
### RUN ### RUN
``` bash ``` bash
$ go get -v github.com/40t/go-sniffer $ go get -v github.com/40t/go-sniffer
@ -44,59 +44,36 @@ $ go run main.go
``` ```
## Usage: ## Usage:
``` bash ``` bash
======================================================================= ==================================================================================
[使用说明] [Usage]
go-sniffer [设备名] [插件名] [插件参数(可选)] go-sniffer [device] [plug] [plug's params(optional)]
[例子] [Example]
go-sniffer en0 redis 抓取redis数据包 go-sniffer en0 redis Capture redis packet
go-sniffer en0 mysql -p 3306 抓取mysql数据包,端口3306 go-sniffer en0 mysql -p 3306 Capture mysql packet
go-sniffer --[命令] go-sniffer --[commend]
--help 帮助信息 --help "this page"
--env 环境变量 --env "environment variable"
--list 插件列表 --list "Plug-in list"
--ver 版本信息 --ver "version"
--dev 设备列表 --dev "device"
[例子] [Example]
go-sniffer --list 查看可抓取的协议 go-sniffer --list "show all plug-in"
======================================================================= ==================================================================================
[设备名] : lo0 : 127.0.0.1 [device] : lo0 : 127.0.0.1
[设备名] : en0 : x:x:x:x:x5:x 192.168.1.3 [device] : en0 : xx:xx:xx:xx:xx:xx 192.168.199.221
[设备名] : utun2 : 1.1.11.1 ==================================================================================
=======================================================================
``` ```
### mysql ### Example:
> 支持预处理语句等常大部分语句
``` bash ``` bash
$ go-sniffer [设备名] mysql [参数] $ go-sniffer lo0 mysql
-p 置顶端口默认3306 $ go-sniffer en0 redis
$ go-sniffer eth0 http -p 8080
$ go-sniffer eth1 mongodb
``` ```
![image](https://github.com/40t/go-sniffer/raw/master/images/mysql.gif)
### redis
``` bash
$ go-sniffer [设备名] redis [参数]
-p 置顶端口默认6379
```
![image](https://github.com/40t/go-sniffer/raw/master/images/redis.gif)
### http
``` bash
$ go-sniffer [设备名] http [参数]
-p 置顶端口默认80
```
![image](https://github.com/40t/go-sniffer/raw/master/images/http.gif)
### mongodb
``` bash
$ go-sniffer [设备名] mongodb [参数]
-p 端口默认27017
```
- 支持大部分语句,只有个别少数语句没有实现
## License: ## License:
[MIT](http://opensource.org/licenses/MIT) [MIT](http://opensource.org/licenses/MIT)

View File

@ -10,11 +10,11 @@ import (
const InternalCmdPrefix = "--" const InternalCmdPrefix = "--"
const ( const (
InternalCmdHelp = "help" //帮助文档 InternalCmdHelp = "help"
InternalCmdEnv = "env" //环境变量 InternalCmdEnv = "env"
InternalCmdList = "list" //插件列表 InternalCmdList = "list"
InternalCmdVer = "ver" //版本信息 InternalCmdVer = "ver"
InternalDevice = "dev" //设备链表 InternalDevice = "dev"
) )
type Cmd struct { type Cmd struct {
@ -32,13 +32,13 @@ func NewCmd(p *Plug) *Cmd {
//start //start
func (cm *Cmd) Run() { func (cm *Cmd) Run() {
//使用帮助 //print help
if len(os.Args) <= 1 { if len(os.Args) <= 1 {
cm.printHelpMessage(); cm.printHelpMessage()
os.Exit(1) os.Exit(1)
} }
//解析命令 //parse command
firstArg := string(os.Args[1]) firstArg := string(os.Args[1])
if strings.HasPrefix(firstArg, InternalCmdPrefix) { if strings.HasPrefix(firstArg, InternalCmdPrefix) {
cm.parseInternalCmd() cm.parseInternalCmd()
@ -47,7 +47,8 @@ func (cm *Cmd) Run() {
} }
} }
//解析内部参数 //parse internal commend
//like --help, --env, --device
func (cm *Cmd) parseInternalCmd() { func (cm *Cmd) parseInternalCmd() {
arg := string(os.Args[1]) arg := string(os.Args[1])
@ -56,9 +57,9 @@ func (cm *Cmd) parseInternalCmd() {
switch cmd { switch cmd {
case InternalCmdHelp: case InternalCmdHelp:
cm.printHelpMessage() cm.printHelpMessage()
break; break
case InternalCmdEnv: case InternalCmdEnv:
fmt.Println("插件路径:"+cm.plugHandle.dir) fmt.Println("External plug-in path : "+cm.plugHandle.dir)
break break
case InternalCmdList: case InternalCmdList:
cm.plugHandle.PrintList() cm.plugHandle.PrintList()
@ -68,45 +69,45 @@ func (cm *Cmd) parseInternalCmd() {
break break
case InternalDevice: case InternalDevice:
cm.printDevice() cm.printDevice()
break; break
} }
os.Exit(1) os.Exit(1)
} }
//使用说明 //usage
func (cm *Cmd) printHelpMessage() { func (cm *Cmd) printHelpMessage() {
fmt.Println("==================================================================================") fmt.Println("==================================================================================")
fmt.Println("[使用说明]") fmt.Println("[Usage]")
fmt.Println("") fmt.Println("")
fmt.Println(" go-sniffer [设备名] [插件名] [插件参数(可选)]") fmt.Println(" go-sniffer [device] [plug] [plug's params(optional)]")
fmt.Println() fmt.Println()
fmt.Println(" [例子]") fmt.Println(" [exp]")
fmt.Println(" go-sniffer en0 redis 抓取redis数据包") fmt.Println(" go-sniffer en0 redis Capture redis packet")
fmt.Println(" go-sniffer en0 mysql -p 3306 抓取mysql数据包,端口3306") fmt.Println(" go-sniffer en0 mysql -p 3306 Capture mysql packet")
fmt.Println() fmt.Println()
fmt.Println(" go-sniffer --[命令]") fmt.Println(" go-sniffer --[commend]")
fmt.Println(" --help 帮助信息") fmt.Println(" --help \"this page\"")
fmt.Println(" --env 环境变量") fmt.Println(" --env \"environment variable\"")
fmt.Println(" --list 插件列表") fmt.Println(" --list \"Plug-in list\"")
fmt.Println(" --ver 版本信息") fmt.Println(" --ver \"version\"")
fmt.Println(" --dev 设备列表") fmt.Println(" --dev \"device\"")
fmt.Println(" [例子]") fmt.Println(" [exp]")
fmt.Println(" go-sniffer --list 查看可抓取的协议") fmt.Println(" go-sniffer --list \"show all plug-in\"")
fmt.Println() fmt.Println()
fmt.Println("==================================================================================") fmt.Println("==================================================================================")
cm.printDevice() cm.printDevice()
fmt.Println("==================================================================================") fmt.Println("==================================================================================")
} }
//打印插件 //print plug-in list
func (cm *Cmd) printPlugList() { func (cm *Cmd) printPlugList() {
l := len(cm.plugHandle.InternalPlugList) l := len(cm.plugHandle.InternalPlugList)
l += len(cm.plugHandle.ExternalPlugList) l += len(cm.plugHandle.ExternalPlugList)
fmt.Println("# 插件数量:"+strconv.Itoa(l)) fmt.Println("# Number of plug-ins : "+strconv.Itoa(l))
} }
//打印设备 //print device
func (cm *Cmd) printDevice() { func (cm *Cmd) printDevice() {
ifaces, err:= net.Interfaces() ifaces, err:= net.Interfaces()
if err != nil { if err != nil {
@ -117,19 +118,19 @@ func (cm *Cmd) printDevice() {
for _,a:=range addrs { for _,a:=range addrs {
if ipnet, ok := a.(*net.IPNet); ok { if ipnet, ok := a.(*net.IPNet); ok {
if ip4 := ipnet.IP.To4(); ip4 != nil { if ip4 := ipnet.IP.To4(); ip4 != nil {
fmt.Println("[设备名] : "+iface.Name+" : "+iface.HardwareAddr.String()+" "+ip4.String()) fmt.Println("[device] : "+iface.Name+" : "+iface.HardwareAddr.String()+" "+ip4.String())
} }
} }
} }
} }
} }
//解析插件需要的参数 //Parameters needed for plug-ins
func (cm *Cmd) parsePlugCmd() { func (cm *Cmd) parsePlugCmd() {
if len(os.Args) < 3 { if len(os.Args) < 3 {
fmt.Println("缺少[插件名]") fmt.Println("not found [Plug-in name]")
fmt.Println("go-sniffer [设备名] [插件名] [插件参数(可选)]") fmt.Println("go-sniffer [device] [plug] [plug's params(optional)]")
os.Exit(1) os.Exit(1)
} }

View File

@ -1,7 +1,6 @@
package core package core
type Core struct{ type Core struct{
//版本信息
Version string Version string
} }
@ -16,13 +15,13 @@ func New() Core {
func (c *Core) Run() { func (c *Core) Run() {
//插件 //new plugin
plug := NewPlug() plug := NewPlug()
//解析参数 //parse commend
cmd := NewCmd(plug) cmd := NewCmd(plug)
cmd.Run() cmd.Run()
//开启抓包 //dispatch
NewDispatch(plug, cmd).Capture() NewDispatch(plug, cmd).Capture()
} }

View File

@ -26,24 +26,24 @@ func NewDispatch(plug *Plug, cmd *Cmd) *Dispatch {
func (d *Dispatch) Capture() { func (d *Dispatch) Capture() {
// Init device //init device
handle, err := pcap.OpenLive(d.device, 65535, false, pcap.BlockForever) handle, err := pcap.OpenLive(d.device, 65535, false, pcap.BlockForever)
if err != nil { if err != nil {
return return
} }
// Set filter //set filter
fmt.Println(d.Plug.BPF) fmt.Println(d.Plug.BPF)
err = handle.SetBPFFilter(d.Plug.BPF) err = handle.SetBPFFilter(d.Plug.BPF)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
// Capture //capture
src := gopacket.NewPacketSource(handle, handle.LinkType()) src := gopacket.NewPacketSource(handle, handle.LinkType())
packets := src.Packets() packets := src.Packets()
// Set up assembly //set up assembly
streamFactory := &ProtocolStreamFactory{ streamFactory := &ProtocolStreamFactory{
dispatch:d, dispatch:d,
} }
@ -51,14 +51,14 @@ func (d *Dispatch) Capture() {
assembler := NewAssembler(streamPool) assembler := NewAssembler(streamPool)
ticker := time.Tick(time.Minute) ticker := time.Tick(time.Minute)
// Loop until ctrl+z //loop until ctrl+z
for { for {
select { select {
case packet := <-packets: case packet := <-packets:
if packet.NetworkLayer() == nil || if packet.NetworkLayer() == nil ||
packet.TransportLayer() == nil || packet.TransportLayer() == nil ||
packet.TransportLayer().LayerType() != layers.LayerTypeTCP { packet.TransportLayer().LayerType() != layers.LayerTypeTCP {
fmt.Println("包不能解析") fmt.Println("ERR : Unknown Packet -_-")
continue continue
} }
tcp := packet.TransportLayer().(*layers.TCP) tcp := packet.TransportLayer().(*layers.TCP)
@ -91,7 +91,7 @@ func (m *ProtocolStreamFactory) New(net, transport gopacket.Flow) tcpassembly.St
} }
//new stream //new stream
fmt.Println("# 新连接:", net, transport) fmt.Println("# Start new stream:", net, transport)
//decode packet //decode packet
go m.dispatch.Plug.ResolveStream(net, transport, &(stm.r)) go m.dispatch.Plug.ResolveStream(net, transport, &(stm.r))

View File

@ -16,36 +16,26 @@ import (
type Plug struct { type Plug struct {
//当前插件路径
dir string dir string
//解析包
ResolveStream func(net gopacket.Flow, transport gopacket.Flow, r io.Reader) ResolveStream func(net gopacket.Flow, transport gopacket.Flow, r io.Reader)
//BPF
BPF string BPF string
//内部插件列表
InternalPlugList map[string]PlugInterface InternalPlugList map[string]PlugInterface
//外部插件列表
ExternalPlugList map[string]ExternalPlug ExternalPlugList map[string]ExternalPlug
} }
// 内部插件必须实现此接口 // All internal plug-ins must implement this interface
// ResolvePacket - 包入口 // ResolvePacket - entry
// BPFFilter - 设置BPF规则,例如mysql: (tcp and port 3306) // BPFFilter - set BPF, like: mysql(tcp and port 3306)
// SetFlag - 设置参数 // SetFlag - plug-in params
// Version - 返回插件版本,例如0.1.0 // Version - plug-in version
type PlugInterface interface { type PlugInterface interface {
//解析流
ResolveStream(net gopacket.Flow, transport gopacket.Flow, r io.Reader) ResolveStream(net gopacket.Flow, transport gopacket.Flow, r io.Reader)
//BPF
BPFFilter() string BPFFilter() string
//设置插件需要的参数
SetFlag([]string) SetFlag([]string)
//获取版本
Version() string Version() string
} }
//外部插件
type ExternalPlug struct { type ExternalPlug struct {
Name string Name string
Version string Version string
@ -54,24 +44,17 @@ type ExternalPlug struct {
SetFlag func([]string) SetFlag func([]string)
} }
//实例化
func NewPlug() *Plug { func NewPlug() *Plug {
var p Plug var p Plug
//设置默认插件目录
p.dir, _ = filepath.Abs( "./plug/") p.dir, _ = filepath.Abs( "./plug/")
//加载内部插件
p.LoadInternalPlugList() p.LoadInternalPlugList()
//加载外部插件
p.LoadExternalPlugList() p.LoadExternalPlugList()
return &p return &p
} }
//加载内部插件
func (p *Plug) LoadInternalPlugList() { func (p *Plug) LoadInternalPlugList() {
list := make(map[string]PlugInterface) list := make(map[string]PlugInterface)
@ -91,12 +74,11 @@ func (p *Plug) LoadInternalPlugList() {
p.InternalPlugList = list p.InternalPlugList = list
} }
//加载外部so后缀插件
func (p *Plug) LoadExternalPlugList() { func (p *Plug) LoadExternalPlugList() {
dir, err := ioutil.ReadDir(p.dir) dir, err := ioutil.ReadDir(p.dir)
if err != nil { if err != nil {
panic(p.dir + "不存在,或者无权访问") panic(p.dir + "not found")
} }
p.ExternalPlugList = make(map[string]ExternalPlug) p.ExternalPlugList = make(map[string]ExternalPlug)
@ -141,17 +123,15 @@ func (p *Plug) LoadExternalPlugList() {
} }
} }
//改变插件地址
func (p *Plug) ChangePath(dir string) { func (p *Plug) ChangePath(dir string) {
p.dir = dir p.dir = dir
} }
//打印插件列表
func (p *Plug) PrintList() { func (p *Plug) PrintList() {
//Print Internal Plug //Print Internal Plug
for inPlugName, _ := range p.InternalPlugList { for inPlugName, _ := range p.InternalPlugList {
fmt.Println("内部插件:"+inPlugName) fmt.Println("internal plug : "+inPlugName)
} }
//split //split
@ -159,11 +139,10 @@ func (p *Plug) PrintList() {
//print External Plug //print External Plug
for exPlugName, _ := range p.ExternalPlugList { for exPlugName, _ := range p.ExternalPlugList {
fmt.Println("外部插件:"+exPlugName) fmt.Println("external plug : "+exPlugName)
} }
} }
//选择当前使用的插件 && 加载插件
func (p *Plug) SetOption(plugName string, plugParams []string) { func (p *Plug) SetOption(plugName string, plugParams []string) {
//Load Internal Plug //Load Internal Plug

Binary file not shown.

Before

Width:  |  Height:  |  Size: 669 KiB

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

View File

@ -21,8 +21,8 @@ const (
) )
type H struct { type H struct {
port int//端口 port int
version string//插件版本 version string
} }
var hp *H var hp *H
@ -81,7 +81,7 @@ func (m *H) SetFlag(flg []string) {
return return
} }
if c >> 1 == 0 { if c >> 1 == 0 {
fmt.Println("http参数数量不正确!") fmt.Println("ERR : Http Number of parameters")
os.Exit(1) os.Exit(1)
} }
for i:=0;i<c;i=i+2 { for i:=0;i<c;i=i+2 {
@ -93,14 +93,14 @@ func (m *H) SetFlag(flg []string) {
port, err := strconv.Atoi(val); port, err := strconv.Atoi(val);
m.port = port m.port = port
if err != nil { if err != nil {
panic("端口数不正确") panic("ERR : port")
} }
if port < 0 || port > 65535 { if port < 0 || port > 65535 {
panic("参数不正确: 端口范围(0-65535)") panic("ERR : port(0-65535)")
} }
break break
default: default:
panic("参数不正确") panic("ERR : mysql's params")
} }
} }
} }

View File

@ -27,12 +27,12 @@ type stream struct {
type packet struct { type packet struct {
isClientFlow bool //客户端->服务器端流 isClientFlow bool //client->server
messageLength int //总消息大小 messageLength int
requestID int //此消息的标识符 requestID int
responseTo int //从原始请求的requestID responseTo int
opCode int //请求类型 opCode int //request type
payload io.Reader payload io.Reader
} }
@ -56,7 +56,7 @@ func (m *Mongodb) SetFlag(flg []string) {
return return
} }
if c >> 1 != 1 { if c >> 1 != 1 {
panic("Mongodb参数数量不正确!") panic("ERR : Mongodb Number of parameters")
} }
for i:=0;i<c;i=i+2 { for i:=0;i<c;i=i+2 {
key := flg[i] key := flg[i]
@ -66,15 +66,15 @@ func (m *Mongodb) SetFlag(flg []string) {
case CmdPort: case CmdPort:
p, err := strconv.Atoi(val); p, err := strconv.Atoi(val);
if err != nil { if err != nil {
panic("端口数不正确") panic("ERR : port")
} }
mongodbInstance.port = p mongodbInstance.port = p
if p < 0 || p > 65535 { if p < 0 || p > 65535 {
panic("参数不正确: 端口范围(0-65535)") panic("ERR : port(0-65535)")
} }
break break
default: default:
panic("参数不正确") panic("ERR : mysql's params")
} }
} }
} }
@ -125,10 +125,10 @@ func (m *Mongodb) newPacket(net, transport gopacket.Flow, r io.Reader) *packet {
//stream close //stream close
if err == io.EOF { if err == io.EOF {
fmt.Println(net, transport, " 关闭") fmt.Println(net, transport, " close")
return nil return nil
} else if err != nil { } else if err != nil {
fmt.Println("流解析错误", net, transport, ":", err) fmt.Println("ERR : Unknown stream", net, transport, ":", err)
return nil return nil
} }
@ -173,7 +173,7 @@ func (stm *stream) resolveClientPacket(pk *packet) {
_ = zero _ = zero
_ = flags _ = flags
msg = fmt.Sprintf(" [更新] [集合:%s] 语句: %v %v", msg = fmt.Sprintf(" [Update] [coll:%s] %v %v",
fullCollectionName, fullCollectionName,
selector, selector,
update, update,
@ -185,7 +185,7 @@ func (stm *stream) resolveClientPacket(pk *packet) {
command := ReadBson2Json(pk.payload) command := ReadBson2Json(pk.payload)
_ = flags _ = flags
msg = fmt.Sprintf(" [插入] [集合:%s] 语句: %v", msg = fmt.Sprintf(" [Insert] [coll:%s] %v",
fullCollectionName, fullCollectionName,
command, command,
) )
@ -202,7 +202,7 @@ func (stm *stream) resolveClientPacket(pk *packet) {
command := ReadBson2Json(pk.payload) command := ReadBson2Json(pk.payload)
selector := ReadBson2Json(pk.payload) selector := ReadBson2Json(pk.payload)
msg = fmt.Sprintf(" [查询] [集合:%s] 语句: %v %v", msg = fmt.Sprintf(" [Query] [coll:%s] %v %v",
fullCollectionName, fullCollectionName,
command, command,
selector, selector,
@ -215,7 +215,7 @@ func (stm *stream) resolveClientPacket(pk *packet) {
commandArgs := ReadBson2Json(pk.payload) commandArgs := ReadBson2Json(pk.payload)
inputDocs := ReadBson2Json(pk.payload) inputDocs := ReadBson2Json(pk.payload)
msg = fmt.Sprintf(" [命令] [数据库:%s] [命令名:%s] %v %v %v", msg = fmt.Sprintf(" [Commend] [DB:%s] [Cmd:%s] %v %v %v",
database, database,
commandName, commandName,
metaData, metaData,
@ -230,7 +230,7 @@ func (stm *stream) resolveClientPacket(pk *packet) {
cursorId := ReadInt64(pk.payload) cursorId := ReadInt64(pk.payload)
_ = zero _ = zero
msg = fmt.Sprintf(" [查询更多] [集合:%s] [回复数量:%v] [游标:%v]", msg = fmt.Sprintf(" [Query more] [coll:%s] [num of reply:%v] [cursor:%v]",
fullCollectionName, fullCollectionName,
numberToReturn, numberToReturn,
cursorId, cursorId,
@ -244,7 +244,7 @@ func (stm *stream) resolveClientPacket(pk *packet) {
_ = zero _ = zero
_ = flags _ = flags
msg = fmt.Sprintf(" [删除] [集合:%s] 语句: %v", msg = fmt.Sprintf(" [Delete] [coll:%s] %v",
fullCollectionName, fullCollectionName,
selector, selector,
) )

View File

@ -1,12 +1,12 @@
package build package build
const ( const (
ComQueryRequestPacket string = "【查询】" ComQueryRequestPacket string = "【Query】"
OkPacket string = "【正确】" OkPacket string = "【Ok】"
ErrorPacket string = "【错误】" ErrorPacket string = "【Err】"
PreparePacket string = "【预处理】" PreparePacket string = "【Pretreatment】"
SendClientHandshakePacket string = "【用户认证】" SendClientHandshakePacket string = "【User Auth】"
SendServerHandshakePacket string = "【登录认证】" SendServerHandshakePacket string = "【Login】"
) )
const ( const (

View File

@ -22,9 +22,9 @@ const (
) )
type Mysql struct { type Mysql struct {
port int//端口 port int
version string//插件版本 version string
source map[string]*stream//流 source map[string]*stream
} }
type stream struct { type stream struct {
@ -101,7 +101,7 @@ func (m *Mysql) SetFlag(flg []string) {
return return
} }
if c >> 1 == 0 { if c >> 1 == 0 {
fmt.Println("Mysql参数数量不正确!") fmt.Println("ERR : Mysql Number of parameters")
os.Exit(1) os.Exit(1)
} }
for i:=0;i<c;i=i+2 { for i:=0;i<c;i=i+2 {
@ -113,14 +113,14 @@ func (m *Mysql) SetFlag(flg []string) {
port, err := strconv.Atoi(val); port, err := strconv.Atoi(val);
m.port = port m.port = port
if err != nil { if err != nil {
panic("端口数不正确") panic("ERR : port")
} }
if port < 0 || port > 65535 { if port < 0 || port > 65535 {
panic("参数不正确: 端口范围(0-65535)") panic("ERR : port(0-65535)")
} }
break break
default: default:
panic("参数不正确") panic("ERR : mysql's params")
} }
} }
} }
@ -137,10 +137,10 @@ func (m *Mysql) newPacket(net, transport gopacket.Flow, r io.Reader) *packet {
//close stream //close stream
if err == io.EOF { if err == io.EOF {
fmt.Println(net, transport, " 关闭") fmt.Println(net, transport, " close")
return nil return nil
} else if err != nil { } else if err != nil {
fmt.Println("错误流:", net, transport, ":", err) fmt.Println("ERR : Unknown stream", net, transport, ":", err)
} }
//generate new packet //generate new packet
@ -165,7 +165,7 @@ func (m *Mysql) resolvePacketTo(r io.Reader, w io.Writer) (uint8, error) {
if n == 0 && err == io.EOF { if n == 0 && err == io.EOF {
return 0, io.EOF return 0, io.EOF
} }
return 0, errors.New("错误流") return 0, errors.New("ERR : Unknown stream")
} }
length := int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16) length := int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16)
@ -174,9 +174,9 @@ func (m *Mysql) resolvePacketTo(r io.Reader, w io.Writer) (uint8, error) {
seq = header[3] seq = header[3]
if n, err := io.CopyN(w, r, int64(length)); err != nil { if n, err := io.CopyN(w, r, int64(length)); err != nil {
return 0, errors.New("错误流") return 0, errors.New("ERR : Unknown stream")
} else if n != int64(length) { } else if n != int64(length) {
return 0, errors.New("错误流") return 0, errors.New("ERR : Unknown stream")
} else { } else {
return seq, nil return seq, nil
} }
@ -222,7 +222,7 @@ func (stm *stream) resolveServerPacket(payload []byte, seq int) {
errorCode := int(binary.LittleEndian.Uint16(payload[1:3])) errorCode := int(binary.LittleEndian.Uint16(payload[1:3]))
errorMsg,_ := ReadStringFromByte(payload[4:]) errorMsg,_ := ReadStringFromByte(payload[4:])
msg = GetNowStr(false)+"%s 错误代码:%s,错误信息:%s" msg = GetNowStr(false)+"%s Err code:%s,Err msg:%s"
msg = fmt.Sprintf(msg, ErrorPacket, strconv.Itoa(errorCode), strings.TrimSpace(errorMsg)) msg = fmt.Sprintf(msg, ErrorPacket, strconv.Itoa(errorCode), strings.TrimSpace(errorMsg))
case 0x00: case 0x00:
@ -230,7 +230,7 @@ func (stm *stream) resolveServerPacket(payload []byte, seq int) {
l,_ := LengthBinary(payload[pos:]) l,_ := LengthBinary(payload[pos:])
affectedRows := int(l) affectedRows := int(l)
msg += GetNowStr(false)+"%s 影响行数:%s" msg += GetNowStr(false)+"%s Effect Row:%s"
msg = fmt.Sprintf(msg, OkPacket, strconv.Itoa(affectedRows)) msg = fmt.Sprintf(msg, OkPacket, strconv.Itoa(affectedRows))
default: default:
@ -250,7 +250,7 @@ func (stm *stream) resolveClientPacket(payload []byte, seq int) {
msg = fmt.Sprintf("USE %s;\n", payload[1:]) msg = fmt.Sprintf("USE %s;\n", payload[1:])
case COM_DROP_DB: case COM_DROP_DB:
msg = fmt.Sprintf("删除数据库 %s;\n", payload[1:]) msg = fmt.Sprintf("Drop DB %s;\n", payload[1:])
case COM_CREATE_DB, COM_QUERY: case COM_CREATE_DB, COM_QUERY:
statement := string(payload[1:]) statement := string(payload[1:])
@ -259,17 +259,17 @@ func (stm *stream) resolveClientPacket(payload []byte, seq int) {
serverPacket := stm.findStmtPacket(stm.packets, seq+1) serverPacket := stm.findStmtPacket(stm.packets, seq+1)
if serverPacket == nil { if serverPacket == nil {
log.Println("找不到预处理响应包") log.Println("ERR : Not found stm packet")
} }
//获取响应包中预处理id //fetch stm id
stmtID := binary.LittleEndian.Uint32(serverPacket.payload[1:5]) stmtID := binary.LittleEndian.Uint32(serverPacket.payload[1:5])
stmt := &Stmt{ stmt := &Stmt{
ID: stmtID, ID: stmtID,
Query: string(payload[1:]), Query: string(payload[1:]),
} }
//记录预处理语句 //record stm sql
stm.stmtMap[stmtID] = stmt stm.stmtMap[stmtID] = stmt
stmt.FieldCount = binary.LittleEndian.Uint16(serverPacket.payload[5:7]) stmt.FieldCount = binary.LittleEndian.Uint16(serverPacket.payload[5:7])
stmt.ParamCount = binary.LittleEndian.Uint16(serverPacket.payload[7:9]) stmt.ParamCount = binary.LittleEndian.Uint16(serverPacket.payload[7:9])
@ -305,19 +305,19 @@ func (stm *stream) resolveClientPacket(payload []byte, seq int) {
var stmt *Stmt var stmt *Stmt
var ok bool var ok bool
if stmt, ok = stm.stmtMap[stmtID]; ok == false { if stmt, ok = stm.stmtMap[stmtID]; ok == false {
log.Println("未发现预处理id: ", stmtID) log.Println("ERR : Not found stm id", stmtID)
} }
//参数 //params
pos += 5 pos += 5
if stmt.ParamCount > 0 { if stmt.ParamCount > 0 {
//空位图Null-Bitmap长度 = (参数数量 + 7) / 8 字节 //Null-Bitmaplen = (paramsCount + 7) / 8 byte
step := int((stmt.ParamCount + 7) / 8) step := int((stmt.ParamCount + 7) / 8)
nullBitmap := payload[pos : pos+step] nullBitmap := payload[pos : pos+step]
pos += step pos += step
//参数分隔标志 //Parameter separator
flag := payload[pos] flag := payload[pos]
pos++ pos++
@ -325,19 +325,18 @@ func (stm *stream) resolveClientPacket(payload []byte, seq int) {
var pTypes []byte var pTypes []byte
var pValues []byte var pValues []byte
//如果参数分隔标志值为1 //if flag == 1
//n 每个参数的类型值(长度 = 参数数量 * 2 字节) //n len = paramsCount * 2 byte
//n 每个参数的值
if flag == 1 { if flag == 1 {
pTypes = payload[pos : pos+int(stmt.ParamCount)*2] pTypes = payload[pos : pos+int(stmt.ParamCount)*2]
pos += int(stmt.ParamCount) * 2 pos += int(stmt.ParamCount) * 2
pValues = payload[pos:] pValues = payload[pos:]
} }
//绑定参数 //bind params
err := stmt.BindArgs(nullBitmap, pTypes, pValues) err := stmt.BindArgs(nullBitmap, pTypes, pValues)
if err != nil { if err != nil {
log.Println("预处理绑定参数失败: ", err) log.Println("ERR : Could not bind params", err)
} }
} }
msg = string(stmt.WriteToText()) msg = string(stmt.WriteToText())

View File

@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"math" "math"
"strings" "strings"
"errors" "errors"
) )
@ -23,7 +22,7 @@ func (stmt *Stmt) WriteToText() []byte {
var buf bytes.Buffer var buf bytes.Buffer
str := fmt.Sprintf("预处理编号[%d]: '%s';\n", stmt.ID, stmt.Query) str := fmt.Sprintf("Stm id[%d]: '%s';\n", stmt.ID, stmt.Query)
buf.WriteString(str) buf.WriteString(str)
for i := 0; i < int(stmt.ParamCount); i++ { for i := 0; i < int(stmt.ParamCount); i++ {
@ -40,7 +39,7 @@ func (stmt *Stmt) WriteToText() []byte {
buf.WriteString(str) buf.WriteString(str)
} }
str = fmt.Sprintf("执行预处理[%d]: ", stmt.ID) str = fmt.Sprintf("Execute stm id[%d]: ", stmt.ID)
buf.WriteString(str) buf.WriteString(str)
for i := 0; i < int(stmt.ParamCount); i++ { for i := 0; i < int(stmt.ParamCount); i++ {
if i == 0 { if i == 0 {
@ -54,7 +53,7 @@ func (stmt *Stmt) WriteToText() []byte {
} }
buf.WriteString(";\n") buf.WriteString(";\n")
str = fmt.Sprintf("丢弃预处理[%d];\n", stmt.ID) str = fmt.Sprintf("Drop stm id[%d];\n", stmt.ID)
buf.WriteString(str) buf.WriteString(str)
return buf.Bytes() return buf.Bytes()
@ -72,13 +71,11 @@ func (stmt *Stmt) BindArgs(nullBitmap, paramTypes, paramValues []byte) error {
for i := 0; i < int(stmt.ParamCount); i++ { for i := 0; i < int(stmt.ParamCount); i++ {
//判断参数是否为null
if nullBitmap[i>>3]&(1<<(uint(i)%8)) > 0 { if nullBitmap[i>>3]&(1<<(uint(i)%8)) > 0 {
args[i] = nil args[i] = nil
continue continue
} }
//参数类型
typ := paramTypes[i<<1] typ := paramTypes[i<<1]
unsigned := (paramTypes[(i<<1)+1] & 0x80) > 0 unsigned := (paramTypes[(i<<1)+1] & 0x80) > 0
@ -168,7 +165,7 @@ func (stmt *Stmt) BindArgs(nullBitmap, paramTypes, paramValues []byte) error {
continue continue
} }
default: default:
return errors.New(fmt.Sprintf("预处理未知类型 %d", typ)) return errors.New(fmt.Sprintf("ERR : Unknown stm type %d", typ))
} }
} }
return nil return nil

View File

@ -31,19 +31,15 @@ func NewInstance() *Redis{
return redis return redis
} }
/**
解析流
*/
func (red Redis) ResolveStream(net, transport gopacket.Flow, r io.Reader) { func (red Redis) ResolveStream(net, transport gopacket.Flow, r io.Reader) {
//只解析clint发出去的包
buf := bufio.NewReader(r) buf := bufio.NewReader(r)
var cmd string var cmd string
var cmdCount = 0 var cmdCount = 0
for { for {
line, _, _ := buf.ReadLine() line, _, _ := buf.ReadLine()
//判断链接是否断开
if len(line) == 0 { if len(line) == 0 {
buff := make([]byte, 1) buff := make([]byte, 1)
_, err := r.Read(buff) _, err := r.Read(buff)
@ -53,17 +49,17 @@ func (red Redis) ResolveStream(net, transport gopacket.Flow, r io.Reader) {
} }
} }
//过滤无用数据 //Filtering useless data
if !strings.HasPrefix(string(line), "*") { if !strings.HasPrefix(string(line), "*") {
continue continue
} }
//过滤服务器返回数据 //Do not display
if strings.EqualFold(transport.Src().String(), strconv.Itoa(red.port)) == true { if strings.EqualFold(transport.Src().String(), strconv.Itoa(red.port)) == true {
continue continue
} }
//解析 //run
l := string(line[1]) l := string(line[1])
cmdCount, _ = strconv.Atoi(l) cmdCount, _ = strconv.Atoi(l)
cmd = "" cmd = ""
@ -87,7 +83,7 @@ func (red *Redis) SetFlag(flg []string) {
return return
} }
if c >> 1 != 1 { if c >> 1 != 1 {
panic("Redis参数数量不正确!") panic("ERR : Redis num of params")
} }
for i:=0;i<c;i=i+2 { for i:=0;i<c;i=i+2 {
key := flg[i] key := flg[i]
@ -98,14 +94,14 @@ func (red *Redis) SetFlag(flg []string) {
port, err := strconv.Atoi(val); port, err := strconv.Atoi(val);
redis.port = port redis.port = port
if err != nil { if err != nil {
panic("端口数不正确") panic("ERR : Port error")
} }
if port < 0 || port > 65535 { if port < 0 || port > 65535 {
panic("参数不正确: 端口范围(0-65535)") panic("ERR : Port(0-65535)")
} }
break break
default: default:
panic("参数不正确") panic("ERR : redis's params")
} }
} }
} }
@ -114,13 +110,13 @@ func (red *Redis) SetFlag(flg []string) {
BPFFilter BPFFilter
*/ */
func (red *Redis) BPFFilter() string { func (red *Redis) BPFFilter() string {
return "tcp and port "+strconv.Itoa(redis.port); return "tcp and port "+strconv.Itoa(redis.port)
} }
/** /**
Version Version
*/ */
func (red *Redis) Version() string { func (red *Redis) Version() string {
return red.version; return red.version
} }