package network import ( "bytes" "fmt" "fyne.io/fyne/v2/data/binding" "gbase/glog" "github.com/google/gopacket" "github.com/google/gopacket/layers" "github.com/google/gopacket/pcap" "os" "regexp" "strings" "time" ) func GetLoopbackInterface() (loopbackInterfaceName string, err error) { // 获取所有网络接口 interfaces, err := pcap.FindAllDevs() if err != nil { glog.XWarning(fmt.Sprintf("pcap.FindAllDevs error : %v\n", err)) return } found := false // 遍历所有接口,找到环回接口 for _, iface := range interfaces { if isLoopback(iface) { //fmt.Printf("Name: %s, Description: %s\n", iface.Name, iface.Description) loopbackInterfaceName = iface.Name found = true break } } if !found { glog.XWarning("No loopback interface found") return loopbackInterfaceName, fmt.Errorf("No loopback interface found") } return loopbackInterfaceName, nil } func GetAllLoopbackInterface() (interfaceNames map[string]string, err error) { interfaceNames = map[string]string{} // 获取所有网络接口 interfaces, err := pcap.FindAllDevs() if err != nil { glog.XWarning(fmt.Sprintf("pcap.FindAllDevs error : %v\n", err)) return interfaceNames, err } cp := regexp.MustCompile(`\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}`) for _, face := range interfaces { addr := "" for _, address := range face.Addresses { ret := cp.FindString(address.IP.String()) if len(ret) > 1 { addr = address.IP.String() break } } if len(addr) < 1 { continue } //println(face.Description + "-----------------" + addr) interfaceNames[face.Name] = addr } return interfaceNames, nil } // 判断接口是否是环回接口 func isLoopback(iface pcap.Interface) bool { for _, address := range iface.Addresses { if address.IP.IsLoopback() { return true } } return false } func Sniffer(interfaceName, sqlName, ip string, port int, dbLog binding.String) (err error) { // 打开环回接口 handle, err := pcap.OpenLive(interfaceName, 1600, true, pcap.BlockForever) if err != nil { glog.XWarning(fmt.Sprintf("pcap.OpenLive %v error : %v\n", interfaceName, err)) return err } defer handle.Close() // 设置过滤器,只捕获 TCP 1433 端口(SQL Server 端口)的数据包 filter := fmt.Sprintf("tcp and port %v", port) err = handle.SetBPFFilter(filter) if err != nil { glog.XWarning(fmt.Sprintf("handle.SetBPFFilter error : %v\n", err)) return err } glog.XWarning(fmt.Sprintf("Listening on %s\n", interfaceName)) ip = strings.ReplaceAll(ip, ".", "_") filename := fmt.Sprintf("%v%v.txt", ip, sqlName) file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { glog.XWarning(fmt.Sprintf("os.OpenFile %v error : %v\n", filename, err)) return } defer file.Close() // 正则表达式匹配 MySQL 语句 re := regexp.MustCompile(`(SELECT|INSERT|UPDATE|DELETE)\b.*`) // 创建数据包源 packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { sqlStatement, isRequest, err := processPacket(packet, port) if err == nil && len(sqlStatement) > 2 { sqlStatement = strings.TrimSpace(sqlStatement) if isRequest { ret := re.FindAllStringSubmatch(sqlStatement, 1) if len(ret) > 0 { currentLog, _ := dbLog.Get() dbLog.Set( fmt.Sprintf("%v %v\n%s", time.Now().Format("2006-01-02 15:04:05"), ret[0][0], currentLog, ), ) file.WriteString(time.Now().Format("2006-01-02 03:04:05") + " " + ret[0][0] + "\n") } } else { // 处理响应数据,去除乱码和无用字符串 cleanResponse := cleanString(sqlStatement) if cleanResponse != "" { file.WriteString(time.Now().Format("2006-01-02 15:04:05") + " Response: " + sqlStatement + "\n") } } } } return nil } func processPacket(packet gopacket.Packet, port int) (sqlStatement string, isRequest bool, err error) { isRequest = false // 检测是否存在任何错误 errs := packet.ErrorLayer() if err != nil { glog.XWarning(fmt.Sprintf("decoding packet error : %v\n", errs.Error())) return } // 解析 TCP 层 tcpLayer := packet.Layer(layers.LayerTypeTCP) if tcpLayer == nil { return } tcp, _ := tcpLayer.(*layers.TCP) isRequest = int(tcp.DstPort) == port // 检查目标端口是否为 MySQL 端口以确定是否为请求 // 打印应用层/有效载荷 applicationLayer := packet.ApplicationLayer() if applicationLayer == nil { return } payload := applicationLayer.Payload() sqlStatement = extractSQLFromPayload(payload) if sqlStatement != "" { return sqlStatement, isRequest, nil } return sqlStatement, isRequest, nil } func extractSQLFromPayload(payload []byte) string { // 将字节转换为字符串 data := string(payload) data = strings.ReplaceAll(data, "\r", "") data = strings.ReplaceAll(data, "\n", "") data = strings.ReplaceAll(data, "\r\n", "") data = strings.ReplaceAll(data, "\t", "") // 检查是否包含 SQL 关键字 if containsSQLKeyword(data) { return data } return "" } func containsSQLKeyword(data string) bool { keywords := []string{"INSERT", "UPDATE", "DELETE", "SELECT"} for _, keyword := range keywords { if strings.Contains(strings.ToUpper(data), keyword) { return true } } return false } func cleanString(input string) string { var buffer bytes.Buffer for _, r := range input { if r >= 32 && r <= 126 { // 保留可打印的 ASCII 字符 buffer.WriteRune(r) } } cleaned := buffer.String() // 进一步清理无用的空格和特殊字符 cleaned = strings.TrimSpace(cleaned) cleaned = strings.ReplaceAll(cleaned, "\r", "") cleaned = strings.ReplaceAll(cleaned, "\n", "") cleaned = strings.ReplaceAll(cleaned, "\t", "") return cleaned }