new: main packet queue is now used to gather network stats, update endpoint, etc

This commit is contained in:
evilsocket 2018-01-13 18:40:43 +01:00
parent a296dacd74
commit 913c581f9f
4 changed files with 127 additions and 15 deletions

View file

@ -4,6 +4,7 @@ import (
"encoding/binary"
"fmt"
"net"
"time"
"github.com/evilsocket/bettercap-ng/core"
)
@ -11,6 +12,7 @@ import (
type OnHostResolvedCallback func(e *Endpoint)
type Endpoint struct {
IP net.IP `json:"-"`
Net *net.IPNet `json:"-"`
IPv6 net.IP `json:"."`
HW net.HardwareAddr `json:"-"`
IpAddress string `json:"ipv4"`
@ -21,12 +23,17 @@ type Endpoint struct {
Hostname string `json:"hostname"`
Vendor string `json:"vendor"`
ResolvedCallback OnHostResolvedCallback `json:"-"`
FirstSeen time.Time `json:"first_seen"`
LastSeen time.Time `json:"last_seen"`
}
func NewEndpointNoResolve(ip, mac, name string, bits uint32) *Endpoint {
hw, _ := net.ParseMAC(mac)
now := time.Now()
e := &Endpoint{
IP: net.ParseIP(ip),
Net: nil,
HW: hw,
IpAddress: ip,
SubnetBits: bits,
@ -35,8 +42,13 @@ func NewEndpointNoResolve(ip, mac, name string, bits uint32) *Endpoint {
Hostname: name,
Vendor: OuiLookup(mac),
ResolvedCallback: nil,
FirstSeen: now,
LastSeen: now,
}
_, netw, _ := net.ParseCIDR(e.CIDR())
e.Net = netw
return e
}

View file

@ -1,42 +1,126 @@
package packets
import (
"bytes"
"fmt"
"github.com/google/gopacket/pcap"
"net"
"sync"
bnet "github.com/evilsocket/bettercap-ng/net"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
type Queue struct {
iface string
handle *pcap.Handle
lock *sync.Mutex
active bool
type Activity struct {
IP net.IP
MAC net.HardwareAddr
}
func NewQueue(iface string) (*Queue, error) {
type Queue struct {
iface *bnet.Endpoint
handle *pcap.Handle
source *gopacket.PacketSource
lock *sync.Mutex
active bool
Activities chan Activity `json:"-"`
Sent uint64
Received uint64
PktReceived uint64
Errors uint64
Protos map[string]uint64
}
func NewQueue(iface *bnet.Endpoint) (*Queue, error) {
var err error
q := &Queue{
iface: iface,
handle: nil,
lock: &sync.Mutex{},
active: true,
iface: iface,
handle: nil,
lock: &sync.Mutex{},
active: true,
source: nil,
Sent: 0,
Received: 0,
PktReceived: 0,
Errors: 0,
Protos: make(map[string]uint64),
Activities: make(chan Activity),
}
q.handle, err = pcap.OpenLive(iface, 1024, true, pcap.BlockForever)
q.handle, err = pcap.OpenLive(iface.Name(), 1024, true, pcap.BlockForever)
if err != nil {
return nil, err
}
q.source = gopacket.NewPacketSource(q.handle, q.handle.LinkType())
go q.worker()
return q, nil
}
func (q *Queue) worker() {
for pkt := range q.source.Packets() {
if q.active == false {
return
}
q.PktReceived++
q.Received += uint64(len(pkt.Data()))
// gather protocols stats
pktLayers := pkt.Layers()
for _, layer := range pktLayers {
proto := layer.LayerType().String()
if proto == "DecodeFailure" || proto == "Payload" {
continue
}
if _, found := q.Protos[proto]; found == false {
q.Protos[proto] = 0
}
q.Protos[proto] += 1
}
// check for new ipv4 endpoints
leth := pkt.Layer(layers.LayerTypeEthernet)
lip4 := pkt.Layer(layers.LayerTypeIPv4)
if leth != nil && lip4 != nil {
eth := leth.(*layers.Ethernet)
ip4 := lip4.(*layers.IPv4)
if bytes.Compare(q.iface.IP, ip4.SrcIP) != 0 && q.iface.Net.Contains(ip4.SrcIP) {
q.Activities <- Activity{
IP: ip4.SrcIP,
MAC: eth.SrcMAC,
}
}
if bytes.Compare(q.iface.IP, ip4.DstIP) != 0 && q.iface.Net.Contains(ip4.DstIP) {
q.Activities <- Activity{
IP: ip4.DstIP,
MAC: eth.SrcMAC,
}
}
}
}
}
func (q *Queue) Send(raw []byte) error {
q.lock.Lock()
defer q.lock.Unlock()
if q.active {
return q.handle.WritePacketData(raw)
err := q.handle.WritePacketData(raw)
if err != nil {
q.Sent += uint64(len(raw))
} else {
q.Errors += 1
}
return err
} else {
return fmt.Errorf("Packet queue is not active.")
}

View file

@ -33,7 +33,7 @@ type Session struct {
Firewall firewall.FirewallManager `json:"-"`
Env *Environment `json:"env"`
Targets *Targets `json:"targets"`
Queue *packets.Queue `json:"-"`
Queue *packets.Queue `json:"packets"`
Input *readline.Instance `json:"-"`
Active bool `json:"active"`
Prompt Prompt `json:"-"`
@ -174,7 +174,7 @@ func (s *Session) Start() error {
s.Env.Set("iface.ipv6", s.Interface.Ip6Address)
s.Env.Set("iface.mac", s.Interface.HwAddress)
if s.Queue, err = packets.NewQueue(s.Interface.Name()); err != nil {
if s.Queue, err = packets.NewQueue(s.Interface); err != nil {
return err
}
@ -227,6 +227,20 @@ func (s *Session) Start() error {
}()
s.Active = true
// keep reading network events in order to add / update endpoints
go func() {
for event := range s.Queue.Activities {
addr := event.IP.String()
mac := event.MAC.String()
s.Targets.AddIfNotExist(addr, mac)
if s.Active == false {
return
}
}
}()
s.Events.Add("session.started", nil)
return nil

View file

@ -4,6 +4,7 @@ import (
"fmt"
"sort"
"sync"
"time"
"github.com/evilsocket/bettercap-ng/core"
"github.com/evilsocket/bettercap-ng/net"
@ -63,6 +64,7 @@ func (tp *Targets) AddIfNotExist(ip, mac string) *net.Endpoint {
}
if t, found := tp.Targets[mac]; found {
t.LastSeen = time.Now()
return t
}