GNU/Linux >> Znalost Linux >  >> Linux

Jak zjistím celkový počet TCP spojení pro daný port a časové období podle IP?

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.


Linux
  1. Jak najít modul jádra pro dané zařízení?

  2. Jak můžete zjistit číslo procesoru, na kterém běží vlákno?

  3. Jak mohu definovat DIRECTORY_SEPARATOR pro platformy Windows i Linux?

  1. Jak mohu zabít TCP port 16969 v Bash?

  2. Jak mohu získat aktuální datum a čas v terminálu a nastavit pro něj vlastní příkaz v terminálu?

  3. Jak zjistím počet uživatelů online v Linuxu?

  1. Jak mohu spočítat počet složek na jednotce pomocí Linuxu?

  2. Jak najít soubor .pid pro daný proces

  3. Zkontrolujte počet aktivních připojení na portu 80?