Podglądanie ruchu
Po tej lekcji: kursant łapie pakiety tcpdump-em na wybranej karcie, filtruje je po adresie, porcie i protokole, zapisuje do pliku i otwiera w Wiresharku, a z tego, co widzi, odczytuje, czy winna jest sieć, zapora czy program.
Wstęp
Strona nie działa. Programista mówi, że to sieć. Sieciowiec mówi, że sieć działa i to aplikacja. Ty stoisz pośrodku jak sędzia na meczu, w którym obie drużyny twierdzą, że to był faul.
Jest narzędzie, które kończy takie kłótnie w pół minuty. Pokazuje każdą paczkę, która przechodzi przez kartę sieciową: skąd, dokąd, na który port, z jakimi flagami. Nie zgaduje i nie ma opinii. Nazywa się tcpdump. Dziś nauczysz się z niego korzystać, a na koniec zobaczysz, jak ten sam zapis wygląda w Wiresharku, w kolorach i z myszką.
Podsłuch na kablu
Wyobraź sobie pocztę, w której przy taśmie z paczkami stoi kamera. Nie otwiera paczek, nie zatrzymuje ich, tylko nagrywa: od kogo, do kogo, jaka waga, jaki znaczek. Potem możesz przewinąć nagranie i zobaczyć, czy paczka w ogóle dotarła do sortowni, czy zginęła po drodze.
tcpdump to taka kamera przy karcie sieciowej. Paczki to pakiety. Instalacja:
sudo apt install tcpdump # [Ubuntu]
sudo dnf install tcpdump # [RHEL]Najpierw sprawdzamy, na których kartach w ogóle można nagrywać:
sudo tcpdump -D1.vsrv [Up, Running, Connected]
2.vr2 [Up, Running, Connected]
3.any (Pseudo-device that captures on all interfaces) [Up, Running]
4.lo [Up, Running, Loopback]any to wszystkie karty naraz. Wygodne, kiedy nie wiesz, którędy płynie ruch.
Pierwsze nagranie
sudo tcpdump -i vcli -n -c 3 icmpW drugim terminalu ping -c1 10.0.0.10. Wynik:
listening on vcli, link-type EN10MB (Ethernet), snapshot length 262144 bytes
16:40:42.704991 IP 10.0.0.20 > 10.0.0.10: ICMP echo request, id 29057, seq 1, length 64
16:40:42.705050 IP 10.0.0.10 > 10.0.0.20: ICMP echo reply, id 29057, seq 1, length 64
2 packets capturedRozbieramy komendę:
-i vclito karta, na której nagrywamy, od „interface”.-nto „nie zamieniaj adresów na nazwy”. Bez tegotcpdumpprzy każdej paczce pyta DNS, jak się nazywa ten adres, a port 22 wypisuje jakossh. Spowalnia i zaśmieca. Admini piszą-nodruchowo, jak „dzień dobry” w windzie.-c 3to „złap trzy pakiety i skończ”, od „count”. Bez tego nagrywa doCtrl+C.icmpto filtr: interesuje mnie tylko ping i jego rodzina.
Każda linijka to jedna paczka: godzina co do mikrosekundy, IP, nadawca > odbiorca, a potem co to za paczka. Prośba o echo i odpowiedź. Klasyka.
Filtry: mów kamerze, na co patrzeć
Na prawdziwym serwerze przez kartę leci kilka tysięcy paczek na sekundę. Bez filtra to jak oglądanie monitoringu z całego dworca, szukając jednego człowieka w czerwonej czapce. Filtry są proste i składają się jak klocki:
sudo tcpdump -i any -n host 10.0.0.20 # wszystko od i do tego adresu
sudo tcpdump -i any -n port 80 # tylko port 80
sudo tcpdump -i any -n src 10.0.0.20 and dst port 443
sudo tcpdump -i any -n port 53 # zapytania DNS
sudo tcpdump -i any -n net 10.1.0.0/24 # cała sieć
sudo tcpdump -i any -n 'host 10.0.0.20 and not port 22'host to adres w dowolnym kierunku, src tylko nadawca, dst tylko odbiorca. port, net, icmp, tcp, udp. Łączysz przez and, or, not. Filtr z nawiasami albo wykrzyknikiem bierz w apostrofy, żeby Bash nie pomyślał, że to do niego.
Uścisk dłoni, czyli jak czytać TCP
Pobierzmy stronę curl-em i nagrajmy rozmowę:
sudo tcpdump -i vsrv -n port 808016:30:52.218411 IP 10.0.0.20.36658 > 10.0.0.10.8080: Flags [S], seq 333638848, win 64240, length 0
16:30:52.218879 IP 10.0.0.10.8080 > 10.0.0.20.36658: Flags [S.], seq 1804112723, ack 333638849, win 65160, length 0
16:30:52.218893 IP 10.0.0.20.36658 > 10.0.0.10.8080: Flags [.], ack 1, win 63, length 0
16:30:52.218960 IP 10.0.0.20.36658 > 10.0.0.10.8080: Flags [P.], seq 1:88, ack 1, win 63, length 87: HTTP: GET /index.html HTTP/1.1
16:30:52.219879 IP 10.0.0.10.8080 > 10.0.0.20.36658: Flags [P.], seq 1:187, ack 88, win 64, length 186: HTTP: HTTP/1.0 200 OK
16:30:52.219977 IP 10.0.0.10.8080 > 10.0.0.20.36658: Flags [F.], seq 204, ack 88, win 64, length 0Po adresie, po kropce, jest port: 10.0.0.20.36658 to adres laptopa i losowy port, z którego dzwoni. A teraz flagi, czyli najważniejsza kolumna:
[S], SYN: „dzień dobry, chcę porozmawiać”.[S.], SYN-ACK: „dzień dobry, słucham”. Kropka znaczy ACK, czyli „potwierdzam”.[.], ACK: „to zaczynamy”.
To jest trójstopniowe uzgodnienie, three-way handshake. Dopiero po nim lecą dane: [P.] to paczka z treścią, tu widać nawet GET /index.html i 200 OK. Na koniec [F.], FIN: „do widzenia”. I jeszcze jedna flaga, którą musisz znać:
16:31:16.417014 IP 127.0.0.1.48238 > 127.0.0.1.9999: Flags [S], seq 4270571044, win 65495, length 0
16:31:16.417022 IP 127.0.0.1.9999 > 127.0.0.1.48238: Flags [R.], seq 0, ack 4270571045, win 0, length 0[R], RST, reset: „nikt tu nie odbiera, proszę się rozłączyć”. To jest właśnie Connection refused z poprzednich lekcji. Na porcie nikt nie siedzi.
Teraz zagadka detektywistyczna. Pukamy nc -zv w port, który blokuje firewalld:
16:31:02.710095 In IP 10.0.0.20.48842 > 10.0.0.10.9999: Flags [S], seq 1258206062, win 64240, length 0
16:31:02.710141 Out IP 10.0.0.10 > 10.0.0.20: ICMP host 10.0.0.10 unreachable - admin prohibited filter, length 68Nie ma RST. Jest ICMP „admin prohibited filter”, czyli „administrator zabronił”. To zapora mówi „nie” wprost. A jeśli widzisz same [S], [S], [S] bez żadnej odpowiedzi, paczka ginie po drodze: zapora z drop, brak trasy powrotnej albo serwer w ogóle nie dostaje ruchu. Trzy różne awarie, trzy różne obrazki. Kłótnia programisty z sieciowcem rozstrzygnięta.
Podgląd treści
Do zajrzenia w środek paczki służy -A, od ASCII:
sudo tcpdump -i any -n -A port 8080GET / HTTP/1.1
Host: 10.0.0.10:8080
User-Agent: curl/8.5.0
Accept: */*
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.13.18Widać całe zapytanie i nagłówki odpowiedzi. Dlatego HTTP bez S to pocztówka, a nie list w kopercie: każdy po drodze może przeczytać. Przy HTTPS i SSH zobaczysz tylko szum. I o to chodzi.
Nagrywanie do pliku i Wireshark
Na żywo wszystko miga za szybko. Lepiej nagrać do pliku i obejrzeć na spokojnie:
sudo tcpdump -i any -n -w zrzut.pcap 'host 10.0.0.20 and not port 22'-w to „zapisz” (write). Na ekranie nic nie widać, tylko licznik po Ctrl+C:
18 packets captured
18 packets received by filter
0 packets dropped by kernelOdtwarzanie przez -r, od „read”. Na odtwarzanym nagraniu też działają filtry:
tcpdump -n -r zrzut.pcap icmpreading from file zrzut.pcap, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144
16:31:02.714245 enp1s0 In IP 10.0.0.20 > 10.0.0.10: ICMP echo request, id 19225, seq 1, length 64
16:31:02.714280 enp1s0 Out IP 10.0.0.10 > 10.0.0.20: ICMP echo reply, id 19225, seq 1, length 64Długie nagrania na produkcji robi się w kółko, żeby nie zapchać dysku:
sudo tcpdump -i vr2 -n -w ruch.pcap -C 1 -W 3
ls -l-rw-r--r-- 1 root root 1026909 Nov 3 16:41 ruch.pcap0
-rw-r--r-- 1 root root 270 Nov 3 16:41 ruch.pcap1
-rw-r--r-- 1 root root 1007826 Nov 3 16:41 ruch.pcap2-C 1 to plik co milion bajtów, -W 3 to najwyżej trzy pliki, potem najstarszy jest nadpisywany. Kamera z kasetą, która nagrywa w pętli.
A teraz Wireshark. To ten sam podsłuch, tylko z okienkami: lista paczek w kolorach, każda rozłożona na warstwy jak cebula, a do tego jedno kliknięcie „pokaż całą rozmowę”. Na serwerze zwykle nie ma pulpitu, więc schemat jest taki: nagrywasz tcpdump -w na serwerze, kopiujesz plik scp-em (o nim w następnej lekcji) i otwierasz Wiresharkiem na swoim komputerze. Instalacja: pakiet wireshark na Linuksie, instalator ze strony wireshark.org na Windowsie i Macu. [macOS]
Uwaga: Wireshark ma dwa rodzaje filtrów. Filtr nagrywania ma składnię tcpdump-a: port 80. Filtr wyświetlania, ten w pasku na górze, ma własną: tcp.port == 80, ip.addr == 10.0.0.20, http.request, dns. Ten sam filtr wyświetlania zadziała w tshark, czyli Wiresharku w terminalu:
tshark -r zrzut.pcap -Y 'tcp.port == 9999 || icmp.type == 3' 13 0.008447 10.0.0.20 → 10.0.0.10 TCP 80 48842 → 9999 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM TSval=859978951 TSecr=0 WS=1024
14 0.008493 10.0.0.10 → 10.0.0.20 ICMP 108 Destination unreachable (Communication administratively filtered)Detektyw na routerze
Teraz zobaczysz coś, co zwykle trzeba wierzyć na słowo. Router z poprzedniej lekcji, przekierowanie 8080 na SSH drugiej maszyny. Nagrywamy na wszystkich kartach naraz tylko paczki z flagą SYN:
sudo tcpdump -i any -n 'tcp[tcpflags] & tcp-syn != 0'16:40:31.228822 vsrv In IP 10.0.0.20.39412 > 10.0.0.10.8080: Flags [S], seq 1591475484, length 0
16:40:31.228863 vr2 Out IP 10.1.0.1.39412 > 10.1.0.2.22: Flags [S], seq 1591475484, length 0
16:40:31.228879 vr2 In IP 10.1.0.2.22 > 10.1.0.1.39412: Flags [S.], seq 1965426657, ack 1591475485, length 0
16:40:31.228884 vsrv Out IP 10.0.0.10.8080 > 10.0.0.20.39412: Flags [S.], seq 1965426657, ack 1591475485, length 0Czytamy jak komiks. Pierwsza linijka: laptop puka do routera na 8080. Druga, 41 mikrosekund później: ta sama paczka, ten sam numer seq, wychodzi drugą kartą, ale z innym nadawcą (10.1.0.1, maskarada) i do innego odbiorcy (10.1.0.2.22, przekierowanie). Trzecia i czwarta: odpowiedź wraca i jest tłumaczona z powrotem. Cały NAT na czterech linijkach. Żaden podręcznik tego tak nie pokaże.
Jak to działa pod spodem
tcpdump korzysta z biblioteki libpcap. Ta prosi jądro o specjalne gniazdo, które dostaje kopię każdej paczki z danej karty. Filtr, który wpisujesz, jest kompilowany do małego programu BPF, Berkeley Packet Filter, i wykonywany w jądrze. Do programu trafiają tylko pasujące paczki, więc nawet na zapchanej karcie filtr port 53 nie zabije procesora.
Ważne: kamera stoi przy karcie, a zapora stoi dalej. Paczki przychodzące tcpdump widzi, zanim zapora zdecyduje, czy je wpuścić. Dlatego widzisz [S] nawet wtedy, gdy ufw za chwilę je wyrzuci. Jeśli tcpdump na serwerze nic nie widzi, paczka nie dotarła do serwera i szukasz winnego po drodze.
Ściąga flag
| Komenda | Flaga | Co robi |
|---|---|---|
tcpdump | -D | lista kart, na których można nagrywać |
tcpdump | -i KARTA / -i any | nagrywa na jednej / na wszystkich kartach |
tcpdump | -n | nie zamienia adresów i portów na nazwy |
tcpdump | -c N | kończy po N pakietach |
tcpdump | -A / -X | pokazuje treść jako tekst / szesnastkowo i tekst |
tcpdump | -v / -vv | więcej szczegółów |
tcpdump | -w plik.pcap | zapisuje do pliku |
tcpdump | -r plik.pcap | czyta z pliku |
tcpdump | -C N -W M | pliki po N milionów bajtów, najwyżej M w kółko |
| filtr | host, src, dst, net | adres w obie strony / nadawca / odbiorca / sieć |
| filtr | port, tcp, udp, icmp | port / protokół |
| filtr | and, or, not | łączenie warunków |
tshark | -r plik -Y 'filtr' | czyta plik z filtrem wyświetlania Wiresharka |
⚠ Typowy błąd
Nagrywanie przez SSH bez filtra.
Łączysz się z serwerem przez SSH, wpisujesz sudo tcpdump -i any i ekran eksploduje. Bo tcpdump wypisuje linijkę, linijka leci do Ciebie przez SSH, czyli jako nowa paczka, którą tcpdump łapie i wypisuje, co tworzy kolejną paczkę SSH… Kamera nagrywa własny monitor. Pies goni własny ogon, tylko szybciej.
Naprawa: zawsze wyklucz własną sesję.
sudo tcpdump -i any -n not port 22Dwa pozostałe błędy, które zobaczysz w pierwszym tygodniu:
tcpdump -i vcli -c 1tcpdump: vcli: You don't have permission to perform this capture on that device
(socket: Operation not permitted)Podsłuch wymaga roota. Dopisz sudo.
sudo tcpdump -i eth0 -c 1tcpdump: eth0: No such device exists
(No such device exists)Poradnik z internetu mówi eth0, a Twoja karta nazywa się enp1s0 albo ens18. Najpierw ip -br a albo tcpdump -D, potem nagrywanie.
✎ Zadanie
Na maszynie wirtualnej uruchom sudo tcpdump -i any -n -w zadanie.pcap 'not port 22'. W drugim terminalu zrób: ping -c 2 8.8.8.8, dig example.com i curl -I http://example.com. Zatrzymaj nagrywanie. Potem odczytaj plik trzy razy z różnymi filtrami: tylko ICMP, tylko port 53 i tylko port 80. W ostatnim znajdź trójstopniowe uzgodnienie i zapisz, ile milisekund minęło od [S] do [S.]. To jest czas podróży pakietu tam i z powrotem.
Pokaż rozwiązanie
Zadanie wymagało internetu. W moim laboratorium „internetem” jest maszyna z zaplecza z małym serwerem DNS i WWW, ale komendy są dokładnie te same.
sudo tcpdump -i any -n -w zadanie.pcap 'not port 22'
# w drugim terminalu:
ping -c 2 10.1.0.2
dig @10.1.0.2 +short example.com
curl -I http://10.1.0.2/Odczyt trzema filtrami:
tcpdump -n -r zadanie.pcap icmp
tcpdump -n -r zadanie.pcap port 53
tcpdump -n -r zadanie.pcap port 8016:44:31.810103 enp1s0 Out IP 10.0.0.20 > 10.1.0.2: ICMP echo request, id 31939, seq 1, length 64
16:44:31.810336 enp1s0 In IP 10.1.0.2 > 10.0.0.20: ICMP echo reply, id 31939, seq 1, length 64
16:44:32.826869 enp1s0 Out IP 10.0.0.20.54020 > 10.1.0.2.53: 55148+ [1au] A? example.com. (52)
16:44:32.827410 enp1s0 In IP 10.1.0.2.53 > 10.0.0.20.54020: 55148* 1/0/1 A 10.1.0.2 (56)
16:44:32.848529 enp1s0 Out IP 10.0.0.20.33462 > 10.1.0.2.80: Flags [S], seq 1979540402, length 0
16:44:32.848603 enp1s0 In IP 10.1.0.2.80 > 10.0.0.20.33462: Flags [S.], seq 3184474449, ack 1979540403, length 0DNS to jedno pytanie A? example.com. i jedna odpowiedź A 10.1.0.2. Czas od [S] do [S.] liczysz, odejmując godziny, albo każesz to zrobić tcpdump-owi przełącznikiem -ttt, który pokazuje odstęp od poprzedniej paczki:
tcpdump -n -ttt -r zadanie.pcap 'port 80 and tcp[tcpflags] & tcp-syn != 0' 00:00:00.000000 enp1s0 Out IP 10.0.0.20.33462 > 10.1.0.2.80: Flags [S] ...
00:00:00.000074 enp1s0 In IP 10.1.0.2.80 > 10.0.0.20.33462: Flags [S.] ...74 mikrosekundy, bo maszyny stoją w jednym komputerze. Do prawdziwego example.com wyjdzie Ci kilkanaście albo kilkadziesiąt milisekund, czyli tyle, ile pakiet leci do serwera i z powrotem.
Co dalej
Po sieci już umiemy chodzić, oglądać ją i rozdzielać ruch. W następnej lekcji wchodzimy do środka SSH: klucze ed25519, plik ~/.ssh/config, który oszczędza tysiąc literek dziennie, konfiguracja serwera bez ryzyka zatrzaśnięcia się i tunele, którymi przemycisz port przez dwie zapory.