mirror of
https://github.com/zr-hebo/sniffer-agent.git
synced 2025-09-19 10:16:53 +08:00
add windows support
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
package capture
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
sd "github.com/zr-hebo/sniffer-agent/session-dealer"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
log "github.com/golang/glog"
|
||||
sd "github.com/zr-hebo/sniffer-agent/session-dealer"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -21,7 +22,10 @@ func init() {
|
||||
}
|
||||
|
||||
localIPAddr = &ipAddr
|
||||
log.Infof("parsed local ip address:%s", *localIPAddr)
|
||||
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
func ShowLocalIP() {
|
||||
log.Infof("parsed local ip address:%s", *localIPAddr)
|
||||
}
|
||||
|
11
capture/model.go
Normal file
11
capture/model.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package capture
|
||||
|
||||
import (
|
||||
"github.com/google/gopacket/layers"
|
||||
)
|
||||
|
||||
type TCPIPPair struct {
|
||||
srcIP string
|
||||
dstIP string
|
||||
tcpPkt *layers.TCP
|
||||
}
|
@@ -4,14 +4,13 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
log "github.com/golang/glog"
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
pp "github.com/pires/go-proxyproto"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/zr-hebo/sniffer-agent/communicator"
|
||||
"github.com/zr-hebo/sniffer-agent/model"
|
||||
sd "github.com/zr-hebo/sniffer-agent/session-dealer"
|
||||
@@ -57,14 +56,34 @@ func (nc *networkCard) Listen() (receiver chan model.QueryPiece) {
|
||||
// Listen get a connection.
|
||||
func (nc *networkCard) listenNormal() {
|
||||
go func() {
|
||||
dealTCPPacket := func(srcIP, dstIP string, tcpPkt *layers.TCP, capturePacketRate float64) {
|
||||
// send FIN tcp packet to avoid not complete session cannot be released
|
||||
// deal FIN packet
|
||||
if tcpPkt.FIN {
|
||||
nc.parseTCPPackage(srcIP, dstIP, tcpPkt, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// deal auth packet
|
||||
if sd.IsAuthPacket(tcpPkt.Payload) {
|
||||
authHeader, _ := pp.Read(bufio.NewReader(bytes.NewReader(tcpPkt.Payload)))
|
||||
nc.parseTCPPackage(srcIP, dstIP, tcpPkt, authHeader)
|
||||
return
|
||||
}
|
||||
|
||||
if 0 < capturePacketRate && capturePacketRate < 1.0 {
|
||||
// fall into throw range
|
||||
rn := rand.Float64()
|
||||
if rn > capturePacketRate {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
nc.parseTCPPackage(srcIP, dstIP, tcpPkt, nil)
|
||||
}
|
||||
|
||||
aliveCounter := 0
|
||||
handler := initEthernetHandlerFromPacp()
|
||||
|
||||
for {
|
||||
var data []byte
|
||||
var ci gopacket.CaptureInfo
|
||||
var err error
|
||||
|
||||
dealTCPIPPacket := func(tcpIPPkt *TCPIPPair) {
|
||||
// capture packets according to a certain probability
|
||||
capturePacketRate := communicator.GetTCPCapturePacketRate()
|
||||
if capturePacketRate <= 0 {
|
||||
@@ -74,53 +93,19 @@ func (nc *networkCard) listenNormal() {
|
||||
aliveCounter = 0
|
||||
nc.receiver <- model.NewBaseQueryPiece(localIPAddr, nc.listenPort, capturePacketRate)
|
||||
}
|
||||
continue
|
||||
|
||||
} else {
|
||||
dealTCPPacket(tcpIPPkt.srcIP, tcpIPPkt.dstIP, tcpIPPkt.tcpPkt, capturePacketRate)
|
||||
}
|
||||
|
||||
data, ci, err = handler.ZeroCopyReadPacketData()
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
time.Sleep(time.Second * 3)
|
||||
continue
|
||||
}
|
||||
|
||||
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
|
||||
// packet := gopacket.NewPacket(data, handler.LinkType(), gopacket.NoCopy)
|
||||
m := packet.Metadata()
|
||||
m.CaptureInfo = ci
|
||||
|
||||
tcpPkt := packet.TransportLayer().(*layers.TCP)
|
||||
// send FIN tcp packet to avoid not complete session cannot be released
|
||||
// deal FIN packet
|
||||
if tcpPkt.FIN {
|
||||
nc.parseTCPPackage(packet, nil)
|
||||
continue
|
||||
}
|
||||
|
||||
// deal auth packet
|
||||
if sd.IsAuthPacket(tcpPkt.Payload) {
|
||||
authHeader, _ := pp.Read(bufio.NewReader(bytes.NewReader(tcpPkt.Payload)))
|
||||
nc.parseTCPPackage(packet, authHeader)
|
||||
continue
|
||||
}
|
||||
|
||||
if 0 < capturePacketRate && capturePacketRate < 1.0 {
|
||||
// fall into throw range
|
||||
rn := rand.Float64()
|
||||
if rn > capturePacketRate {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
aliveCounter = 0
|
||||
nc.parseTCPPackage(packet, nil)
|
||||
}
|
||||
|
||||
dealEachTCPIPPacket(dealTCPIPPacket)
|
||||
}()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (nc *networkCard) parseTCPPackage(packet gopacket.Packet, authHeader *pp.Header) {
|
||||
func (nc *networkCard) parseTCPPackage(srcIP, dstIP string, tcpPkt *layers.TCP, authHeader *pp.Header) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -128,25 +113,10 @@ func (nc *networkCard) parseTCPPackage(packet gopacket.Packet, authHeader *pp.He
|
||||
}
|
||||
}()
|
||||
|
||||
tcpPkt := packet.TransportLayer().(*layers.TCP)
|
||||
if tcpPkt.SYN || tcpPkt.RST {
|
||||
return
|
||||
}
|
||||
|
||||
ipLayer := packet.Layer(layers.LayerTypeIPv4)
|
||||
if ipLayer == nil {
|
||||
err = fmt.Errorf("no ip layer found in package")
|
||||
return
|
||||
}
|
||||
|
||||
ipInfo, ok := ipLayer.(*layers.IPv4)
|
||||
if !ok {
|
||||
err = fmt.Errorf("parsed no ip address")
|
||||
return
|
||||
}
|
||||
|
||||
srcIP := ipInfo.SrcIP.String()
|
||||
dstIP := ipInfo.DstIP.String()
|
||||
srcPort := int(tcpPkt.SrcPort)
|
||||
dstPort := int(tcpPkt.DstPort)
|
||||
|
||||
@@ -231,7 +201,7 @@ func readToServerPackage(
|
||||
session.Close()
|
||||
delete(sessionPool, *sessionKey)
|
||||
}
|
||||
log.Debugf("close connection from %s", *sessionKey)
|
||||
log.Infof("close connection from %s", *sessionKey)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -1,17 +1,21 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package capture
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
log "github.com/golang/glog"
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/google/gopacket/pcap"
|
||||
"github.com/google/gopacket/pcapgo"
|
||||
"golang.org/x/net/bpf"
|
||||
)
|
||||
|
||||
func initEthernetHandlerFromPacp() (handler PcapHandler) {
|
||||
func initEthernetHandlerFromPacp() (pcapgoHandler *pcapgo.EthernetHandle) {
|
||||
pcapgoHandler, err := pcapgo.NewEthernetHandle(DeviceName)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot open network interface %s <-- %s", DeviceName, err.Error()))
|
||||
@@ -40,6 +44,58 @@ func initEthernetHandlerFromPacp() (handler PcapHandler) {
|
||||
}
|
||||
|
||||
_ = pcapgoHandler.SetCaptureLength(65536)
|
||||
handler = pcapgoHandler
|
||||
return
|
||||
}
|
||||
|
||||
func dealEachTCPIPPacket(dealTCPIPPacket func(tcpIPPkt *TCPIPPair)) {
|
||||
handler := initEthernetHandlerFromPacp()
|
||||
defer func() {
|
||||
handler.Close()
|
||||
}()
|
||||
|
||||
for {
|
||||
var ci gopacket.CaptureInfo
|
||||
data, ci, err := handler.ZeroCopyReadPacketData()
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
time.Sleep(time.Second * 3)
|
||||
continue
|
||||
}
|
||||
|
||||
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
|
||||
m := packet.Metadata()
|
||||
m.CaptureInfo = ci
|
||||
|
||||
tcpPkt, ok := packet.TransportLayer().(*layers.TCP)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
ipLayer := packet.NetworkLayer()
|
||||
if ipLayer == nil {
|
||||
log.Error("no ip layer found in package")
|
||||
continue
|
||||
}
|
||||
|
||||
var srcIP, dstIP string
|
||||
switch realIPLayer := ipLayer.(type) {
|
||||
case *layers.IPv6:
|
||||
{
|
||||
srcIP = realIPLayer.SrcIP.String()
|
||||
dstIP = realIPLayer.DstIP.String()
|
||||
}
|
||||
case *layers.IPv4:
|
||||
{
|
||||
srcIP = realIPLayer.SrcIP.String()
|
||||
dstIP = realIPLayer.DstIP.String()
|
||||
}
|
||||
}
|
||||
|
||||
tcpipPair := &TCPIPPair{
|
||||
srcIP: srcIP,
|
||||
dstIP: dstIP,
|
||||
tcpPkt: tcpPkt,
|
||||
}
|
||||
dealTCPIPPacket(tcpipPair)
|
||||
}
|
||||
}
|
||||
|
@@ -1,15 +1,20 @@
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package capture
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
log "github.com/golang/glog"
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/google/gopacket/pcap"
|
||||
)
|
||||
|
||||
// in online use, we found a strange bug: pcap cost 100% core CPU and memory increase along
|
||||
func initEthernetHandlerFromPacp() (handler PcapHandler) {
|
||||
func initEthernetHandlerFromPacp() (pcapHandler *pcap.Handle) {
|
||||
pcapHandler, err := pcap.OpenLive(DeviceName, 65536, false, pcap.BlockForever)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot open network interface %s <-- %s", DeviceName, err.Error()))
|
||||
@@ -20,6 +25,58 @@ func initEthernetHandlerFromPacp() (handler PcapHandler) {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
handler = pcapHandler
|
||||
return
|
||||
}
|
||||
|
||||
func dealEachTCPIPPacket(dealTCPIPPacket func(tcpIPPkt *TCPIPPair)) {
|
||||
handler := initEthernetHandlerFromPacp()
|
||||
defer func() {
|
||||
handler.Close()
|
||||
}()
|
||||
|
||||
for {
|
||||
var ci gopacket.CaptureInfo
|
||||
data, ci, err := handler.ZeroCopyReadPacketData()
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
time.Sleep(time.Second * 3)
|
||||
continue
|
||||
}
|
||||
|
||||
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
|
||||
m := packet.Metadata()
|
||||
m.CaptureInfo = ci
|
||||
|
||||
tcpPkt, ok := packet.TransportLayer().(*layers.TCP)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
ipLayer := packet.NetworkLayer()
|
||||
if ipLayer == nil {
|
||||
log.Error("no ip layer found in package")
|
||||
continue
|
||||
}
|
||||
|
||||
var srcIP, dstIP string
|
||||
switch realIPLayer := ipLayer.(type) {
|
||||
case *layers.IPv6:
|
||||
{
|
||||
srcIP = realIPLayer.SrcIP.String()
|
||||
dstIP = realIPLayer.DstIP.String()
|
||||
}
|
||||
case *layers.IPv4:
|
||||
{
|
||||
srcIP = realIPLayer.SrcIP.String()
|
||||
dstIP = realIPLayer.DstIP.String()
|
||||
}
|
||||
}
|
||||
|
||||
tcpipPair := &TCPIPPair{
|
||||
srcIP: srcIP,
|
||||
dstIP: dstIP,
|
||||
tcpPkt: tcpPkt,
|
||||
}
|
||||
dealTCPIPPacket(tcpipPair)
|
||||
}
|
||||
}
|
||||
|
81
capture/pacp_windows.go
Normal file
81
capture/pacp_windows.go
Normal file
@@ -0,0 +1,81 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package capture
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
log "github.com/golang/glog"
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/google/gopacket/pcap"
|
||||
)
|
||||
|
||||
var (
|
||||
handler *pcap.Handle
|
||||
)
|
||||
|
||||
func initEthernetHandlerFromPacp() (pcapHandler *pcap.Handle) {
|
||||
devices, err := pcap.FindAllDevs()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, device := range devices {
|
||||
log.Infof("found Windows device:'%s', device info:%s", device.Name, device.Description)
|
||||
}
|
||||
|
||||
pcapHandler, err = pcap.OpenLive(DeviceName, 1024, false, time.Hour*24)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot open network interface %s <-- %s", DeviceName, err.Error()))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func dealEachTCPIPPacket(dealTCPIPPacket func(tcpIPPkt *TCPIPPair)) {
|
||||
handler = initEthernetHandlerFromPacp()
|
||||
defer handler.Close()
|
||||
packetSource := gopacket.NewPacketSource(handler, handler.LinkType())
|
||||
for packet := range packetSource.Packets() {
|
||||
if err := packet.ErrorLayer(); err != nil {
|
||||
log.Error(err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
// Process packet here
|
||||
tcpLayer := packet.Layer(layers.LayerTypeTCP)
|
||||
if tcpLayer == nil {
|
||||
continue
|
||||
}
|
||||
tcpPkt := tcpLayer.(*layers.TCP)
|
||||
if (int(tcpPkt.SrcPort) != snifferPort && int(tcpPkt.DstPort) != snifferPort) {
|
||||
continue
|
||||
}
|
||||
|
||||
var srcIP, dstIP string
|
||||
ipLayer := packet.NetworkLayer()
|
||||
switch realIPLayer := ipLayer.(type) {
|
||||
case *layers.IPv6:
|
||||
{
|
||||
srcIP = realIPLayer.SrcIP.String()
|
||||
dstIP = realIPLayer.DstIP.String()
|
||||
}
|
||||
case *layers.IPv4:
|
||||
{
|
||||
srcIP = realIPLayer.SrcIP.String()
|
||||
dstIP = realIPLayer.DstIP.String()
|
||||
}
|
||||
}
|
||||
|
||||
tcpipPair := &TCPIPPair{
|
||||
srcIP: srcIP,
|
||||
dstIP: dstIP,
|
||||
tcpPkt: tcpPkt,
|
||||
}
|
||||
dealTCPIPPacket(tcpipPair)
|
||||
}
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user