shellgraph

How the collector works

One scan from start to end, with the rules for service names, connection direction, samples and containers.

A scan, step by step

  1. The collector gets the list of Environments and VLANs from the server.
  2. You select a VLAN, in a menu or with --env and --vlan.
  3. The collector gets the configuration of the VLAN from the server: the CIDR, the SSH port and the credential.
  4. The collector tests the SSH port of each address in the CIDR. It connects to each address that answers.
  5. On each server, the collector runs a fixed script that only reads data. The script gets the processes, the addresses and the TCP sockets.
  6. The collector finds the services, the ports where they listen, and their connections.
  7. The collector sends one report for the complete VLAN to the server.
  8. The server replaces the data of each host in the VLAN. The map changes to match.

How a service gets its name

  1. A process in a Docker or Podman container: the name of the container.
  2. A process in a systemd service: the name of the unit, for example nginx.service.
  3. Other processes: the process name, for example java.

Two java programs on one host are two services. To tell them apart, the collector removes the digits from each command line and makes a short hash. A restart changes the process ID, and sometimes a port number, but the hash stays the same.

How the collector finds the direction

The ss command shows each socket, but not which side started the connection. The collector decides:

  • A connection to a port where the service listens is inbound. The other side is a client.
  • All other connections are outbound. The service calls the other side.

A connection between two services of the same host shows two times in ss, one time for each side. The collector keeps only the outbound side and records which local service listens. That is how the map shows calls inside a host, for example an application that calls a local Redis.

The collector does not report its own SSH session.

Samples

ss shows the sockets at one moment. The collector reads them 3 times by default, 5 seconds apart, and joins the results. Each connection has the number of samples that found it. More samples find more short connections. They also make the scan longer: with --samples 5, each host takes approximately 20 seconds instead of 10.

Containers

The collector finds Docker and Podman containers without root access to the container runtime:

  • It reads /proc/<pid>/cgroup to find the processes of each container.
  • It reads the sockets of the container network namespace from /proc/<pid>/net/tcp and /proc/<pid>/net/tcp6. It does not use nsenter.
  • It reads the addresses of the container from /proc/<pid>/net/fib_trie.
  • A port published with -p shows as a listen of the container.
  • A container with --network host uses the sockets of the host. The systemd unit of the process links it to its container.

If the SSH user cannot run docker ps or podman ps, the service has the short container ID as its name.

Host keys

The first time that the collector connects to an address, it accepts the host key and sends its fingerprint to the server (trust on first use). At the next scans, the server sends the known fingerprints to the collector. If a key is different, the collector does not collect the host, and the result is hostkey_changed. An administrator must accept the new key on the host page.

Limits

  • If /proc is mounted with hidepid, the collector cannot read the containers of other users.
  • Rootless Podman containers of other users are not tested.
  • Kubernetes pods and UDP are not supported.