-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathparser.go
117 lines (90 loc) · 2.33 KB
/
parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"golang.org/x/exp/slog"
)
const (
snapshotLen int32 = 1024
prom = false
timeout = 1 * time.Millisecond
msgQuery = 'Q'
)
// capture listen tcp traffic with filter and parse SQL-query.
func capture(device string, port int, highlight bool) error {
handle, err := pcap.OpenLive(device, snapshotLen, prom, timeout)
if err != nil {
return fmt.Errorf("open live: %w", err)
}
defer handle.Close()
filter := fmt.Sprintf("tcp and port %d", port)
if err := handle.SetBPFFilter(filter); err != nil {
return fmt.Errorf("set filter: %w", err)
}
slog.Info("start capturing", slog.String("filter", filter), slog.String("device", device))
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
packetSource.DecodeOptions.Lazy = true
packetSource.DecodeOptions.NoCopy = true
for packet := range packetSource.Packets() {
if packet == nil {
continue
}
tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer == nil {
continue
}
tcp, ok := tcpLayer.(*layers.TCP)
if !ok {
slog.Warn("could`t cast packet layer")
continue
}
if tcp.DstPort == layers.TCPPort(port) {
buf := bytes.NewBuffer(tcp.Payload)
msgType, err := buf.ReadByte()
if err != nil {
continue
}
if msgType == msgQuery {
query := extractQuery(buf)
if highlight {
highlightSQL(query)
} else {
fmt.Println(query)
}
fmt.Println("- - - ")
}
}
}
return nil
}
// extractQuery extract SQL-query from pocket payload.
func extractQuery(buf io.Reader) string {
const lenMsgSize = 4
size := make([]byte, lenMsgSize)
if _, err := buf.Read(size); err != nil {
slog.Error("failed timeout read size", err)
}
payload := make([]byte, int32(binary.BigEndian.Uint32(size))-lenMsgSize)
if _, err := buf.Read(payload); err != nil {
slog.Error("failed timeout read payload", err)
}
return string(payload[:len(payload)-1])
}
// deviceList provide network device list.
func deviceList() error {
devices, err := pcap.FindAllDevs()
if err != nil {
return fmt.Errorf("find all devs: %w", err)
}
fmt.Println("network device list:")
for i := range devices {
fmt.Println(devices[i].Name)
}
return nil
}