mirror of
https://github.com/evilsocket/opensnitch.git
synced 2025-03-04 00:24:40 +01:00
netstat: added option to monitor AF_PACKET sockets
For now, we parse /proc/net/packet, because vishvananda/netlink does not have support to dump AF_PACKET sockets from kernel.
This commit is contained in:
parent
70e868ad8c
commit
83eb82a343
6 changed files with 107 additions and 2 deletions
|
@ -14,6 +14,7 @@ type Entry struct {
|
|||
DstIP net.IP
|
||||
SrcPort uint
|
||||
DstPort uint
|
||||
Iface int
|
||||
UserId int
|
||||
INode int
|
||||
}
|
||||
|
|
61
daemon/netstat/parse_packet.go
Normal file
61
daemon/netstat/parse_packet.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package netstat
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/evilsocket/opensnitch/daemon/core"
|
||||
"github.com/evilsocket/opensnitch/daemon/log"
|
||||
)
|
||||
|
||||
var (
|
||||
// sk RefCnt Type Proto Iface R Rmem User Inode
|
||||
// ffff90b72f893800 3 3 0003 3 1 0 0 257944535
|
||||
packetParser = regexp.MustCompile(`(?i)` +
|
||||
`[a-z0-9]+\s+` + // sk
|
||||
`[0-9]\s+` + // refCnt
|
||||
`([0-9])\s+` + // Type
|
||||
`([0-9a-z]+)\s+` + // proto
|
||||
`([0-9])\s+` + // iface
|
||||
`[0-9]\s+` + // r
|
||||
`[0-9]+\s+` + // rmem
|
||||
`([0-9]+)\s+` + // user
|
||||
`([0-9]+)`, // inode
|
||||
)
|
||||
)
|
||||
|
||||
// ParsePacket scans and retrieves the opened sockets from /proc/net/packet
|
||||
func ParsePacket() ([]Entry, error) {
|
||||
filename := core.ConcatStrings("/proc/net/packet")
|
||||
fd, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
entries := make([]Entry, 0)
|
||||
scanner := bufio.NewScanner(fd)
|
||||
for lineno := 0; scanner.Scan(); lineno++ {
|
||||
// skip column names
|
||||
if lineno == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
line := core.Trim(scanner.Text())
|
||||
m := packetParser.FindStringSubmatch(line)
|
||||
if m == nil {
|
||||
log.Warning("Could not parse netstat line from %s: %s", filename, line)
|
||||
continue
|
||||
}
|
||||
// TODO: get proto, type, etc.
|
||||
en := Entry{}
|
||||
en.Iface = decToInt(m[3])
|
||||
en.UserId = decToInt(m[4])
|
||||
en.INode = decToInt(m[5])
|
||||
|
||||
entries = append(entries, en)
|
||||
}
|
||||
|
||||
return entries, nil
|
||||
}
|
|
@ -5,10 +5,13 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/evilsocket/opensnitch/daemon/log"
|
||||
daemonNetlink "github.com/evilsocket/opensnitch/daemon/netlink"
|
||||
"github.com/evilsocket/opensnitch/daemon/netstat"
|
||||
"github.com/evilsocket/opensnitch/daemon/procmon"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -70,6 +73,35 @@ func (pm *SocketsMonitor) dumpSockets() *SocketsTable {
|
|||
wg.Wait()
|
||||
}
|
||||
|
||||
if exclude(pm.Config.Family, unix.AF_PACKET) {
|
||||
return socketList
|
||||
}
|
||||
entries, err := netstat.ParsePacket()
|
||||
if err != nil {
|
||||
return socketList
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
|
||||
pktList := make(map[int]struct{}, len(entries))
|
||||
for n, e := range entries {
|
||||
if _, isDup := pktList[n]; isDup {
|
||||
continue
|
||||
}
|
||||
pktList[n] = struct{}{}
|
||||
|
||||
wg.Add(1)
|
||||
s := daemonNetlink.Socket{}
|
||||
s.Family = unix.AF_PACKET
|
||||
s.INode = uint32(e.INode)
|
||||
s.UID = uint32(e.UserId)
|
||||
s.ID = daemonNetlink.SocketID{
|
||||
Interface: uint32(e.Iface),
|
||||
}
|
||||
// TODO: report the protocol and type
|
||||
go addSocketToTable(pm.Ctx, &wg, syscall.IPPROTO_RAW, socketList, s)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
return socketList
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package socketsmonitor
|
||||
|
||||
import (
|
||||
//"golang.org/x/sys/unix"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Protos holds valid combinations of protocols, families and socket types that can be created.
|
||||
|
@ -28,4 +29,11 @@ var options = []Protos{
|
|||
{syscall.IPPROTO_UDP, syscall.AF_INET6},
|
||||
{syscall.IPPROTO_UDPLITE, syscall.AF_INET},
|
||||
{syscall.IPPROTO_UDPLITE, syscall.AF_INET6},
|
||||
|
||||
// for AF_PACKET, Type is the "Protocol" (SOCK_DGRAM, SOCK_RAW)
|
||||
{syscall.IPPROTO_RAW, unix.AF_PACKET},
|
||||
// here UDP is SOCK_DGRAM. Does not imply UDP protocol.
|
||||
{syscall.IPPROTO_UDP, unix.AF_PACKET},
|
||||
//{syscall.IPPROTO_IP, unix.AF_PACKET},
|
||||
//{unix.ETH_P_ALL, syscall.AF_PACKET},
|
||||
}
|
||||
|
|
|
@ -539,6 +539,7 @@ class StatsDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
|
|||
self.comboNetstatFamily.addItem(QC.translate("stats", "ALL"), 0)
|
||||
self.comboNetstatFamily.addItem("AF_INET", 2)
|
||||
self.comboNetstatFamily.addItem("AF_INET6", 10)
|
||||
self.comboNetstatFamily.addItem("AF_PACKET", 17) # 0x11
|
||||
self.comboNetstatInterval.currentIndexChanged.connect(lambda index: self._cb_combo_netstat_changed(0, index))
|
||||
self.comboNetstatNodes.activated.connect(lambda index: self._cb_combo_netstat_changed(1, index))
|
||||
self.comboNetstatProto.currentIndexChanged.connect(lambda index: self._cb_combo_netstat_changed(2, index))
|
||||
|
|
|
@ -5,7 +5,7 @@ Family = {
|
|||
'0': 'AF_UNSPEC',
|
||||
'2': 'AF_INET',
|
||||
'10': 'AF_INET6',
|
||||
'11': 'AF_PACKET',
|
||||
'17': 'AF_PACKET',
|
||||
'40': 'AF_VSOCK',
|
||||
'44': 'AF_XDP',
|
||||
'45': 'AF_MCTP',
|
||||
|
@ -27,6 +27,8 @@ Proto = {
|
|||
}
|
||||
|
||||
State = {
|
||||
# special case for protos that don't report state (AF_PACKET)
|
||||
'0': 'LISTEN',
|
||||
'1': 'Established',
|
||||
'2': 'TCP_SYN_SENT',
|
||||
'3': 'TCP_SYN_RECV',
|
||||
|
|
Loading…
Add table
Reference in a new issue