DenyIP-go/cap.go
2025-03-07 09:33:23 +08:00

121 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"github.com/google/gopacket/pcapgo"
)
// 打印可用的网络接口信息
func printAvailableInterfaces() {
devices, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}
fmt.Println("可用的网络接口:")
for _, device := range devices {
fmt.Printf("名称: %s\n描述: %s\n地址: %+v\n\n", device.Name, device.Description, device.Addresses)
}
}
// 判断 IP 是否在链表中
func isIPInList(ip net.IP) bool {
for e := IpList.Front(); e != nil; e = e.Next() {
if e.Value.(net.IP).Equal(ip) {
return true
}
}
return false
}
// 打印捕获到的每个数据包的信息
func printPacketInfo(packet gopacket.Packet) {
ipLayer := packet.Layer(layers.LayerTypeIPv4)
if ipLayer != nil {
ip, _ := ipLayer.(*layers.IPv4)
IpMutex.Lock()
defer IpMutex.Unlock()
if !isIPInList(ip.SrcIP) {
IpList.PushBack(ip.SrcIP)
log.Printf("\033[31m 已添加源 IP: %s 到链表 \033[0m\n", ip.SrcIP)
}
}
}
// startPacketCapture 启动数据包捕获
func startPacketCapture() {
// 打开指定的网络接口进行实时数据包捕获
handle, err := pcap.OpenLive(*InterfaceName, 65535, true, pcap.BlockForever)
if err != nil {
log.Fatalf("打开网络接口 %s 出错: %v", *InterfaceName, err)
}
// 确保在函数退出时关闭句柄,释放资源
defer func() {
fmt.Println("清理资源...")
if handle != nil {
handle.Close()
}
}()
// 设置 BPFBerkeley Packet Filter过滤器以便只捕获指定协议的数据包
err = handle.SetBPFFilter(*Protocol)
if err != nil {
log.Fatalf("设置 BPF 过滤器出错: %v", err)
}
// 如果指定了输出文件,则创建文件并初始化 pcapgo.Writer
var pcapWriter *pcapgo.Writer
if *PcapFile != "" {
file, err := os.Create(*PcapFile)
if err != nil {
log.Fatalf("创建输出文件出错: %v", err)
}
defer file.Close()
pcapWriter = pcapgo.NewWriter(file)
// 写入 pcap 文件头部,指定最大捕获长度和链路层类型
err = pcapWriter.WriteFileHeader(65535, layers.LinkTypeEthernet)
if err != nil {
log.Fatalf("写入全局头部出错: %v", err)
}
}
// 创建数据包源,用于从网络接口读取数据包
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
fmt.Printf("正在监听网络接口 %s, 使用过滤器 '%s'...\n", *InterfaceName, *Protocol)
// 创建信号通道,用于捕获中断信号
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
// 启动一个 goroutine 来处理捕获到的数据包
go func() {
for packet := range packetSource.Packets() {
// 打印数据包信息
printPacketInfo(packet)
// 如果指定了输出文件,则将数据包写入文件
if pcapWriter != nil {
err := pcapWriter.WritePacket(packet.Metadata().CaptureInfo, packet.Data())
if err != nil {
log.Printf("写入数据包出错: %v", err)
}
}
}
}()
// 等待中断信号,收到信号后停止捕获
<-sigChan
fmt.Println("\n停止抓包...")
}