mirror of
https://github.com/bettercap/bettercap
synced 2025-07-16 10:03:39 -07:00
new: main packet queue is now used to gather network stats, update endpoint, etc
This commit is contained in:
parent
a296dacd74
commit
913c581f9f
4 changed files with 127 additions and 15 deletions
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/evilsocket/bettercap-ng/core"
|
"github.com/evilsocket/bettercap-ng/core"
|
||||||
)
|
)
|
||||||
|
@ -11,6 +12,7 @@ import (
|
||||||
type OnHostResolvedCallback func(e *Endpoint)
|
type OnHostResolvedCallback func(e *Endpoint)
|
||||||
type Endpoint struct {
|
type Endpoint struct {
|
||||||
IP net.IP `json:"-"`
|
IP net.IP `json:"-"`
|
||||||
|
Net *net.IPNet `json:"-"`
|
||||||
IPv6 net.IP `json:"."`
|
IPv6 net.IP `json:"."`
|
||||||
HW net.HardwareAddr `json:"-"`
|
HW net.HardwareAddr `json:"-"`
|
||||||
IpAddress string `json:"ipv4"`
|
IpAddress string `json:"ipv4"`
|
||||||
|
@ -21,12 +23,17 @@ type Endpoint struct {
|
||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
Vendor string `json:"vendor"`
|
Vendor string `json:"vendor"`
|
||||||
ResolvedCallback OnHostResolvedCallback `json:"-"`
|
ResolvedCallback OnHostResolvedCallback `json:"-"`
|
||||||
|
FirstSeen time.Time `json:"first_seen"`
|
||||||
|
LastSeen time.Time `json:"last_seen"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEndpointNoResolve(ip, mac, name string, bits uint32) *Endpoint {
|
func NewEndpointNoResolve(ip, mac, name string, bits uint32) *Endpoint {
|
||||||
hw, _ := net.ParseMAC(mac)
|
hw, _ := net.ParseMAC(mac)
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
e := &Endpoint{
|
e := &Endpoint{
|
||||||
IP: net.ParseIP(ip),
|
IP: net.ParseIP(ip),
|
||||||
|
Net: nil,
|
||||||
HW: hw,
|
HW: hw,
|
||||||
IpAddress: ip,
|
IpAddress: ip,
|
||||||
SubnetBits: bits,
|
SubnetBits: bits,
|
||||||
|
@ -35,8 +42,13 @@ func NewEndpointNoResolve(ip, mac, name string, bits uint32) *Endpoint {
|
||||||
Hostname: name,
|
Hostname: name,
|
||||||
Vendor: OuiLookup(mac),
|
Vendor: OuiLookup(mac),
|
||||||
ResolvedCallback: nil,
|
ResolvedCallback: nil,
|
||||||
|
FirstSeen: now,
|
||||||
|
LastSeen: now,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, netw, _ := net.ParseCIDR(e.CIDR())
|
||||||
|
e.Net = netw
|
||||||
|
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
110
packets/queue.go
110
packets/queue.go
|
@ -1,42 +1,126 @@
|
||||||
package packets
|
package packets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/google/gopacket/pcap"
|
"net"
|
||||||
"sync"
|
"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 {
|
type Activity struct {
|
||||||
iface string
|
IP net.IP
|
||||||
handle *pcap.Handle
|
MAC net.HardwareAddr
|
||||||
lock *sync.Mutex
|
|
||||||
active bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
var err error
|
||||||
|
|
||||||
q := &Queue{
|
q := &Queue{
|
||||||
iface: iface,
|
iface: iface,
|
||||||
handle: nil,
|
handle: nil,
|
||||||
lock: &sync.Mutex{},
|
lock: &sync.Mutex{},
|
||||||
active: true,
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
q.source = gopacket.NewPacketSource(q.handle, q.handle.LinkType())
|
||||||
|
go q.worker()
|
||||||
|
|
||||||
return q, nil
|
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 {
|
func (q *Queue) Send(raw []byte) error {
|
||||||
q.lock.Lock()
|
q.lock.Lock()
|
||||||
defer q.lock.Unlock()
|
defer q.lock.Unlock()
|
||||||
|
|
||||||
if q.active {
|
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 {
|
} else {
|
||||||
return fmt.Errorf("Packet queue is not active.")
|
return fmt.Errorf("Packet queue is not active.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ type Session struct {
|
||||||
Firewall firewall.FirewallManager `json:"-"`
|
Firewall firewall.FirewallManager `json:"-"`
|
||||||
Env *Environment `json:"env"`
|
Env *Environment `json:"env"`
|
||||||
Targets *Targets `json:"targets"`
|
Targets *Targets `json:"targets"`
|
||||||
Queue *packets.Queue `json:"-"`
|
Queue *packets.Queue `json:"packets"`
|
||||||
Input *readline.Instance `json:"-"`
|
Input *readline.Instance `json:"-"`
|
||||||
Active bool `json:"active"`
|
Active bool `json:"active"`
|
||||||
Prompt Prompt `json:"-"`
|
Prompt Prompt `json:"-"`
|
||||||
|
@ -174,7 +174,7 @@ func (s *Session) Start() error {
|
||||||
s.Env.Set("iface.ipv6", s.Interface.Ip6Address)
|
s.Env.Set("iface.ipv6", s.Interface.Ip6Address)
|
||||||
s.Env.Set("iface.mac", s.Interface.HwAddress)
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,6 +227,20 @@ func (s *Session) Start() error {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
s.Active = true
|
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)
|
s.Events.Add("session.started", nil)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/evilsocket/bettercap-ng/core"
|
"github.com/evilsocket/bettercap-ng/core"
|
||||||
"github.com/evilsocket/bettercap-ng/net"
|
"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 {
|
if t, found := tp.Targets[mac]; found {
|
||||||
|
t.LastSeen = time.Now()
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue