Linux
banshee/linux-collection/linux/ssh/
tcp
TCP connections of a Linux by SSH, IPv4 and IPv6: established, TIME-WAIT, CLOSE-WAIT, listening.
by banshee1 installation2 versions
v2Latest
Published on October 28, 2026. One naming convention across collections; documentation completed.
// The TCP connections of a Linux, by SSH, IPv4 and IPv6 together: those established, those waiting to be
// closed on either side (TIME-WAIT, CLOSE-WAIT), the listening ports and the total.
// Reads /proc/net/tcp and /proc/net/tcp6 with cat, counted by awk on the target: the kernel writes these
// files the same way on Alpine, Debian and Fedora, and the awk program only uses what BusyBox awk, mawk
// (Debian) and gawk (Fedora) all know. tcp6 is missing on a machine without IPv6: cat keeps quiet.
// The counting happens on the target, so that a server with a hundred thousand connections returns a few lines.
need('protocol:ssh');
output('established', 'number', array('label' => 'Established connections'));
output('time-wait', 'number', array('label' => 'Connections in TIME-WAIT'));
output('close-wait', 'number', array('label' => 'Connections in CLOSE-WAIT'));
output('listen', 'number', array('label' => 'Listening ports'));
output('total', 'number', array('label' => 'TCP connections'));
// No threshold by default: what is normal depends on the role of the server. CLOSE-WAIT piling up says an
// application does not close its connections.
watch.above('too-many', 'Too many TCP connections', 'established', array('enabled' => false));
watch.habit('unusual', 'Unusual number of connections', 'established', array('enabled' => false));
watch.above('close-wait', 'Connections left open', 'close-wait', array('warning' => 100, 'for' => '3 runs', 'enabled' => false));
// One line per state present, "01 42": the state in hexadecimal (the 4th column of /proc/net/tcp, 01
// ESTABLISHED, 06 TIME_WAIT, 08 CLOSE_WAIT, 0A LISTEN...), then the number of connections. The header of
// each file holds "st" there, which the pattern leaves out.
$read = ssh.run("cat /proc/net/tcp /proc/net/tcp6 2>/dev/null | awk '$4 ~ /^[0-9A-F][0-9A-F]$/ { n[$4]++ } END { for (s in n) print s, n[s] }'");
$count = array();
$total = 0;
foreach (text.lines($read['output']) as $line) {
$words = text.words($line);
if (list.count($words) == 2 && text.is_number($words[1])) {
$count[$words[0]] = $words[1];
$total = $total + $words[1];
}
}
// The collector's own SSH connection is a TCP connection: reading none is reading nothing.
if ($total == 0) {
fail('misconfigured', 'No connection found in /proc/net/tcp', $read['output'] . $read['errors']);
}
value('established', list.get($count, '01', 0));
value('time-wait', list.get($count, '06', 0));
value('close-wait', list.get($count, '08', 0));
value('listen', list.get($count, '0A', 0));
value('total', $total);