Schalten Sie iptables ein und setzen Sie es auf LOG
für eingehende Verbindungen. Beispielregel:
-A INPUT --state NEW -p tcp --dport 4711 -j LOG
(wobei 4711 der Port ist, den Sie verfolgen möchten).
Führen Sie dann das resultierende Protokoll durch ein beliebiges Skript, das die Zusammenfassung für Sie erledigen kann.
Sie können tcpdump verwenden, um alle SYN-Pakete (ohne ACK) zu protokollieren:
tcpdump "dst port 4711 and tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn"
oder alle SYN+ACK-Pakete (aufgebaute Verbindungen) protokollieren:
tcpdump "src port 4711 and tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)"
Und dann kombiniere es mit einem wc -l
um alle Zeilen zu zählen
Sie brauchen auch eine Möglichkeit, feste Zeiträume zu messen (Sie könnten einen Cron haben, der ihm in regelmäßigen Abständen einfach ein SIGINT sendet, tcpdump zählt Bytes und Pakete, protokolliert aber nur die Zeit)
Update:Unnötig zu sagen, schauen Sie sich die Manpage von tcpdump an und erwägen Sie die Verwendung einiger Optionen wie:-i
(nur eine Schnittstelle hören), -p
(Promiskuitiver Modus deaktivieren; weniger invasiv) oder einige Ausgabeoptionen. Tcpdump benötigt Root-Berechtigungen und Ihr Chef mag es vielleicht nicht, weil es eine Art Hacker-Tool ist. Andererseits müssen Sie nichts an Ihrem System anfassen, um es auszuführen (im Gegensatz zum iptables LOG
Lösung)
Bitte beachten Sie auch den kleinen src/dsk-Unterschied im Filter. Wenn Sie SYN+ACK-Pakete abfangen und Verbindungen zu zählen möchten einen Server auf Port 4711 benötigen Sie src. Wenn Sie SYN+!ACK-Pakete für dasselbe Ergebnis abfangen, benötigen Sie dst. Wenn Sie Verbindungen auf dem Server selbst zählen, müssen Sie immer das Gegenteil verwenden.
SystemTap-Lösung
Vom Beispiel tcp_connections.stp inspiriertes Skript:
#!/usr/bin/env stap
# To monitor another TCP port run:
# stap -G port=80 tcp_connections.stp
# or
# ./tcp_connections.stp -G port=80
global port = 22
global connections
function report() {
foreach (addr in connections) {
printf("%s: %d\n", addr, @count(connections[addr]))
}
}
probe end {
printf("\n=== Summary ===\n")
report()
}
probe kernel.function("tcp_accept").return?,
kernel.function("inet_csk_accept").return? {
sock = $return
if (sock != 0) {
local_port = inet_get_local_port(sock)
if (local_port == port) {
remote_addr = inet_get_ip_source(sock)
connections[remote_addr] <<< 1
printf("%s New connection from %s\n", ctime(gettimeofday_s()), remote_addr)
}
}
}
Ausgabe:
[[email protected] ~]# ./tcp_connections.stp -G port=80
Mon Mar 17 04:13:03 2014 New connection from 192.168.122.1
Mon Mar 17 04:13:04 2014 New connection from 192.168.122.1
Mon Mar 17 04:13:08 2014 New connection from 192.168.122.4
^C
=== Summary ===
192.168.122.1: 2
192.168.122.4: 1
Strace-Lösung
Starten Sie das Programm entweder unter strace:
strace -r -f -e trace=accept -o /tmp/strace ${PROGRAM} ${ARGS}
oder verfolgen Sie ein bereits laufendes Programm:
strace -r -f -e trace=accept -o /tmp/strace -p ${PID_OF_PROGRAM}
-r
druckt einen relativen Zeitstempel beim Eintritt in jeden Systemaufruf, falls er später für eine zusätzliche Leistungsanalyse benötigt wird. -f
verfolgt untergeordnete Prozesse und wird möglicherweise nicht benötigt.
Die Ausgabe sieht in etwa so aus:
999 0.000000 accept(3, {sa_family=AF_INET, sin_port=htons(34702), sin_addr=inet_addr("192.168.122.4")}, [16]) = 5
999 0.008079 --- SIGCHLD (Child exited) @ 0 (0) ---
999 1.029846 accept(3, {sa_family=AF_INET, sin_port=htons(34703), sin_addr=inet_addr("192.168.122.4")}, [16]) = 5
999 0.008276 --- SIGCHLD (Child exited) @ 0 (0) ---
999 3.580122 accept(3, {sa_family=AF_INET, sin_port=htons(50114), sin_addr=inet_addr("192.168.122.1")}, [16]) = 5
und kann gefiltert werden mit:
# gawk 'match($0, /^([0-9]+)[[:space:]]+([0-9.]+)[[:space:]]+accept\(.*htons\(([^)]+)\),.*inet_addr\("([^"]+)"\).*[[:space:]]+=[[:space:]]+([1-9][0-9]*)/, m) {connections[m[4]]++} END {for (addr in connections) printf("%s: %d\n", addr, connections[addr]); }' /tmp/strace
192.168.122.4: 3
192.168.122.1: 2
Kurze Erläuterung des AKW-Einzeilers:m[1]
ist die PID, m[2]
ist der Zeitstempel, m[3]
ist der entfernte Port und m[4]
ist die entfernte Adresse.
Der Vorteil dieser Lösung ist, dass root nicht erforderlich ist, wenn der Server unter demselben Benutzer läuft. Der Nachteil ist, dass alle Verbindungen gezählt werden, es gibt keine Filterung, also funktioniert es nicht, wenn die Anwendung auf mehreren Ports lauscht.