eBPF: ignore netlink errors if there're no connections

When enabling the eBPF monitor method we dump the active connections,
but in some cases there're no active connections, and because of this
we're failing enabling this monitor method.

If there're no connections established, netlink returns 0 entries. It's
not clear if it's an indication of error in some cases or the expected
result.

Either way:
- fail only if we're unable to load the eBPF module.
- dump TCP IPv6 connections only if IPv6 is enabled in the syste,-
This commit is contained in:
Gustavo Iñiguez Goia 2021-05-29 00:16:18 +02:00
parent 1db03b5570
commit e5b54f0a6b
3 changed files with 43 additions and 38 deletions

View file

@ -223,7 +223,7 @@ func netlinkRequest(sockReq *SocketRequest, family uint8, proto uint8, srcPort,
return nil, err
}
if len(msgs) == 0 {
return nil, errors.New("Warning, no message nor error from netlink")
return nil, errors.New("Warning, no message nor error from netlink, or no connections found")
}
var sock []*Socket
for n, m := range msgs {

View file

@ -8,6 +8,7 @@ import (
"syscall"
"unsafe"
"github.com/evilsocket/opensnitch/daemon/core"
"github.com/evilsocket/opensnitch/daemon/log"
daemonNetlink "github.com/evilsocket/opensnitch/daemon/netlink"
"github.com/evilsocket/opensnitch/daemon/procmon"
@ -123,8 +124,7 @@ func Start() error {
// save already established connections
socketListTCP, err := daemonNetlink.SocketsDump(uint8(syscall.AF_INET), uint8(syscall.IPPROTO_TCP))
if err != nil {
log.Error("eBPF could not dump TCP sockets via netlink: %v", err)
return err
log.Debug("eBPF could not dump TCP sockets via netlink: %v", err)
}
for _, sock := range socketListTCP {
inode := int((*sock).INode)
@ -135,18 +135,20 @@ func Start() error {
alreadyEstablished.Unlock()
}
socketListTCPv6, err := daemonNetlink.SocketsDump(uint8(syscall.AF_INET6), uint8(syscall.IPPROTO_TCP))
if err != nil {
log.Error("eBPF could not dump TCPv6 sockets via netlink: %v", err)
return err
}
for _, sock := range socketListTCPv6 {
inode := int((*sock).INode)
pid := procmon.GetPIDFromINode(inode, fmt.Sprint(inode,
(*sock).ID.Source, (*sock).ID.SourcePort, (*sock).ID.Destination, (*sock).ID.DestinationPort))
alreadyEstablished.Lock()
alreadyEstablished.TCPv6[sock] = pid
alreadyEstablished.Unlock()
if core.IPv6Enabled {
socketListTCPv6, err := daemonNetlink.SocketsDump(uint8(syscall.AF_INET6), uint8(syscall.IPPROTO_TCP))
if err != nil {
log.Debug("eBPF could not dump TCPv6 sockets via netlink: %v", err)
} else {
for _, sock := range socketListTCPv6 {
inode := int((*sock).INode)
pid := procmon.GetPIDFromINode(inode, fmt.Sprint(inode,
(*sock).ID.Source, (*sock).ID.SourcePort, (*sock).ID.Destination, (*sock).ID.DestinationPort))
alreadyEstablished.Lock()
alreadyEstablished.TCPv6[sock] = pid
alreadyEstablished.Unlock()
}
}
}
go monitorMaps()

View file

@ -5,6 +5,7 @@ import (
"time"
"unsafe"
"github.com/evilsocket/opensnitch/daemon/core"
"github.com/evilsocket/opensnitch/daemon/log"
daemonNetlink "github.com/evilsocket/opensnitch/daemon/netlink"
elf "github.com/iovisor/gobpf/elf"
@ -70,7 +71,7 @@ func monitorAlreadyEstablished() {
}
socketListTCP, err := daemonNetlink.SocketsDump(uint8(syscall.AF_INET), uint8(syscall.IPPROTO_TCP))
if err != nil {
log.Error("eBPF error in dumping TCP sockets via netlink")
log.Debug("eBPF error in dumping TCP sockets via netlink")
continue
}
alreadyEstablished.Lock()
@ -94,31 +95,33 @@ func monitorAlreadyEstablished() {
}
alreadyEstablished.Unlock()
socketListTCPv6, err := daemonNetlink.SocketsDump(uint8(syscall.AF_INET6), uint8(syscall.IPPROTO_TCP))
if err != nil {
log.Error("eBPF error in dumping TCPv6 sockets via netlink")
continue
}
alreadyEstablished.Lock()
for aesock := range alreadyEstablished.TCPv6 {
found := false
for _, sock := range socketListTCPv6 {
if (*aesock).INode == (*sock).INode &&
//inodes are unique enough, so the matches below will never have to be checked
(*aesock).ID.SourcePort == (*sock).ID.SourcePort &&
(*aesock).ID.Source.Equal((*sock).ID.Source) &&
(*aesock).ID.Destination.Equal((*sock).ID.Destination) &&
(*aesock).ID.DestinationPort == (*sock).ID.DestinationPort &&
(*aesock).UID == (*sock).UID {
found = true
break
if core.IPv6Enabled {
socketListTCPv6, err := daemonNetlink.SocketsDump(uint8(syscall.AF_INET6), uint8(syscall.IPPROTO_TCP))
if err != nil {
log.Debug("eBPF error in dumping TCPv6 sockets via netlink: %s", err)
continue
}
alreadyEstablished.Lock()
for aesock := range alreadyEstablished.TCPv6 {
found := false
for _, sock := range socketListTCPv6 {
if (*aesock).INode == (*sock).INode &&
//inodes are unique enough, so the matches below will never have to be checked
(*aesock).ID.SourcePort == (*sock).ID.SourcePort &&
(*aesock).ID.Source.Equal((*sock).ID.Source) &&
(*aesock).ID.Destination.Equal((*sock).ID.Destination) &&
(*aesock).ID.DestinationPort == (*sock).ID.DestinationPort &&
(*aesock).UID == (*sock).UID {
found = true
break
}
}
if !found {
delete(alreadyEstablished.TCPv6, aesock)
}
}
if !found {
delete(alreadyEstablished.TCPv6, aesock)
}
alreadyEstablished.Unlock()
}
alreadyEstablished.Unlock()
}
}