npcap.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. package network
  2. import (
  3. "bytes"
  4. "fmt"
  5. "fyne.io/fyne/v2/data/binding"
  6. "gbase/glog"
  7. "github.com/google/gopacket"
  8. "github.com/google/gopacket/layers"
  9. "github.com/google/gopacket/pcap"
  10. "os"
  11. "regexp"
  12. "strings"
  13. "time"
  14. )
  15. func GetLoopbackInterface() (loopbackInterfaceName string, err error) {
  16. // 获取所有网络接口
  17. interfaces, err := pcap.FindAllDevs()
  18. if err != nil {
  19. glog.XWarning(fmt.Sprintf("pcap.FindAllDevs error : %v\n", err))
  20. return
  21. }
  22. found := false
  23. // 遍历所有接口,找到环回接口
  24. for _, iface := range interfaces {
  25. if isLoopback(iface) {
  26. //fmt.Printf("Name: %s, Description: %s\n", iface.Name, iface.Description)
  27. loopbackInterfaceName = iface.Name
  28. found = true
  29. break
  30. }
  31. }
  32. if !found {
  33. glog.XWarning("No loopback interface found")
  34. return loopbackInterfaceName, fmt.Errorf("No loopback interface found")
  35. }
  36. return loopbackInterfaceName, nil
  37. }
  38. func GetAllLoopbackInterface() (interfaceNames map[string]string, err error) {
  39. interfaceNames = map[string]string{}
  40. // 获取所有网络接口
  41. interfaces, err := pcap.FindAllDevs()
  42. if err != nil {
  43. glog.XWarning(fmt.Sprintf("pcap.FindAllDevs error : %v\n", err))
  44. return interfaceNames, err
  45. }
  46. cp := regexp.MustCompile(`\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}`)
  47. for _, face := range interfaces {
  48. addr := ""
  49. for _, address := range face.Addresses {
  50. ret := cp.FindString(address.IP.String())
  51. if len(ret) > 1 {
  52. addr = address.IP.String()
  53. break
  54. }
  55. }
  56. if len(addr) < 1 {
  57. continue
  58. }
  59. //println(face.Description + "-----------------" + addr)
  60. interfaceNames[face.Name] = addr
  61. }
  62. return interfaceNames, nil
  63. }
  64. // 判断接口是否是环回接口
  65. func isLoopback(iface pcap.Interface) bool {
  66. for _, address := range iface.Addresses {
  67. if address.IP.IsLoopback() {
  68. return true
  69. }
  70. }
  71. return false
  72. }
  73. func Sniffer(interfaceName, sqlName, ip string, port int, dbLog binding.String) (err error) {
  74. // 打开环回接口
  75. handle, err := pcap.OpenLive(interfaceName, 1600, true, pcap.BlockForever)
  76. if err != nil {
  77. glog.XWarning(fmt.Sprintf("pcap.OpenLive %v error : %v\n", interfaceName, err))
  78. return err
  79. }
  80. defer handle.Close()
  81. // 设置过滤器,只捕获 TCP 1433 端口(SQL Server 端口)的数据包
  82. filter := fmt.Sprintf("tcp and port %v", port)
  83. err = handle.SetBPFFilter(filter)
  84. if err != nil {
  85. glog.XWarning(fmt.Sprintf("handle.SetBPFFilter error : %v\n", err))
  86. return err
  87. }
  88. glog.XWarning(fmt.Sprintf("Listening on %s\n", interfaceName))
  89. ip = strings.ReplaceAll(ip, ".", "_")
  90. filename := fmt.Sprintf("%v%v.txt", ip, sqlName)
  91. file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
  92. if err != nil {
  93. glog.XWarning(fmt.Sprintf("os.OpenFile %v error : %v\n", filename, err))
  94. return
  95. }
  96. defer file.Close()
  97. // 正则表达式匹配 MySQL 语句
  98. re := regexp.MustCompile(`(SELECT|INSERT|UPDATE|DELETE)\b.*`)
  99. // 创建数据包源
  100. packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
  101. for packet := range packetSource.Packets() {
  102. sqlStatement, isRequest, err := processPacket(packet, port)
  103. if err == nil && len(sqlStatement) > 2 {
  104. sqlStatement = strings.TrimSpace(sqlStatement)
  105. if isRequest {
  106. ret := re.FindAllStringSubmatch(sqlStatement, 1)
  107. if len(ret) > 0 {
  108. currentLog, _ := dbLog.Get()
  109. dbLog.Set(
  110. fmt.Sprintf("%v %v\n%s",
  111. time.Now().Format("2006-01-02 15:04:05"),
  112. ret[0][0],
  113. currentLog,
  114. ),
  115. )
  116. file.WriteString(time.Now().Format("2006-01-02 03:04:05") + " " + ret[0][0] + "\n")
  117. }
  118. } else {
  119. // 处理响应数据,去除乱码和无用字符串
  120. cleanResponse := cleanString(sqlStatement)
  121. if cleanResponse != "" {
  122. file.WriteString(time.Now().Format("2006-01-02 15:04:05") + " Response: " + sqlStatement + "\n")
  123. }
  124. }
  125. }
  126. }
  127. return nil
  128. }
  129. func processPacket(packet gopacket.Packet, port int) (sqlStatement string, isRequest bool, err error) {
  130. isRequest = false
  131. // 检测是否存在任何错误
  132. errs := packet.ErrorLayer()
  133. if err != nil {
  134. glog.XWarning(fmt.Sprintf("decoding packet error : %v\n", errs.Error()))
  135. return
  136. }
  137. // 解析 TCP 层
  138. tcpLayer := packet.Layer(layers.LayerTypeTCP)
  139. if tcpLayer == nil {
  140. return
  141. }
  142. tcp, _ := tcpLayer.(*layers.TCP)
  143. isRequest = int(tcp.DstPort) == port // 检查目标端口是否为 MySQL 端口以确定是否为请求
  144. // 打印应用层/有效载荷
  145. applicationLayer := packet.ApplicationLayer()
  146. if applicationLayer == nil {
  147. return
  148. }
  149. payload := applicationLayer.Payload()
  150. sqlStatement = extractSQLFromPayload(payload)
  151. if sqlStatement != "" {
  152. return sqlStatement, isRequest, nil
  153. }
  154. return sqlStatement, isRequest, nil
  155. }
  156. func extractSQLFromPayload(payload []byte) string {
  157. // 将字节转换为字符串
  158. data := string(payload)
  159. data = strings.ReplaceAll(data, "\r", "")
  160. data = strings.ReplaceAll(data, "\n", "")
  161. data = strings.ReplaceAll(data, "\r\n", "")
  162. data = strings.ReplaceAll(data, "\t", "")
  163. // 检查是否包含 SQL 关键字
  164. if containsSQLKeyword(data) {
  165. return data
  166. }
  167. return ""
  168. }
  169. func containsSQLKeyword(data string) bool {
  170. keywords := []string{"INSERT", "UPDATE", "DELETE", "SELECT"}
  171. for _, keyword := range keywords {
  172. if strings.Contains(strings.ToUpper(data), keyword) {
  173. return true
  174. }
  175. }
  176. return false
  177. }
  178. func cleanString(input string) string {
  179. var buffer bytes.Buffer
  180. for _, r := range input {
  181. if r >= 32 && r <= 126 { // 保留可打印的 ASCII 字符
  182. buffer.WriteRune(r)
  183. }
  184. }
  185. cleaned := buffer.String()
  186. // 进一步清理无用的空格和特殊字符
  187. cleaned = strings.TrimSpace(cleaned)
  188. cleaned = strings.ReplaceAll(cleaned, "\r", "")
  189. cleaned = strings.ReplaceAll(cleaned, "\n", "")
  190. cleaned = strings.ReplaceAll(cleaned, "\t", "")
  191. return cleaned
  192. }