improved connections parsing

Under certain conditions, when we dumped inodes via netlink, we were
linking network connections to wrong applications.

- To improve this situation:

1) Use netfilter's UID by default:
   Sometimes the UID reported via netlink was different than the one
   reported by libnetfilter. libnetfilter UID is always correct.
   If you had a rule that filtered by UID, this problem could cause to
   prompt you again to allow the connection.

2) Use the netlink entry that matches exactly the properties of an
   outgoing connection:
   There're some in-kernel sockets that doesn't match 1:1 outgoing
   connections (daemon/netlink/socket.go#L22).
   In order to identify the applications that initiate these network
   connections we use a workaround. But under certain conditions
   (source port reuse), we were associating connections to wrong
   applications.
   So in order to avoid this problem, if there's a 1:1 match use that
   netlink entry. If not, fallback to the workaround.

- misc: added more logs to better debug these issues.
This commit is contained in:
Gustavo Iñiguez Goia 2021-11-15 13:26:52 +01:00
parent 743ef71d7e
commit 479b8ded59
2 changed files with 12 additions and 10 deletions

View file

@ -83,7 +83,7 @@ func newConnectionImpl(nfp *netfilter.Packet, c *Connection, protoType string) (
}
pid := -1
var uid int
uid := -1
if procmon.MethodIsEbpf() {
pid, uid, err = ebpf.GetPid(c.Protocol, c.SrcPort, c.SrcIP, c.DstIP, c.DstPort)
if err != nil {
@ -118,17 +118,17 @@ func newConnectionImpl(nfp *netfilter.Packet, c *Connection, protoType string) (
for n, inode := range inodeList {
pid = procmon.GetPIDFromINode(inode, fmt.Sprint(inode, c.SrcIP, c.SrcPort, c.DstIP, c.DstPort))
if pid != -1 {
log.Debug("[%d] PID found %d", n, pid)
log.Debug("[%d] PID found %d [%d]", n, pid, inode)
c.Entry.INode = inode
break
}
}
}
if uid != -1 {
c.Entry.UserId = uid
} else if c.Entry.UserId == -1 && nfp.UID != 0xffffffff {
if nfp.UID != 0xffffffff {
c.Entry.UserId = int(nfp.UID)
} else {
c.Entry.UserId = uid
}
if pid == os.Getpid() {

View file

@ -44,8 +44,9 @@ func GetSocketInfo(proto string, srcIP net.IP, srcPort uint, dstIP net.IP, dstPo
if sock.UID != 0xffffffff {
uid = int(sock.UID)
}
log.Debug("[%d/%d] outgoing connection: %d:%v -> %v:%d || netlink response: %d:%v -> %v:%d inode: %d - loopback: %v multicast: %v unspecified: %v linklocalunicast: %v ifaceLocalMulticast: %v GlobalUni: %v ",
log.Debug("[%d/%d] outgoing connection uid: %d, %d:%v -> %v:%d || netlink response: %d:%v -> %v:%d inode: %d - loopback: %v multicast: %v unspecified: %v linklocalunicast: %v ifaceLocalMulticast: %v GlobalUni: %v ",
n, len(sockList),
int(sock.UID),
srcPort, srcIP, dstIP, dstPort,
sock.ID.SourcePort, sock.ID.Source,
sock.ID.Destination, sock.ID.DestinationPort, sock.INode,
@ -62,14 +63,11 @@ func GetSocketInfo(proto string, srcIP net.IP, srcPort uint, dstIP net.IP, dstPo
((sock.ID.Destination.IsGlobalUnicast() || sock.ID.Destination.IsLoopback()) && sock.ID.Destination.Equal(dstIP)) {
inodes = append([]int{int(sock.INode)}, inodes...)
continue
} else if sock.ID.SourcePort == uint16(srcPort) && sock.ID.Source.Equal(srcIP) &&
(sock.ID.DestinationPort == uint16(dstPort)) {
inodes = append([]int{int(sock.INode)}, inodes...)
continue
}
log.Debug("GetSocketInfo() invalid: %d:%v -> %v:%d", sock.ID.SourcePort, sock.ID.Source, sock.ID.Destination, sock.ID.DestinationPort)
}
// handle special cases (see function description): ntp queries (123), broadcasts, incomming connections.
if len(inodes) == 0 && len(sockList) > 0 {
for n, sock := range sockList {
if sockList[n].ID.Destination.Equal(net.IPv4zero) || sockList[n].ID.Destination.Equal(net.IPv6zero) {
@ -79,6 +77,10 @@ func GetSocketInfo(proto string, srcIP net.IP, srcPort uint, dstIP net.IP, dstPo
sockList[n].ID.SourcePort, sockList[n].ID.Source,
sockList[n].ID.Destination, sockList[n].ID.DestinationPort,
sockList[n].INode, TCPStatesMap[sock.State])
} else if sock.ID.SourcePort == uint16(srcPort) && sock.ID.Source.Equal(srcIP) &&
(sock.ID.DestinationPort == uint16(dstPort)) {
inodes = append([]int{int(sock.INode)}, inodes...)
continue
} else {
log.Debug("netlink socket not found, EXCLUDING entry: %d:%v -> %v:%d || %d:%v -> %v:%d inode: %d state: %s",
srcPort, srcIP, dstIP, dstPort,