Jak przechwytywać i analizować ruch sieciowy za pomocą tcpdump?

tcpdump to niesamowite narzędzie wiersza poleceń do wąchania sieci. Jest to branżowy standard przechwytywania i analizowania pakietów TCP/IP.

Narzędzie tcpdump może być bardzo pomocne przy rozwiązywaniu problemów z siecią. Pakiety można zapisać do pliku i później analizować. Dobrym pomysłem jest uruchamianie tego narzędzia od czasu do czasu, aby mieć oko na swoją sieć.

Jak wygląda wyjście tcpdump?

tcpdump pozwala na sprawdzenie nagłówków pakietów TCP/IP. Drukuje jedną linię dla każdego pakietu, a polecenie działa do momentu naciśnięcia Ctrl + C, aby zakończyć.

Przyjrzyjmy się jednej linii z przykładowego wyjścia:

20:58:26.765637 IP 10.0.0.50.80 > 10.0.0.1.53181: Flags [F.], seq 1, ack 2, win 453, options [nop,nop,TS val 3822939 ecr 249100129], length 0

Każda linia zawiera

  • Sygnatura czasowa systemu Unix (20:58:26.765637)
  • protokół (IP)
  • źródłowa nazwa hosta lub adres IP oraz numer portu (10.0.0.50.80)
  • docelowa nazwa hosta lub adres IP oraz numer portu (10.0.0.1.53181)
  • Flagi TCP (flagi [F.]). Flagi wskazują stan połączenia. Może to obejmować więcej niż jedną wartość, jak w tym przykładzie [F.] dla FIN-ACK. To pole może mieć następujące wartości:
    • S – SYN. Pierwszy krok w nawiązaniu połączenia.
    • F – FIN. Zakończenie połączenia.
    • . – ACK. Pomyślnie odebrano pakiet potwierdzenia.
    • P – Pchnij. Nakazuje odbiornikowi przetwarzanie pakietów zamiast ich buforowania.
    • R – RST. Komunikacja zatrzymana.
  • Numer sekwencyjny danych w pakiecie. (sekwencja 1)
  • Numer potwierdzenia (ack 2)
  • Rozmiar okna (win 453). Liczba bajtów dostępnych w buforze odbiorczym. Następnie następują opcje TCP.
  • Długość ładunku danych. (długość 0)

Instalacja

W dystrybucjach opartych na Debianie tcpdump można zainstalować za pomocą polecenia APT:

# apt install tcpdump -y

W dystrybucjach opartych na RPM tcpdump można zainstalować za pomocą YUM :

# yum install tcpdump -y

Lub używając DNF, jeśli RHEL 8

# dnf install tcpdump -y

Opcje polecenia tcpdump

Musisz być rootem, aby uruchomić tcpdump. Zawiera wiele opcji i filtrów. Uruchomienie tcpdump bez żadnych opcji spowoduje przechwycenie wszystkich pakietów przepływających przez domyślny interfejs.

Aby zobaczyć listę interfejsów sieciowych dostępnych w systemie i na których tcpdump może przechwytywać pakiety.

# tcpdump -D

Lub

# Tcpdump --list-interfaces
1.eth0
2.nflog (Linux netfilter log (NFLOG) interface)
3.nfqueue (Linux netfilter queue (NFQUEUE) interface)
4.eth1
5.any (Pseudo-device that captures on all interfaces)
6.lo [Loopback]

Jest to szczególnie przydatne w systemach, które nie mają polecenia do wyświetlania listy interfejsów.

Aby przechwycić pakiety przepływające przez określony interfejs, użyj flagi -i z nazwą interfejsu. Bez interfejsu -i tcpdump pobierze pierwszy napotkany interfejs sieciowy.

# tcpdump -i eth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
01:06:09.278817 IP vagrant-ubuntu-trusty-64 > 10.0.0.51: ICMP echo request, id 4761, seq 1, length 64
01:06:09.279374 IP 10.0.0.51 > vagrant-ubuntu-trusty-64: ICMP echo reply, id 4761, seq 1, length 64
01:06:10.281142 IP vagrant-ubuntu-trusty-64 > 10.0.0.51: ICMP echo request, id 4761, seq 2, length 64

Flaga -v zwiększa ilość wyświetlanych informacji o pakietach, -vv daje jeszcze więcej szczegółów.

Domyślnie tcpdump tłumaczy adresy IP na nazwy hostów, a także używa nazw usług zamiast numerów portów. Jeśli DNS jest uszkodzony lub nie chcesz, aby tcpdump wykonywał wyszukiwanie nazw, użyj opcji -n.

# tcpdump -n
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
04:19:07.675216 IP 10.0.2.15.22 > 10.0.2.2.50422: Flags [P.], seq 2186733178:2186733278, ack 204106815, win 37232, length 100
04:19:07.675497 IP 10.0.2.2.50422 > 10.0.2.15.22: Flags [.], ack 100, win 65535, length 0
04:19:07.675747 IP 10.0.2.15.22 > 10.0.2.2.50422: Flags [P.], seq 100:136, ack 1, win 37232, length 36
04:19:07.675902 IP 10.0.2.2.50422 > 10.0.2.15.22: Flags [.], ack 136, win 65535, length 0
04:19:07.676142 IP 10.0.2.15.22 > 10.0.2.2.50422: Flags [P.], seq 136:236, ack 1, win 37232, length 100

Aby przechwycić tylko zestaw linii, powiedzmy 5, użyj flagi -c:

#tcpdump -c 5
04:19:07.675216 IP 10.0.2.15.22 > 10.0.2.2.50422: Flags [P.], seq 2186733178:2186733278, ack 204106815, win 37232, length 100
04:19:07.675497 IP 10.0.2.2.50422 > 10.0.2.15.22: Flags [.], ack 100, win 65535, length 0
04:19:07.675747 IP 10.0.2.15.22 > 10.0.2.2.50422: Flags [P.], seq 100:136, ack 1, win 37232, length 36
04:19:07.675902 IP 10.0.2.2.50422 > 10.0.2.15.22: Flags [.], ack 136, win 65535, length 0
04:19:07.676142 IP 10.0.2.15.22 > 10.0.2.2.50422: Flags [P.], seq 136:236, ack 1, win 37232, length 100
5 packets captured

Domyślne wyjście tcpdump wykorzystuje znaczniki czasu systemu Unix. Aby przechwytywać pakiety z czytelnym dla człowieka znacznikiem czasu:

# tcpdump -tttt
2020-07-06 04:30:12.203638 IP 10.0.2.15.22 > 10.0.2.2.50422: Flags [P.], seq 2186734102:2186734138, ack 204107103, win 37232, length 36
2020-07-06 04:30:12.203910 IP 10.0.2.2.50422 > 10.0.2.15.22: Flags [.], ack 36, win 65535, length 0
2020-07-06 04:30:12.204292 IP 10.0.2.15.22 > 10.0.2.2.50422: Flags [P.], seq 36:72, ack 1, win 37232, length 36
2020-07-06 04:30:12.204524 IP 10.0.2.2.50422 > 10.0.2.15.22: Flags [.], ack 72, win 65535, length 0
2020-07-06 04:30:12.204658 IP 10.0.2.15.22 > 10.0.2.2.50422: Flags [P.], seq 72:108, ack 1, win 37232, length 36

wyrażenia filtra tcpdump

Wyrażenia filtrów wybierają, które nagłówki pakietów będą wyświetlane. Jeśli nie zastosowano żadnych filtrów, wyświetlane są wszystkie nagłówki pakietów. Powszechnie używane filtry to port, host, src, dst, tcp, udp, icmp.

filtr portu

Użyj filtru portów, aby wyświetlić pakiety docierające do określonego portu:

# Tcpdump -i eth1 -c 5 port 80
23:54:24.978612 IP 10.0.0.1.53971 > 10.0.0.50.80: Flags [SEW], seq 53967733, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 256360128 ecr 0,sackOK,eol], length 0
23:54:24.978650 IP 10.0.0.50.80 > 10.0.0.1.53971: Flags [S.E], seq 996967790, ack 53967734, win 28960, options [mss 1460,sackOK,TS val 5625522 ecr 256360128,nop,wscale 6], length 0
23:54:24.978699 IP 10.0.0.1.53972 > 10.0.0.50.80: Flags [SEW], seq 226341105, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 256360128 ecr 0,sackOK,eol], length 0
23:54:24.978711 IP 10.0.0.50.80 > 10.0.0.1.53972: Flags [S.E], seq 1363851389, ack 226341106, win 28960, options [mss 1460,sackOK,TS val 5625522 ecr 256360128,nop,wscale 6], length 0

filtr hosta

Aby przechwycić wszystkie pakiety przychodzące lub wychodzące z hosta o adresie IP 10.0.2.15:

# tcpdump host 10.0.2.15
03:48:06.087509 IP 10.0.2.15.22 > 10.0.2.2.50225: Flags [P.], seq 3862934963:3862934999, ack 65355639, win 37232, length 36
03:48:06.087806 IP 10.0.2.2.50225 > 10.0.2.15.22: Flags [.], ack 36, win 65535, length 0
03:48:06.088087 IP 10.0.2.15.22 > 10.0.2.2.50225: Flags [P.], seq 36:72, ack 1, win 37232, length 36
03:48:06.088274 IP 10.0.2.2.50225 > 10.0.2.15.22: Flags [.], ack 72, win 65535, length 0
03:48:06.088440 IP 10.0.2.15.22 > 10.0.2.2.50225: Flags [P.], seq 72:108, ack 1, win 37232, length 36

Aby przechwycić pakiety określonego typu protokołu, na przykład icmp, na interfejsie eth1:

# tcpdump -i eth1 icmp
04:03:47.408545 IP vagrant-ubuntu-trusty-64 > 10.0.0.51: ICMP echo request, id 2812, seq 75, length 64
04:03:47.408999 IP 10.0.0.51 > vagrant-ubuntu-trusty-64: ICMP echo reply, id 2812, seq 75, length 64
04:03:48.408697 IP vagrant-ubuntu-trusty-64 > 10.0.0.51: ICMP echo request, id 2812, seq 76, length 64
04:03:48.409208 IP 10.0.0.51 > vagrant-ubuntu-trusty-64: ICMP echo reply, id 2812, seq 76, length 64
04:03:49.411287 IP vagrant-ubuntu-trusty-64 > 10.0.0.51: ICMP echo request, id 2812, seq 77, length 64

Łączenie wyrażeń filtrów

Te wyrażenia filtrów można łączyć z operatorami AND, OR i NOT. Umożliwi to pisanie poleceń, które mogą dokładniej izolować pakiety:

Pakiety z określonego adresu IP i przeznaczone dla określonego portu:

# tcpdump -n -i eth1 src 10.0.0.1 and dst port 80
00:18:17.155066 IP 10.0.0.1.54222 > 10.0.0.50.80: Flags [F.], seq 500773341, ack 2116767648, win 4117, options [nop,nop,TS val 257786173 ecr 5979014], length 0
00:18:17.155104 IP 10.0.0.1.54225 > 10.0.0.50.80: Flags [S], seq 904045691, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 257786173 ecr 0,sackOK,eol], length 0
00:18:17.157337 IP 10.0.0.1.54221 > 10.0.0.50.80: Flags [P.], seq 4282813257:4282813756, ack 1348066220, win 4111, options [nop,nop,TS val 257786174 ecr 5979015], length 499: HTTP: GET / HTTP/1.1
00:18:17.157366 IP 10.0.0.1.54225 > 10.0.0.50.80: Flags [.], ack 1306947508, win 4117, options [nop,nop,TS val 257786174 ecr 5983566], length 0

Aby przechwycić wszystkie pakiety z wyjątkiem ICMP, użyj operatora NOT:

# tcpdump -i eth1 not icmp

Zapisywanie nagłówków pakietów do pliku

Ponieważ dane wyjściowe tcpdump mogą dość szybko przewijać się poza ekran, możesz przechowywać nagłówki pakietów w pliku z flagą -w. Pliki do zapisania danych wyjściowych używają formatu pcap i mają rozszerzenie .pcap.

PCAP oznacza przechwytywanie pakietów. Poniższe polecenie zapisuje 10 wierszy danych wyjściowych interfejsu eth1 w pliku icmp.pcap.

# tcpdump -i eth1 -c 10 -w icmp.pcap
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
10 packets captured
10 packets received by filter
0 packets dropped by kernel

Możesz przeczytać ten plik z flagą -r:

tcpdump -r icmp.pcap
reading from file icmp.pcap, link-type EN10MB (Ethernet)
05:33:20.852732 IP vagrant-ubuntu-trusty-64 > 10.0.0.51: ICMP echo request, id 3261, seq 33, length 64
05:33:20.853245 IP 10.0.0.51 > vagrant-ubuntu-trusty-64: ICMP echo reply, id 3261, seq 33, length 64
05:33:21.852586 IP vagrant-ubuntu-trusty-64 > 10.0.0.51: ICMP echo request, id 3261, seq 34, length 64
05:33:21.853104 IP 10.0.0.51 > vagrant-ubuntu-trusty-64: ICMP echo reply, id 3261, seq 34, length 64
05:33:22.852615 IP vagrant-ubuntu-trusty-64 > 10.0.0.51: ICMP echo request, id 3261, seq 35, length 64

Wyświetlanie szczegółów pakietu

Do tej pory widzieliśmy tylko nagłówki pakietów, aby zobaczyć zawartość pakietu użyj opcji -A. Spowoduje to wydrukowanie zawartości pakietu w ASCII, co może być pomocne w rozwiązywaniu problemów z siecią. Można również użyć flagi -X do wyświetlenia danych wyjściowych w formacie szesnastkowym. Może to nie być zbyt pomocne, jeśli połączenie jest szyfrowane.

# tcpdump -c10 -i eth1 -n -A port 80
23:35:53.109306 IP 10.0.0.1.53916 > 10.0.0.50.80: Flags [P.], seq 2366590408:2366590907, ack 175457677, win 4111, options [nop,nop,TS val 255253117 ecr 5344866], length 499: HTTP: GET / HTTP/1.1
E..'[email protected]@.%.
...
..2...P..M.
uE............
.6.}.Q.bGET / HTTP/1.1
Host: 10.0.0.50
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
If-Modified-Since: Tue, 04 Mar 2014 11:46:45 GMT

Wniosek

tcpdump jest łatwy w konfiguracji, a kiedy już zrozumiesz dane wyjściowe, różne flagi i filtry, możesz go użyć do rozwiązania problemów z siecią i zabezpieczenia sieci.