Skip to content

Commit

Permalink
add gre first shot
Browse files Browse the repository at this point in the history
  • Loading branch information
dmachard committed Oct 8, 2024
1 parent 98eedb5 commit 0e7defb
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ GO_DNSTAP_PROTOBUF := 1.1.0
GO_FRAMESTREAM := 1.0.0
GO_CLIENTSYSLOG := 1.0.0
GO_TOPMAP := 1.0.1
GO_NETUTILS := 1.0.0
GO_NETUTILS := 1.0.1

BUILD_TIME := $(shell LANG=en_US date +"%F_%T_%z")
COMMIT := $(shell git rev-parse --short HEAD)
Expand Down
30 changes: 21 additions & 9 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,29 @@ global:
# transformers: https://github.com/dmachard/go-dnscollector/blob/main/docs/transformers.md
################################################
pipelines:
- name: tap
dnstap:
listen-ip: 0.0.0.0
listen-port: 6000
transforms:
normalize:
qname-lowercase: true
qname-replace-nonprintable: true
- name: sniffer
afpacket-sniffer:
port: 53
device: wlp2s0
enable-defrag-ip: true
chan-buffer-size: 0
# transforms:
# filtering:
# keep-queryip-file: ./tests/testsdata/filtering_queryip_gre.txt
routing-policy:
forward: [ console ]
dropped: [ ]

# - name: tap
# dnstap:
# listen-ip: 0.0.0.0
# listen-port: 6000
# transforms:
# normalize:
# qname-lowercase: true
# qname-replace-nonprintable: true
# routing-policy:
# forward: [ console ]
# dropped: [ ]

- name: console
stdout:
Expand Down
20 changes: 20 additions & 0 deletions docs/_examples/use-case-27.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
global:
trace:
verbose: true

pipelines:
- name: sniffer
afpacket-sniffer:
port: 53
device: wlp2s0
enable-defrag-ip: true
chan-buffer-size: 0
transforms:
filtering:
keep-queryip-file: ./tests/testsdata/filtering_queryip_gre.txt
routing-policy:
forward: [ console ]

- name: console
stdout:
mode: text
1 change: 1 addition & 0 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ You will find below some examples of configurations to manage your DNS logs.
- [x] [Add geographical metadata with GeoIP](./_examplesuse-case-11.yml)
- [x] [Count the number of evicted queries](./_examples/use-case-18.yml)
- [x] [Detect repetitive traffic and log it only once](./_examples/use-case-20.yml)
- [x] [Keep incoming traffic with specific ip prefix](./_examples/use-case-27.yml)

- Capture DNS traffic from FRSTRM/dnstap files
- [x] [Save incoming DNStap streams to file (frstrm)](./_examples/use-case-13.yml)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/dmachard/go-dnstap-protobuf v1.1.0
github.com/dmachard/go-framestream v1.0.0
github.com/dmachard/go-logger v1.1.0
github.com/dmachard/go-netutils v1.0.0
github.com/dmachard/go-netutils v1.0.1
github.com/dmachard/go-powerdns-protobuf v1.2.0
github.com/dmachard/go-topmap v1.0.1
github.com/farsightsec/golang-framestream v0.3.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ github.com/dmachard/go-framestream v1.0.0 h1:cdL8Gc2PhWl9hKXmtBIDIfssplUAsIK3Dhf
github.com/dmachard/go-framestream v1.0.0/go.mod h1:icl91cC7AE1jw2gXBa/P9iIGmhApfB2EnmZCb4XzoRw=
github.com/dmachard/go-logger v1.1.0 h1:AOXHDEOp4SiXt9ZfVL1jTQNWFTBaw28bR4JfH3/OX/4=
github.com/dmachard/go-logger v1.1.0/go.mod h1:p+qf9XDiJOcpjx1Bl3vRGTVqwLoZ6cNUZCxulaVJ6e8=
github.com/dmachard/go-netutils v1.0.0 h1:WUb4wIJ2r9UJMLXdRvAzZkrS4jMQKTtNa85RkUPx8Gc=
github.com/dmachard/go-netutils v1.0.0/go.mod h1:kTrO5B/mXW/cPdHyUWsHqXUVkvb2mTUwm/68Fc48XuE=
github.com/dmachard/go-netutils v1.0.1 h1:0EdhahW4b7wrvSt7vLC5dkX+hRr4t+9uDYO+zfN1MTc=
github.com/dmachard/go-netutils v1.0.1/go.mod h1:kTrO5B/mXW/cPdHyUWsHqXUVkvb2mTUwm/68Fc48XuE=
github.com/dmachard/go-powerdns-protobuf v1.2.0 h1:VrmT7Ir2eKvB2I0bTJwlHHPLrS95B3X2gD2tlXEx76A=
github.com/dmachard/go-powerdns-protobuf v1.2.0/go.mod h1:TgY5tdhMyzDkWK0jBtGPDpOFOGp/brrlb5FaW7YgcDM=
github.com/dmachard/go-topmap v1.0.1 h1:aqAul7Nf30fZQjdx5HSCNd0eN8icGAYe5Gqpnp+QKfE=
Expand Down
2 changes: 2 additions & 0 deletions tests/testsdata/filtering_queryip_gre.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
10.0.0.1
10.0.0.2
118 changes: 103 additions & 15 deletions workers/sniffer_afpacket_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ func (w *AfpacketSniffer) Listen() error {
return err
}

filter := netutils.GetBpfFilterPort(w.GetConfig().Collectors.AfpacketLiveCapture.Port)
// prepare bpf filter and apply it
filter, err := netutils.GetBpfFilterPort(w.GetConfig().Collectors.AfpacketLiveCapture.Port)
if err != nil {
return err
}
err = netutils.ApplyBpfFilter(filter, fd)
if err != nil {
return err
Expand Down Expand Up @@ -105,7 +109,6 @@ func (w *AfpacketSniffer) StartCollect() {
fragIP6Chan := make(chan gopacket.Packet)

netDecoder := &netutils.NetDecoder{}

// defrag ipv4
go netutils.IPDefragger(fragIP4Chan, udpChan, tcpChan, w.GetConfig().Collectors.AfpacketLiveCapture.Port)
// defrag ipv6
Expand Down Expand Up @@ -193,38 +196,123 @@ func (w *AfpacketSniffer) StartCollect() {
packet.Metadata().Length = len(packet.Data())
packet.Metadata().Timestamp = timestamp

// some security checks
// some security checks, ignore the packet...
if packet.NetworkLayer() == nil {
continue
}
if packet.TransportLayer() == nil {
continue
}

// ipv4 fragmented packet ?
// handle ipv4
if packet.NetworkLayer().LayerType() == layers.LayerTypeIPv4 {
if !w.GetConfig().Collectors.AfpacketLiveCapture.FragmentSupport {
continue
}
ip4 := packet.NetworkLayer().(*layers.IPv4)

// gre ?
if ip4.Protocol == layers.IPProtocolGRE {
// Decapsulate GRE and re-process the inner packet
greLayer := packet.Layer(layers.LayerTypeGRE)
if greLayer != nil {
gre := greLayer.(*layers.GRE)

// check ip encapsuled packet protocol, ignore ipv6 encapsuled in ipv4
innerIP4 := &layers.IPv4{}
if err := innerIP4.DecodeFromBytes(gre.Payload, gopacket.NilDecodeFeedback); err != nil {
continue
}

//Create new packet with GRE

Check failure on line 221 in workers/sniffer_afpacket_linux.go

View workflow job for this annotation

GitHub Actions / linter

commentFormatting: put a space between `//` and comment text (gocritic)
ethernetHeader := packet.Data()[:14]
newPacket := append([]byte{}, ethernetHeader...) // Start with the Ethernet header
newPacket = append(newPacket, gre.Payload...)
innerPacket := gopacket.NewPacket(newPacket, netDecoder, gopacket.NoCopy)

// handle fragment inside the encapsulated packet
if innerIP4.Flags&layers.IPv4MoreFragments == 1 || innerIP4.FragOffset > 0 {
if w.GetConfig().Collectors.AfpacketLiveCapture.FragmentSupport {
fragIP4Chan <- innerPacket
}
continue
}

// Handle TCP/UDP inside the encapsulated packet
if innerPacket.TransportLayer() == nil {
continue
}

if innerPacket.TransportLayer().LayerType() == layers.LayerTypeUDP {
udpChan <- innerPacket
}
if innerPacket.TransportLayer().LayerType() == layers.LayerTypeTCP {
tcpChan <- innerPacket
}
continue
}
}

// fragment ?
if ip4.Flags&layers.IPv4MoreFragments == 1 || ip4.FragOffset > 0 {
fragIP4Chan <- packet
if w.GetConfig().Collectors.AfpacketLiveCapture.FragmentSupport {
fragIP4Chan <- packet
}
continue
}
}

// ipv6 fragmented packet ?
// handle ipv6
if packet.NetworkLayer().LayerType() == layers.LayerTypeIPv6 {
if !w.GetConfig().Collectors.AfpacketLiveCapture.FragmentSupport {
continue
ipv6 := packet.NetworkLayer().(*layers.IPv6)

// gre ?
if ipv6.NextHeader == layers.IPProtocolGRE {
// Decapsulate GRE and re-process the inner packet
greLayer := packet.Layer(layers.LayerTypeGRE)
if greLayer != nil {
gre := greLayer.(*layers.GRE)

// Attempt to decode the inner IPv6 packet, ignore IPv4 inside IPv6
innerIP6 := &layers.IPv6{}
if err := innerIP6.DecodeFromBytes(gre.Payload, gopacket.NilDecodeFeedback); err != nil {
continue
}

//Create new packet with GRE

Check failure on line 276 in workers/sniffer_afpacket_linux.go

View workflow job for this annotation

GitHub Actions / linter

commentFormatting: put a space between `//` and comment text (gocritic)
ethernetHeader := packet.Data()[:14]
newPacket := append([]byte{}, ethernetHeader...) // Start with the Ethernet header
newPacket = append(newPacket, gre.Payload...)
innerPacket := gopacket.NewPacket(newPacket, netDecoder, gopacket.NoCopy)

// Handle fragmentation inside the encapsulated IPv6 packet
// Check if it has fragmentation header
if innerPacket.Layer(layers.LayerTypeIPv6Fragment) != nil {
if w.GetConfig().Collectors.AfpacketLiveCapture.FragmentSupport {
fragIP6Chan <- innerPacket
}
continue
}

// Handle TCP/UDP inside the encapsulated packet
if innerPacket.TransportLayer().LayerType() == layers.LayerTypeUDP {
udpChan <- innerPacket
}
if innerPacket.TransportLayer().LayerType() == layers.LayerTypeTCP {
tcpChan <- innerPacket
}
continue
}
}

v6frag := packet.Layer(layers.LayerTypeIPv6Fragment)
if v6frag != nil {
fragIP6Chan <- packet
if w.GetConfig().Collectors.AfpacketLiveCapture.FragmentSupport {
fragIP6Chan <- packet
}
continue
}
}

// transport is empty, ignore the packet...
if packet.TransportLayer() == nil {
continue
}

// tcp or udp packets ?
if packet.TransportLayer().LayerType() == layers.LayerTypeUDP {
udpChan <- packet
Expand Down

0 comments on commit 0e7defb

Please sign in to comment.