netstat: allow to list XDP sockets

- daemon: Allow to dump XDP sockets from kernel.
 - ui: Added options to filter by RAW protocol and AF_XDP family.
 - Bumped vishvananda/netlink version to v1.3.0.
 - Updated go.mod and go.sum
This commit is contained in:
Gustavo Iñiguez Goia 2025-02-05 00:00:47 +01:00
parent c5e24c04f1
commit 335f2a783d
5 changed files with 50 additions and 15 deletions

View file

@ -10,11 +10,12 @@ require (
github.com/google/uuid v1.3.0
github.com/iovisor/gobpf v0.2.0
github.com/varlink/go v0.4.0
github.com/vishvananda/netlink v1.1.1-0.20220115184804-dd687eb2f2d4
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae
github.com/vishvananda/netlink v1.3.0
github.com/vishvananda/netns v0.0.4
golang.org/x/net v0.17.0
golang.org/x/sys v0.13.0
google.golang.org/grpc v1.32.0
google.golang.org/protobuf v1.26.0
)
require (
@ -27,6 +28,5 @@ require (
golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 // indirect
google.golang.org/protobuf v1.26.0 // indirect
honnef.co/go/tools v0.2.2 // indirect
)

View file

@ -76,10 +76,10 @@ github.com/mdlayher/socket v0.0.0-20211102153432-57e3fa563ecb/go.mod h1:nFZ1EtZY
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/varlink/go v0.4.0 h1:+/BQoUO9eJK/+MTSHwFcJch7TMsb6N6Dqp6g0qaXXRo=
github.com/varlink/go v0.4.0/go.mod h1:DKg9Y2ctoNkesREGAEak58l+jOC6JU2aqZvUYs5DynU=
github.com/vishvananda/netlink v1.1.1-0.20220115184804-dd687eb2f2d4 h1:fB26rIBlWTVJyEB6ONHdoEvUbvwoudH0/cMEXHiD1RU=
github.com/vishvananda/netlink v1.1.1-0.20220115184804-dd687eb2f2d4/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -134,8 +134,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -154,6 +152,8 @@ golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View file

@ -0,0 +1,11 @@
package netlink
import (
vnl "github.com/vishvananda/netlink"
)
// SocketGetXDP dumps all the opened XDP sockets from kernel
func SocketGetXDP() ([]*vnl.XDPDiagInfoResp, error) {
// TODO: enable filtering
return vnl.SocketDiagXDP()
}

View file

@ -8,7 +8,7 @@ import (
"syscall"
"github.com/evilsocket/opensnitch/daemon/log"
daemonNetlink "github.com/evilsocket/opensnitch/daemon/netlink"
"github.com/evilsocket/opensnitch/daemon/netlink"
"github.com/evilsocket/opensnitch/daemon/netstat"
"github.com/evilsocket/opensnitch/daemon/procmon"
"golang.org/x/sys/unix"
@ -22,7 +22,7 @@ const (
// Socket represents every socket dumped from the kernel for the given filter.
type Socket struct {
Socket *daemonNetlink.Socket
Socket *netlink.Socket
Iface string
PID int
Mark uint32
@ -40,6 +40,7 @@ func (pm *SocketsMonitor) dumpSockets() *SocketsTable {
socketList := &SocketsTable{}
socketList.Table = make([]*Socket, 0)
socketList.Processes = make(map[int]*procmon.Process, 0)
for n, opt := range options {
if exclude(pm.Config.Family, opt.Fam) {
continue
@ -48,7 +49,7 @@ func (pm *SocketsMonitor) dumpSockets() *SocketsTable {
continue
}
sockList, err := daemonNetlink.SocketsDump(opt.Fam, opt.Proto)
sockList, err := netlink.SocketsDump(opt.Fam, opt.Proto)
if err != nil {
log.Debug("[sockmon][%d] fam: %d, proto: %d, error: %s", n, opt.Fam, opt.Proto, err)
continue
@ -73,6 +74,26 @@ func (pm *SocketsMonitor) dumpSockets() *SocketsTable {
wg.Wait()
}
if !exclude(pm.Config.Family, unix.AF_XDP) && !exclude(pm.Config.Proto, syscall.IPPROTO_RAW) {
xdpList, err := netlink.SocketGetXDP()
if err == nil {
var wg sync.WaitGroup
for _, xdp := range xdpList {
s := netlink.Socket{}
s.Family = unix.AF_XDP
s.INode = uint32(xdp.XDPDiagMsg.Ino)
s.UID = uint32(xdp.XDPInfo.UID)
s.ID = netlink.SocketID{
Interface: xdp.XDPInfo.Ifindex,
Cookie: xdp.XDPDiagMsg.Cookie,
}
wg.Add(1)
go addSocketToTable(pm.Ctx, &wg, syscall.IPPROTO_RAW, socketList, s)
}
wg.Wait()
}
}
if exclude(pm.Config.Family, unix.AF_PACKET) {
return socketList
}
@ -90,11 +111,11 @@ func (pm *SocketsMonitor) dumpSockets() *SocketsTable {
pktList[n] = struct{}{}
wg.Add(1)
s := daemonNetlink.Socket{}
s := netlink.Socket{}
s.Family = unix.AF_PACKET
s.INode = uint32(e.INode)
s.UID = uint32(e.UserId)
s.ID = daemonNetlink.SocketID{
s.ID = netlink.SocketID{
Interface: uint32(e.Iface),
}
// TODO: report the protocol and type
@ -109,7 +130,7 @@ func exclude(expected, what uint8) bool {
return expected > AnySocket && expected != what
}
func addSocketToTable(ctx context.Context, wg *sync.WaitGroup, proto uint8, st *SocketsTable, s daemonNetlink.Socket) {
func addSocketToTable(ctx context.Context, wg *sync.WaitGroup, proto uint8, st *SocketsTable, s netlink.Socket) {
inode := int(s.INode)
pid := procmon.GetPIDFromINode(inode, fmt.Sprint(inode,
s.ID.Source, s.ID.SourcePort, s.ID.Destination, s.ID.DestinationPort),

View file

@ -518,6 +518,7 @@ class StatsDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
self.comboNetstatProto.addItem("ICMP", 1)
self.comboNetstatProto.addItem("ICMPv6", 58)
self.comboNetstatProto.addItem("IGMP", 2)
self.comboNetstatProto.addItem("RAW", 255)
# These are sockets states. Conntrack uses a different enum.
self.comboNetstatStates.clear()
@ -540,6 +541,8 @@ class StatsDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
self.comboNetstatFamily.addItem("AF_INET", 2)
self.comboNetstatFamily.addItem("AF_INET6", 10)
self.comboNetstatFamily.addItem("AF_PACKET", 17) # 0x11
self.comboNetstatFamily.addItem("AF_XDP", 44)
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))