Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Network viewer (ebpf version) #16856

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

ktsaou
Copy link
Member

@ktsaou ktsaou commented Jan 26, 2024

The goal is to provide a "network dependency map".

What is a "network dependency map"?

A "network dependency map" is a tool that users can consult to see all the network dependencies of their systems. So, if a server depends on another server or third party service, the network dependencies explorer should be able to identify this and report it.

For implementing this network dependency map this need only OUTBOUND sockets (i.e. sockets that have been initiated by a process on the local system, towards other systems). For each such socket we need:

  1. The destination IP (IPv4 or IPv6)
  2. The destination Port
  3. The protocol (tcp4, tcp6, udp4, upd6)
  4. The first time it was seen
  5. The last time it was seen
  6. The process name that last initiated this connection

To interconnect servers we also need to know the IPs they consider local. So, for each local-IP of a server we need:

  1. The IP (IPv4 or IPv6)
  2. The first time it was seen
  3. The last time it was seen

Classifying the direction of sockets

Sockets is based on the information available on each socket. Such information is the local IP and port, the remote IP and port, the PID of the process that owns the socket and therefore its command name and various other socket attributes like the socket state.

  1. LISTEN: are all the TCP sockets that are in TCP_LISTEN state and all sockets that their remote IP is zero. The later (remote IP is zero) can be used to classify UDP sockets as LISTEN.
  2. LOCAL: are all the non-LISTEN sockets that either their source IP or their remote IP are loopback addresses. Loopback addresses are those in 127.0.0.0/8 and ::1. When IPv4 addresses are mapped into IPv6, their IPv4 addresses should be checked too.
    Also, LOCAL are those sockets that their remote-IP is one of the IPs that appear as local-IP on another socket. This way we detect when processes of a host communicate via a non-loopback IP of the same host.
  3. INBOUND: are all the non-LISTEN and non-LOCAL sockets that their local port is a port of another socket that is marked as LISTEN. This way we can detect that established sockets have been initiated from a listening server running on the system.
  4. OUTBOUND: are all the other sockets. In other words, if a socket's remote IP is not zero, not loopback and not another IP that the host has, and its local-port is not listened to, then it is an outbound socket some process on this system initiated.

Multi-Node view

In a multi-node view of the network dependency map, it is important to be able to connect nodes together, so that we can understand how they interact with each other.

For this we need each node to provide 2 lists:

  1. The list of OUTBOUND connections it has (destination IP, port, protocol)
  2. The list of IPs it considers as local-IPs (source IP of all its connections).

By combining these 2 lists across multiple servers, we can build interconnects between the nodes.

Special care is needed in cases the local-IPs across servers are overlapping. This may happen because servers have internal bridges for containers or VMs. These internal IPs should normally be classified as LOCAL, because they start and end in the same server. Still we may have to deal with the situation that a remote-IP of a server appear as local-IP on multiple other servers.

Once all the known servers contribute these 2 lists, we could then visualize a network dependency map, showing how servers depend on each other and how the whole infrastructure depends on third parties.

Implementation

Bootstrapping

local-listeners is now using a library called local-sockets.h which is able to provide a list of all currently open sockets, categorized as LISTEN, LOCAL, INBOUND and OUTBOUND. This works for IPv4 and IPv6, TCP and UDP. You can see the full classification of sockets on any system by running local-listeners debug using the version of local-listeners on this PR.

This library is used to initialize the network dependency map with the information we need when Netdata starts (or restarts).

Detection with EBPF

An EBPF program intercepts sockets creation and status change and records the changes into the 2 lists (local IPs, OUTBOUND sockets) required for the network dependency map.

@ktsaou
Copy link
Member Author

ktsaou commented Jan 29, 2024

Didn't close it...

@ktsaou ktsaou reopened this Jan 29, 2024
@ktsaou ktsaou changed the title WIP: Network viewer WIP: Network viewer (ebpf version) Jan 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/aclk area/build Build system (autotools and cmake). area/collectors Everything related to data collection
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant