init
This commit is contained in:
162
internal/capture/capture.go
Normal file
162
internal/capture/capture.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package capture
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"equipment-analyzer/internal/model"
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/google/gopacket/pcap"
|
||||
)
|
||||
|
||||
type PacketCapture struct {
|
||||
handle *pcap.Handle
|
||||
isCapturing bool
|
||||
stopChan chan bool
|
||||
mutex sync.RWMutex
|
||||
tcpProcessor *TCPProcessor
|
||||
dataChan chan *model.TCPData
|
||||
errorChan chan error
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
InterfaceName string
|
||||
Filter string
|
||||
Timeout time.Duration
|
||||
BufferSize int
|
||||
}
|
||||
|
||||
func NewPacketCapture() *PacketCapture {
|
||||
return &PacketCapture{
|
||||
stopChan: make(chan bool),
|
||||
tcpProcessor: NewTCPProcessor(),
|
||||
dataChan: make(chan *model.TCPData, 1000),
|
||||
errorChan: make(chan error, 100),
|
||||
}
|
||||
}
|
||||
|
||||
func (pc *PacketCapture) Start(config Config) error {
|
||||
pc.mutex.Lock()
|
||||
defer pc.mutex.Unlock()
|
||||
|
||||
if pc.isCapturing {
|
||||
return fmt.Errorf("capture already running")
|
||||
}
|
||||
|
||||
// 打开网络接口
|
||||
handle, err := pcap.OpenLive(
|
||||
config.InterfaceName,
|
||||
int32(config.BufferSize),
|
||||
true, // promiscuous
|
||||
config.Timeout,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open interface: %v", err)
|
||||
}
|
||||
|
||||
// 设置过滤器
|
||||
if err := handle.SetBPFFilter(config.Filter); err != nil {
|
||||
handle.Close()
|
||||
return fmt.Errorf("failed to set filter: %v", err)
|
||||
}
|
||||
|
||||
pc.handle = handle
|
||||
pc.isCapturing = true
|
||||
|
||||
// 启动抓包协程
|
||||
go pc.captureLoop()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pc *PacketCapture) Stop() {
|
||||
pc.mutex.Lock()
|
||||
defer pc.mutex.Unlock()
|
||||
|
||||
if !pc.isCapturing {
|
||||
return
|
||||
}
|
||||
|
||||
pc.isCapturing = false
|
||||
close(pc.stopChan)
|
||||
|
||||
if pc.handle != nil {
|
||||
pc.handle.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (pc *PacketCapture) IsCapturing() bool {
|
||||
pc.mutex.RLock()
|
||||
defer pc.mutex.RUnlock()
|
||||
return pc.isCapturing
|
||||
}
|
||||
|
||||
func (pc *PacketCapture) captureLoop() {
|
||||
packetSource := gopacket.NewPacketSource(pc.handle, pc.handle.LinkType())
|
||||
|
||||
log.Println("[抓包] 开始监听数据包...")
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-pc.stopChan:
|
||||
return
|
||||
default:
|
||||
packet, err := packetSource.NextPacket()
|
||||
if err != nil {
|
||||
if err.Error() == "Timeout Expired" {
|
||||
// 静默跳过超时
|
||||
continue
|
||||
}
|
||||
log.Printf("Error reading packet: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 处理TCP包
|
||||
pc.processTCPPacket(packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pc *PacketCapture) processTCPPacket(packet gopacket.Packet) {
|
||||
tcpLayer := packet.Layer(layers.LayerTypeTCP)
|
||||
if tcpLayer == nil {
|
||||
return
|
||||
}
|
||||
|
||||
tcp, ok := tcpLayer.(*layers.TCP)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// 提取TCP负载
|
||||
if len(tcp.Payload) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建TCP数据包
|
||||
tcpData := &model.TCPData{
|
||||
Payload: tcp.Payload,
|
||||
Seq: uint32(tcp.Seq),
|
||||
Ack: uint32(tcp.Ack),
|
||||
SrcPort: uint16(tcp.SrcPort),
|
||||
DstPort: uint16(tcp.DstPort),
|
||||
}
|
||||
|
||||
// 发送给TCP处理器
|
||||
pc.tcpProcessor.ProcessPacket(tcpData)
|
||||
}
|
||||
|
||||
func (pc *PacketCapture) GetCapturedData() []string {
|
||||
return pc.tcpProcessor.GetFinalBuffer()
|
||||
}
|
||||
|
||||
func (pc *PacketCapture) ProcessAllData() {
|
||||
pc.tcpProcessor.ProcessAllData()
|
||||
}
|
||||
|
||||
func (pc *PacketCapture) Clear() {
|
||||
pc.tcpProcessor.Clear()
|
||||
}
|
||||
73
internal/capture/interface.go
Normal file
73
internal/capture/interface.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package capture
|
||||
|
||||
import (
|
||||
"equipment-analyzer/internal/model"
|
||||
"fmt"
|
||||
"github.com/google/gopacket/pcap"
|
||||
)
|
||||
|
||||
// GetNetworkInterfaces 获取网络接口列表
|
||||
func GetNetworkInterfaces() ([]model.NetworkInterface, error) {
|
||||
devices, err := pcap.FindAllDevs()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find network devices: %v", err)
|
||||
}
|
||||
|
||||
var interfaces []model.NetworkInterface
|
||||
for _, device := range devices {
|
||||
// 跳过回环接口
|
||||
if device.Name == "lo" || device.Name == "loopback" {
|
||||
continue
|
||||
}
|
||||
|
||||
// 提取IP地址
|
||||
var addresses []string
|
||||
for _, address := range device.Addresses {
|
||||
addresses = append(addresses, address.IP.String())
|
||||
}
|
||||
|
||||
interfaceInfo := model.NetworkInterface{
|
||||
Name: device.Name,
|
||||
Description: device.Description,
|
||||
Addresses: addresses,
|
||||
IsLoopback: device.Name == "lo" || device.Name == "loopback",
|
||||
}
|
||||
|
||||
interfaces = append(interfaces, interfaceInfo)
|
||||
}
|
||||
|
||||
return interfaces, nil
|
||||
}
|
||||
|
||||
// GetDefaultInterface 获取默认网络接口
|
||||
func GetDefaultInterface() (*model.NetworkInterface, error) {
|
||||
interfaces, err := GetNetworkInterfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 查找第一个非回环接口
|
||||
for _, iface := range interfaces {
|
||||
if !iface.IsLoopback && len(iface.Addresses) > 0 {
|
||||
return &iface, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no suitable network interface found")
|
||||
}
|
||||
|
||||
// ValidateInterface 验证网络接口是否可用
|
||||
func ValidateInterface(interfaceName string) error {
|
||||
devices, err := pcap.FindAllDevs()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find network devices: %v", err)
|
||||
}
|
||||
|
||||
for _, device := range devices {
|
||||
if device.Name == interfaceName {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("interface %s not found", interfaceName)
|
||||
}
|
||||
96
internal/capture/processor.go
Normal file
96
internal/capture/processor.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package capture
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"equipment-analyzer/internal/model"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type TCPProcessor struct {
|
||||
mutex sync.RWMutex
|
||||
ackData map[uint32][]*model.TCPData
|
||||
finalBuffer []string
|
||||
loads map[string]bool // 去重用
|
||||
}
|
||||
|
||||
func NewTCPProcessor() *TCPProcessor {
|
||||
return &TCPProcessor{
|
||||
ackData: make(map[uint32][]*model.TCPData),
|
||||
loads: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (tp *TCPProcessor) ProcessPacket(tcpData *model.TCPData) {
|
||||
tp.mutex.Lock()
|
||||
defer tp.mutex.Unlock()
|
||||
|
||||
// 生成数据哈希用于去重
|
||||
hash := tp.generateHash(tcpData.Payload)
|
||||
if tp.loads[hash] {
|
||||
return // 跳过重复数据
|
||||
}
|
||||
tp.loads[hash] = true
|
||||
|
||||
// 按ACK号分组存储
|
||||
ack := uint32(tcpData.Ack)
|
||||
if tp.ackData[ack] == nil {
|
||||
tp.ackData[ack] = make([]*model.TCPData, 0)
|
||||
}
|
||||
tp.ackData[ack] = append(tp.ackData[ack], tcpData)
|
||||
}
|
||||
|
||||
func (tp *TCPProcessor) generateHash(data []byte) string {
|
||||
hash := md5.Sum(data)
|
||||
return hex.EncodeToString(hash[:])
|
||||
}
|
||||
|
||||
func (tp *TCPProcessor) ProcessAllData() {
|
||||
tp.mutex.Lock()
|
||||
defer tp.mutex.Unlock()
|
||||
|
||||
tp.finalBuffer = make([]string, 0)
|
||||
|
||||
for ack, dataList := range tp.ackData {
|
||||
tp.tryBuffer(ack, dataList)
|
||||
}
|
||||
}
|
||||
|
||||
func (tp *TCPProcessor) tryBuffer(ack uint32, dataList []*model.TCPData) {
|
||||
// 按序列号排序
|
||||
sort.Slice(dataList, func(i, j int) bool {
|
||||
return dataList[i].Seq < dataList[j].Seq
|
||||
})
|
||||
|
||||
// 合并所有分片数据
|
||||
var buffer bytes.Buffer
|
||||
for _, data := range dataList {
|
||||
buffer.Write(data.Payload)
|
||||
}
|
||||
|
||||
// 转换为十六进制字符串
|
||||
hexStr := hex.EncodeToString(buffer.Bytes())
|
||||
tp.finalBuffer = append(tp.finalBuffer, hexStr)
|
||||
}
|
||||
|
||||
func (tp *TCPProcessor) GetFinalBuffer() []string {
|
||||
tp.mutex.RLock()
|
||||
defer tp.mutex.RUnlock()
|
||||
|
||||
result := make([]string, len(tp.finalBuffer))
|
||||
copy(result, tp.finalBuffer)
|
||||
//// 输出每条finalBuffer的16进制字符串到控制台
|
||||
//fmt.Println("抓取16进制字符串")
|
||||
//fmt.Println(result)
|
||||
return result
|
||||
}
|
||||
func (tp *TCPProcessor) Clear() {
|
||||
tp.mutex.Lock()
|
||||
defer tp.mutex.Unlock()
|
||||
|
||||
tp.ackData = make(map[uint32][]*model.TCPData)
|
||||
tp.finalBuffer = make([]string, 0)
|
||||
tp.loads = make(map[string]bool)
|
||||
}
|
||||
Reference in New Issue
Block a user