Zapněte iptables a nastavte jej na LOG
pro příchozí spojení. Příklad pravidla:
-A INPUT --state NEW -p tcp --dport 4711 -j LOG
(kde 4711 je port, který chcete sledovat).
Potom spusťte výsledný protokol pomocí libovolného skriptu, který za vás udělá shrnutí.
Pomocí tcpdump můžete protokolovat všechny pakety SYN (bez ACK):
tcpdump "dst port 4711 and tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn"
nebo zaznamenat všechny pakety SYN+ACK (navázaná spojení):
tcpdump "src port 4711 and tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)"
A pak jej zkombinujte s wc -l
spočítat všechny řádky
Také byste potřebovali způsob, jak měřit pevné časové úseky (můžete mít cron, aby mu v pravidelných intervalech posílal SIGINT, tcpdump bude počítat bajty a pakety, ale zaznamená pouze čas)
Aktualizace:není nutné říkat, podívejte se na manuálovou stránku tcpdump a zvažte použití některých možností, jako je:-i
(poslouchejte pouze jedno rozhraní), -p
(zakázat promiskuitní režim; méně invazivní) nebo některé možnosti výstupu. Tcpdump potřebuje oprávnění root a vašemu šéfovi se to nemusí líbit, protože je to druh hackerského nástroje. Na druhou stranu se k jeho spuštění nemusíte na systému ničeho dotýkat (na rozdíl od iptables LOG
řešení)
Všimněte si také malého rozdílu src/dsk ve filtru. Pokud zachytíte pakety SYN+ACK a chcete počítat spojení do server na portu 4711 potřebujete src. Pokud zachytáváte pakety SYN+!ACK pro stejný výsledek, potřebujete dst. Pokud počítáte připojení na samotném serveru, musíte vždy použít obrácený postup.
Řešení SystemTap
Skript inspirovaný příkladem tcp_connections.stp:
#!/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)
}
}
}
Výstup:
[[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 řešení
Buď spusťte program pod strace:
strace -r -f -e trace=accept -o /tmp/strace ${PROGRAM} ${ARGS}
nebo sledovat již běžící program:
strace -r -f -e trace=accept -o /tmp/strace -p ${PID_OF_PROGRAM}
-r
vytiskne relativní časové razítko při vstupu do každého systémového volání pro případ, že by to bylo později potřeba pro další analýzu výkonu. -f
sleduje podřízené procesy a nemusí být potřeba.
Výstup vypadá asi takto:
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
a lze jej filtrovat pomocí:
# 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
Krátké vysvětlení AKW one-liner:m[1]
je PID, m[2]
je časové razítko, m[3]
je vzdálený port a m[4]
je vzdálená adresa.
Výhoda tohoto řešení spočívá v tom, že root není vyžadován, pokud server běží pod stejným uživatelem. nevýhoda je, že se počítají všechna připojení, neexistuje žádné filtrování, takže to nebude fungovat, pokud aplikace naslouchá na více portech.