23 przykłady jak przechwytywać ruch za pomocą tcpdump

Jeśli miałbym wymienić najprzydatniejsze narzędzia, których używam przy rozwiązywaniu problemów sieciowych, to tcpdump byłby na pewno na górze tej listy. Praktycznie zawsze, kiedy zastanawiam się, czy jakiś ruch jest generowany, jak wygląda nagłówek TCP/IP i czy jest komunikacja powrotna, używam tcpdump’a. Niniejszy poradnik jest zbiorem przykładów jak używać tcpdump’a do przechwytywania, analizy i zapisywania ruchu sieciowego. Znajdziecie też tutaj kilka ciekawych trików jak lepiej i wygodniej przechwytywać ruch. Zaczynajmy!

Filtrowanie po interfejsach

1. Listowanie interfejsów

Naprawdę rzadko się zdarza, że jest nam obojętne, na którym interfejsie będziemy przechwytywać pakiety. Nawet jeśli urządzenie, na którym uruchamiamy tcpdump ma tylko jedną kartę sieciową to z pewnością ma również jakieś wirtualne karty (loopback, VPN itp.), na których ruch może się pojawiać. Dlatego pierwszą rzeczą, którą warto sprawdzić to wylistowanie wszystkich kart sieciowych, na których będzie można przechwytywać ruch. Zrobimy to za pomocą opcji –list-interface albo krócej przełącznika -D

Przykład: tcpdump –list-interface

$ tcpdump -D
1.eth0 [Up, Running]
2.eth1 [Up, Running]
3.eth2 [Up, Running]
4.any (Pseudo-device that captures on all interfaces) [Up, Running]
5.lo [Up, Running, Loopback]

2. Przechwytywanie ruchu na wszystkich interfejsach

Ten przykład nasłuchiwania komunikacji sieciowej wykonywany jest bardzo rzadko. Niemniej, podaję go tutaj, bo jeśli urządzenie ma naprawdę dużo interfejsów, czasem warto sprawdzić, czy w ogóle jakiś ruch się pojawia, nie wnikając, na którym interfejsie on występuje. Do nasłuchiwania na dowolnym interfejsie służy przełącznik -i any

Przykład: tcpdump -i any

$ tcpdump -i any
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
12:25:56.881538 IP VM.ssh > 192.168.1.13.25521: Flags [P.], seq 3995326478:3995326542, ack 3733810658, win 518, length 64
12:25:56.881964 IP VM.ssh > 192.168.1.13.25521: Flags [P.], seq 64:192, ack 1, win 518, length 128
12:25:56.882024 IP VM.ssh > 192.168.1.13.25521: Flags [P.], seq 192:256, ack 1, win 518, length 64
12:25:56.882055 IP VM.ssh > 192.168.1.13.25521: Flags [P.], seq 256:400, ack 1, win 518, length 144
12:25:56.882329 IP 192.168.1.13.25521 > VM.ssh: Flags [.], ack 192, win 8211, length 0

3. Przechwytywanie całego ruchu na pojedynczym interfejsie

Zazwyczaj nie wystarcza nam wiedza o tym, że ruch w ogóle się pojawia, ale chcemy wiedzieć, na którym interfejsie? Czy na pewno na tym, na którym się go spodziewamy, a może z powodu jakiegoś błędu konfiguracyjnego widzimy ruch, ale na niewłaściwym interfejsie? Z pomocą przychodzi nam przełącznik -i nazwa_interfejsu. Oczywiście jako nazwa_interfejsu podstawiamy nazwę, którą poznaliśmy w pierwszym przykładzie, czyli –list-interface

Przykład: tcpdump -i eth0

$ tcpdump -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:35:04.826366 IP 192.168.1.10.43848 > 77.79.248.195.https: Flags [S], seq 2174450655, win 64240, options [mss 1460,sackOK,TS val 2510123793 ecr 0,nop,wscale 7], length 0
12:35:04.834123 IP 77.79.248.195.https > 192.168.1.10.43848: Flags [S.], seq 2462832399, ack 2174450656, win 28960, options [mss 1452,sackOK,TS val 2696148927 ecr 2510123793,nop,wscale 7], length 0
12:35:04.834146 IP 192.168.1.10.43848 > 77.79.248.195.https: Flags [.], ack 1, win 502, options [nop,nop,TS val 2510123801 ecr 2696148927], length 0
12:35:04.835931 IP 192.168.1.10.43848 > 77.79.248.195.https: Flags [P.], seq 1:518, ack 1, win 502, options [nop,nop,TS val 2510123803 ecr 2696148927], length 517
12:35:04.843630 IP 77.79.248.195.https > 192.168.1.10.43848: Flags [.], ack 518, win 235, options [nop,nop,TS val 2696148936 ecr 2510123803], length 0

Filtrowanie po adresach

4. Filtrowanie na podstawie adresu IP

Filtrowanie na podstawie adresu IP jest jednym z najczęściej używanych filtrów. Zazwyczaj wiemy komunikacja, z jakim adresem nas interesuje i potrafimy zawęzić ruch, który będzie przechwycony do tej właśnie komunikacji. Filtrowanie na podstawie adresu IP odbywa się z użyciem argumentu host i podaniu adresu IP. Ważne jest to, że przechwycone będą pakiety, w których wskazany adres IP będzie adresem źródłowym albo docelowym, czyli przechwycimy zarówno zapytania, jak i odpowiedzi.

Przykład: tcpdump -i eth0 host 192.168.1.10

$ tcpdump -i eth0 host 192.168.1.10
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:47:57.131657 IP 192.168.1.10.44786 > 82.221.107.34.bc.googleusercontent.com.http: Flags [S], seq 2526868978, win 64240, options [mss 1460,sackOK,TS val 2135062734 ecr 0,nop,wscale 7], length 0
12:47:57.141689 IP 82.221.107.34.bc.googleusercontent.com.http > 192.168.1.10.44786: Flags [S.], seq 2607142984, ack 2526868979, win 65535, options [mss 1430,sackOK,TS val 3260628142 ecr 2135062734,nop,wscale 8], length 0
12:47:57.141738 IP 192.168.1.10.44786 > 82.221.107.34.bc.googleusercontent.com.http: Flags [.], ack 1, win 502, options [nop,nop,TS val 2135062744 ecr 3260628142], length 0
12:47:57.141946 IP 192.168.1.10.44786 > 82.221.107.34.bc.googleusercontent.com.http: Flags [P.], seq 1:297, ack 1, win 502, options [nop,nop,TS val 2135062745 ecr 3260628142], length 296: HTTP: GET /success.txt HTTP/1.1
12:47:57.151423 IP 82.221.107.34.bc.googleusercontent.com.http > 192.168.1.10.44786: Flags [.], ack 297, win 261, options [nop,nop,TS val 3260628152 ecr 2135062745], length 0

5. Filtrowanie ruchu na podstawie podsieci

Czasem nasz filtr musimy zarzucić nieco szerzej, np. na całą podsieć. W takim przypadku używamy argumentu net i podajemy podsieć w notacji CIDR, czyli /16, /24, /28 itp.

Przykład: tcpdump -i eth0 net 192.168.1.0/24

$ tcpdump -i eth0 net 192.168.1.0/24
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:51:45.602095 ARP, Request who-has 192.168.1.1 tell 192.168.1.10, length 28
12:51:45.603364 ARP, Reply 192.168.1.1 is-at 32:02:71:29:01:ab (oui Unknown), length 46
12:51:50.721733 IP 192.168.1.10.44788 > 82.221.107.34.bc.googleusercontent.com.http: Flags [.], ack 1115423913, win 501, options [nop,nop,TS val 2135296324 ecr 3260851493], length 0
12:51:50.721782 IP 192.168.1.10.44786 > 82.221.107.34.bc.googleusercontent.com.http: Flags [.], ack 2607144745, win 501, options [nop,nop,TS val 2135296324 ecr 3260851493], length 0
12:51:50.739880 IP 82.221.107.34.bc.googleusercontent.com.http > 192.168.1.10.44786: Flags [.], ack 1, win 290, options [nop,nop,TS val 3260861733 ecr 2135204337], length 0

6. Filtrowanie ruchu na podstawie kierunku

Wykorzystując argument src albo dst z argumentami host i net możliwe jest filtrowanie ruchu w określonym kierunku. Tak na przykład src host pozwoli nam odfiltorować wszystkie pakiety wysłane przez komputer, natomiast dst host pokaże wszystkie pakiety kierowane do niego. Pamiętaj, żeby używać tych argumentów bardzo uważnie. Widoczność tylko jednego kierunku ruchu może dawać wrażenie, że komunikacja jest poprawna, podczas gdy w rzeczywistości jedna ze stron nie odpowiada albo odpowiada niepoprawnie.

Przykład: tcpdump -i eth0 src host 192.168.1.10

$ tcpdump -i eth0 src host 192.168.1.10
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:58:40.238392 IP 192.168.1.10 > one.one.one.one: ICMP echo request, id 1, seq 9, length 64
12:58:40.238952 IP 192.168.1.10.46812 > dns.google.domain: 3666+ [1au] PTR? 1.1.1.1.in-addr.arpa. (49)
12:58:40.251694 IP 192.168.1.10.47501 > dns.google.domain: 12473+ [1au] PTR? 18.1.168.192.in-addr.arpa. (54)
12:58:40.262284 IP 192.168.1.10.60534 > dns.google.domain: 46278+ [1au] PTR? 8.8.8.8.in-addr.arpa. (49)
12:58:40.869835 ARP, Reply 192.168.1.10 is-at 08:00:27:ff:62:f4 (oui Unknown), length 28

Filtrowanie po portach i protokołach

7. Filtrowanie po protokołach

Kolejna przydatna funkcja to filtrowanie ruchu po protokole. Jej użycie jest niezwykle proste, bo nie wymaga podawania żadnego parametru, wystarczy podać nazwę protokołu, który chcemy odfiltrować np.: tcp, udp, icmp, arp itp.

Przykład: tcpdump -i eth0 icmp

$ tcpdump -i eth0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:01:51.966501 IP VM > dns.google: ICMP echo request, id 4, seq 1, length 64
13:01:51.979529 IP VM > dns.google: ICMP VM udp port 52459 unreachable, length 109
13:01:51.979498 IP dns.google > VM: ICMP echo reply, id 4, seq 1, length 64
13:01:52.968262 IP VM > dns.google: ICMP echo request, id 4, seq 2, length 64
13:01:52.979166 IP dns.google > VM: ICMP echo reply, id 4, seq 2, length 64

8. Filtrowanie po portach

W przypadku protokołów TCP i UDP filtrować możemy dodatkowo po portach używanych w komunikacji. W tym przypadku do argumentu port dodajemy wartość liczbową lub nazwę portu. Tak więc w przypadku komunikacji DNS możemy użyć zarówno parametru port 53, jak i port dns.

Przykład: tcpdump -i eth0 port 53

$ tcpdump -i eth0 port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:32:01.041515 IP 192.168.1.10.49267 > dns.google.domain: 61289+ [1au] A? detectportal.firefox.com. (53)
13:32:01.042018 IP 192.168.1.10.47592 > dns.google.domain: 2457+ [1au] PTR? 8.8.8.8.in-addr.arpa. (49)
13:32:01.042062 IP 192.168.1.10.49267 > dns.google.domain: 24695+ [1au] AAAA? detectportal.firefox.com. (53)
13:32:01.053901 IP dns.google.domain > 192.168.1.10.49267: 61289 3/0/1 CNAME detectportal.prod.mozaws.net., CNAME prod.detectportal.prod.cloudops.mozgcp.net., A 34.107.221.82 (164)
13:32:01.054247 IP dns.google.domain > 192.168.1.10.49267: 24695 3/0/1 CNAME detectportal.prod.mozaws.net., CNAME prod.detectportal.prod.cloudops.mozgcp.net., AAAA 2600:1901:0:38d7:: (176)
13:32:01.059039 IP dns.google.domain > 192.168.1.10.47592: 2457 1/0/1 PTR dns.google. (73)
13:32:01.059177 IP 192.168.1.10.53424 > dns.google.domain: 23488+ [1au] PTR? 18.1.168.192.in-addr.arpa. (54)
13:32:01.073726 IP dns.google.domain > 192.168.1.10.53424: 23488 NXDomain 0/0/1 (54)
13:32:01.164788 IP 192.168.1.10.57759 > dns.google.domain: 61250+ [1au] A? example.org. (40)
13:32:01.174329 IP dns.google.domain > 192.168.1.10.57759: 61250$ 1/0/1 A 93.184.216.34 (56)

Ruch możemy filtrować również na podstawie jego kierunku, czyli na podstawie portów źródłowych i docelowych. Zasada jest ta sama jak w przypadku filtrowania kierunków w IP, czyli przed port dodajemy src lub dst w zależności, jaki kierunek chcemy zobaczyć. Pamiętajcie jednak, że filtrując w ten sposób, nie widzimy obydwu kierunków ruchu, więc może nam coś umknąć.

Przykład: tcpdump -i eth0 dst port 443

$ tcpdump -i eth0 dst port 443
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:39:56.267450 IP 192.168.1.10.34036 > 133.247.244.35.bc.googleusercontent.com.https: Flags [P.], seq 1735834685:1735834832, ack 2941032209, win 501, options [nop,nop,TS val 150526122 ecr 3252696117], length 147
13:39:56.268414 IP 192.168.1.10.34036 > 133.247.244.35.bc.googleusercontent.com.https: Flags [P.], seq 147:496, ack 1, win 501, options [nop,nop,TS val 150526123 ecr 3252696117], length 349
13:39:56.288281 IP 192.168.1.10.49754 > waw02s16-in-f14.1e100.net.https: Flags [S], seq 946558600, win 64240, options [mss 1460,sackOK,TS val 932126463 ecr 0,nop,wscale 7], length 0
13:39:56.309362 IP 192.168.1.10.49754 > waw02s16-in-f14.1e100.net.https: Flags [.], ack 4158032308, win 502, options [nop,nop,TS val 932126484 ecr 1112837710], length 0
13:39:56.311276 IP 192.168.1.10.49754 > waw02s16-in-f14.1e100.net.https: Flags [P.], seq 0:517, ack 1, win 502, options [nop,nop,TS val 932126486 ecr 1112837710], length 517

Łączenie filtrów

9. Operatory łączące filtry

Rzadko jest tak, że do przechwycenia ruchu wystarczy nam jeden filtr. Dlatego tcpdump pozwala na stosowanie operatorów w celu budowania bardziej skomplikowanych filtrów. Operatory, jakie możemy stosować to and, or oraz not.

W przypadku operatora and oba filtry muszą być spełnione jednocześnie. Jest to więc idealny operator do przechwytywania ruchu pomiędzy dwoma adresami IP.

Przykład: tcpdump -i eth0 host 192.168.1.1 and host 192.168.1.10

tcpdump -i eth0 host 192.168.1.10 and host 192.168.1.1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:31:31.750932 IP 192.168.1.10.58834 > 192.168.1.1.http: Flags [S], seq 1622692865, win 64240, options [mss 1460,sackOK,TS val 45978457 ecr 0,nop,wscale 7], length 0
14:31:31.758941 IP 192.168.1.1.http > 192.168.1.10.58834: Flags [R.], seq 0, ack 1622692866, win 0, length 0
14:31:31.762097 IP 192.168.1.10.38580 > 192.168.1.1.https: Flags [S], seq 2439134577, win 64240, options [mss 1460,sackOK,TS val 45978468 ecr 0,nop,wscale 7], length 0
14:31:31.765155 IP 192.168.1.1.https > 192.168.1.10.38580: Flags [R.], seq 0, ack 2439134578, win 0, length 0

Albo do filtrowania ruchu na podstawie adresu IP i usługi

Przykład: tcpdump -i eth0 host 192.168.1.10 and port 443

 tcpdump -i eth0 host 192.168.1.10 and port 443
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:34:26.840087 IP 192.168.1.10.47144 > ec2-44-236-191-53.us-west-2.compute.amazonaws.com.https: Flags [S], seq 2825391353, win 64240, options [mss 1460,sackOK,TS val 3761390349 ecr 0,nop,wscale 7], length 0
14:34:27.033832 IP ec2-44-236-191-53.us-west-2.compute.amazonaws.com.https > 192.168.1.10.47144: Flags [S.], seq 3620984649, ack 2825391354, win 26847, options [mss 1452,sackOK,TS val 4129039128 ecr 3761390349,nop,wscale 8], length 0
14:34:27.033857 IP 192.168.1.10.47144 > ec2-44-236-191-53.us-west-2.compute.amazonaws.com.https: Flags [.], ack 1, win 502, options [nop,nop,TS val 3761390543 ecr 4129039128], length 0
14:34:27.034249 IP 192.168.1.10.47144 > ec2-44-236-191-53.us-west-2.compute.amazonaws.com.https: Flags [P.], seq 1:214, ack 1, win 502, options [nop,nop,TS val 3761390543 ecr 4129039128], length 213
14:34:27.228104 IP ec2-44-236-191-53.us-west-2.compute.amazonaws.com.https > 192.168.1.10.47144: Flags [.], ack 214, win 117, options [nop,nop,TS val 4129039375 ecr 3761390543], length 0

W przypadku operatora or spełniony musi być pierwszy lub drugi filtr, lub oba jednocześnie. Or sprawdzi się bardzo dobrze, jeśli chcemy zobaczyć ruch, który może działać na różnych portach. Np. komunikacja www może odbywać się na porcie http (80) albo https (443) a filtr, który będzie wyświetlał ten ruch, może wyglądać następująco:

Przykład: tcpdump -i eth0 port 80 or port 443

$ tcpdump -i eth0 port 80 or port 443
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:52:00.942279 IP 192.168.1.10.59896 > one.one.one.one.http: Flags [S], seq 1312716693, win 64240, options [mss 1460,sackOK,TS val 3632147508 ecr 0,nop,wscale 7], length 0
14:52:00.952418 IP one.one.one.one.http > 192.168.1.10.59896: Flags [S.], seq 3886611099, ack 1312716694, win 65535, options [mss 1452,nop,nop,sackOK,nop,wscale 10], length 0
14:52:00.952441 IP 192.168.1.10.59896 > one.one.one.one.http: Flags [.], ack 1, win 502, length 0
14:52:00.953259 IP 192.168.1.10.59896 > one.one.one.one.http: Flags [P.], seq 1:399, ack 1, win 502, length 398: HTTP: GET / HTTP/1.1
14:52:00.962485 IP one.one.one.one.http > 192.168.1.10.59896: Flags [.], ack 399, win 66, length 0
14:52:00.963781 IP one.one.one.one.http > 192.168.1.10.59896: Flags [P.], seq 1:459, ack 399, win 66, length 458: HTTP: HTTP/1.1 301 Moved Permanently
14:52:00.967106 IP 192.168.1.10.58322 > one.one.one.one.https: Flags [S], seq 2108419057, win 64240, options [mss 1460,sackOK,TS val 3632147533 ecr 0,nop,wscale 7], length 0
14:52:00.967460 IP one.one.one.one.http > 192.168.1.10.59896: Flags [F.], seq 459, ack 400, win 66, length 0
14:52:00.967473 IP 192.168.1.10.59896 > one.one.one.one.http: Flags [R], seq 1312717093, win 0, length 0
14:52:00.980299 IP one.one.one.one.https > 192.168.1.10.58322: Flags [S.], seq 3409669950, ack 2108419058, win 65535, options [mss 1452,nop,nop,sackOK,nop,wscale 10], length 0

Operator not może występować sam lub w połączeniu z and tworząc and not. Przykładem jego zastosowania może być filtrowanie ruchu z całej podsieci z wyłączeniem pojedynczego hosta.

Przykład: tcpdump -i eth0 net 192.168.1.0/24 and not host 192.168.1.20

10. Łączenie wielu operatorów w jednym filtrze

Często jest tak, że musimy połączyć wiele filtrów jednocześnie. Jest to o tyle skomplikowane, że tak jak w matematyce kolejność działania ma znaczenie, tak łącząc filtry w tcpdump w różny sposób, otrzymamy różne wyniki.

Zobacz na proste działania matematyczne:

2×2+2=6

2x(2+2)=8

Chociaż wyglądają bardzo podobnie, to wynik tych działań jest zupełnie różny. Tak samo stosując różną kolejność operatorów w składni, otrzymamy zupełnie różne wyniki. Zobacz na taką składnię:

tcpdump -i eth0 port 53 and udp or tcp

Na pierwszy rzut oka może się wydawać, że chodzi o filtr, który ma pokazać ruch DNS odbywający się po protokole udp lub tcp. W rzeczywistości zobaczymy jednak ruch na porcie 53/UDP oraz całą komunikację TCP niezależnie od tego, na jakim będzie ona porcie.

Żeby zobaczyć ruch na porcie 53 dla protokołów TCP i UDP, powinniśmy zastosować następującą składnię:

Przykład: tcpdump -i eth0 port 53 and '(udp or tcp)’

$ tcpdump -i eth0 'port 53 and (udp or tcp)'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
15:14:43.697037 IP 192.168.1.10.42789 > dns.google.domain: Flags [S], seq 1010530222, win 64240, options [mss 1460,sackOK,TS val 2207461563 ecr 0,nop,wscale 7], length 0
15:14:43.697523 IP 192.168.1.10.32960 > dns.google.domain: 19113+ [1au] PTR? 8.8.8.8.in-addr.arpa. (49)
15:14:43.707203 IP dns.google.domain > 192.168.1.10.42789: Flags [S.], seq 1803634384, ack 1010530223, win 65535, options [mss 1430,sackOK,TS val 4217305978 ecr 2207461563,nop,wscale 8], length 0
15:14:43.707226 IP 192.168.1.10.42789 > dns.google.domain: Flags [.], ack 1, win 502, options [nop,nop,TS val 2207461573 ecr 4217305978], length 0
15:14:43.707319 IP 192.168.1.10.42789 > dns.google.domain: Flags [P.], seq 1:54, ack 1, win 502, options [nop,nop,TS val 2207461573 ecr 4217305978], length 53 44087+ [1au] A? google.com. (51)
15:14:43.711681 IP dns.google.domain > 192.168.1.10.32960: 19113 1/0/1 PTR dns.google. (73)
15:14:43.711819 IP 192.168.1.10.41002 > dns.google.domain: 14037+ [1au] PTR? 18.1.168.192.in-addr.arpa. (54)
15:14:43.717158 IP dns.google.domain > 192.168.1.10.42789: Flags [.], ack 54, win 256, options [nop,nop,TS val 4217305988 ecr 2207461573], length 0
15:14:43.718273 IP dns.google.domain > 192.168.1.10.42789: Flags [P.], seq 1:58, ack 54, win 256, options [nop,nop,TS val 4217305989 ecr 2207461573], length 57 44087 1/0/1 A 216.58.208.206 (55)
15:14:43.718286 IP 192.168.1.10.42789 > dns.google.domain: Flags [.], ack 58, win 502, options [nop,nop,TS val 2207461584 ecr 4217305989], length 0

W składni tcpdump (i w ogóle poleceń linuksowych) znak ’ neutralizuje znaki specjalne. Oznacza to, że znaki ( oraz ) są stosowane dosłownie, czyli jako nawiasy grupujące. Dzięki umiejętnemu stosowaniu nawiasów w składni możliwe jest dowolne, nawet bardzo skomplikowane łączenie ze sobą filtrów.

Limitowanie zbieranych danych

11. Przechwytywanie tylko n pakietów

Nie zawsze potrzebujemy przechwycić cały ruch, czasem wystarczy nam kilka pakietów, żeby rozpocząć analizę problemów. Do ograniczenia liczby przechwytywanych danych służy argument -c, po którym podajemy, ile pakietów ma zostać przechwyconych. Ważne jest to, że po przechwyceniu zadanej liczby pakietów program zakończy swoje działanie.

Przykład: tcpdump -i eth0 -c 5

$ tcpdump -i eth0 -c 5
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:11:01.309131 IP 192.168.1.10.49906 > waw02s16-in-f14.1e100.net.https: Flags [P.], seq 3866539527:3866539566, ack 3183383926, win 501, options [nop,nop,TS val 933991484 ecr 3888303802], length 39
14:11:01.309762 IP 192.168.1.10.46375 > dns.google.domain: 62860+ [1au] PTR? 78.215.58.216.in-addr.arpa. (55)
14:11:01.320154 IP dns.google.domain > 192.168.1.10.46375: 62860 1/0/1 PTR waw02s16-in-f14.1e100.net. (94)
14:11:01.320303 IP 192.168.1.10.39644 > dns.google.domain: 21543+ [1au] PTR? 18.1.168.192.in-addr.arpa. (54)
14:11:01.329026 IP waw02s16-in-f14.1e100.net.https > 192.168.1.10.49906: Flags [P.], seq 1:40, ack 39, win 271, options [nop,nop,TS val 3888362790 ecr 933991484], length 39
5 packets captured
5 packets received by filter
0 packets dropped by kernel

12. Przechwytywanie pakietów o określonej wielkości

Tcpdump pozwala na filtrowanie danych po wielkości danych w pakiecie. Może się to przydać do znajdywania pakietów zbyt dużych w stosunku do standardu np. zbyt dużych zapytań DNS albo niewłaściwej komunikacji ICMP.

Przykład: tcpdump -i eth0 greater 1024

$ tcpdump -i eth0 greater 1024
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:01:02.237806 IP muc03s08-in-f46.1e100.net.https > 192.168.1.10.36696: Flags [.], seq 3567877317:3567878735, ack 2348136195, win 261, options [nop,nop,TS val 551014923 ecr 4169524240], length 1418
14:01:02.238415 IP muc03s08-in-f46.1e100.net.https > 192.168.1.10.36696: Flags [P.], seq 1418:3869, ack 1, win 261, options [nop,nop,TS val 551014923 ecr 4169524240], length 2451
14:01:02.521706 IP muc03s08-in-f46.1e100.net.https > 192.168.1.10.36696: Flags [P.], seq 5726:7144, ack 759, win 273, options [nop,nop,TS val 551015206 ecr 4169524498], length 1418
14:01:02.521737 IP muc03s08-in-f46.1e100.net.https > 192.168.1.10.36696: Flags [.], seq 7144:9980, ack 759, win 273, options [nop,nop,TS val 551015207 ecr 4169524498], length 2836
14:01:02.522414 IP muc03s08-in-f46.1e100.net.https > 192.168.1.10.36696: Flags [.], seq 9980:11398, ack 759, win 273, options [nop,nop,TS val 551015208 ecr 4169524498], length 1418
14:01:02.523778 IP muc03s08-in-f46.1e100.net.https > 192.168.1.10.36696: Flags [P.], seq 11615:13033, ack 759, win 273, options [nop,nop,TS val 551015209 ecr 4169524498], length 1418

Filtrować możemy również pakiety mniejsze niż jakaś wartość i wtedy uzywamy przełącznika less.

Przykład: tcpdump -i eth0 less 128

$ tcpdump -i eth0 less 128
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:58:28.580781 IP 192.168.1.10.39158 > 82.221.107.34.bc.googleusercontent.com.http: Flags [.], ack 3522294884, win 501, options [nop,nop,TS val 4236398755 ecr 6682145], length 0
13:58:28.580874 IP 192.168.1.10.39156 > 82.221.107.34.bc.googleusercontent.com.http: Flags [.], ack 2826453460, win 501, options [nop,nop,TS val 4236398756 ecr 2048631299], length 0
13:58:28.603207 IP 82.221.107.34.bc.googleusercontent.com.http > 192.168.1.10.39158: Flags [.], ack 1, win 319, options [nop,nop,TS val 6692322 ecr 4236388602], length 0
13:58:28.604517 IP 82.221.107.34.bc.googleusercontent.com.http > 192.168.1.10.39156: Flags [.], ack 1, win 290, options [nop,nop,TS val 2048641499 ecr 4236388580], length 0
13:58:33.282406 ARP, Request who-has 192.168.1.10 (08:00:27:ff:62:f4 (oui Unknown)) tell 192.168.1.16, length 46
13:58:33.282426 ARP, Reply 192.168.1.10 is-at 08:00:27:ff:62:f4 (oui Unknown), length 28

Wyświetlanie danych

13. Wyświetlanie IP i numeru portu zamiast ich nazwy

Zauważyliście pewnie w poprzednich przykładach, że tcpdump wszędzie tam, gdzie zna nazwę hosta albo zna nazwę usługi wykorzystującej jakiś port, używa tej nazwy zamiast IP czy numeru portu. Czasem jest to wygodne a czasem nie, dlatego z pomocą przełącznika -n możemy wyłączyć wyświetlanie nazw.

Przykład: tcpdump -i eth0 -n

$ tcpdump -i eth0 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:51:32.084980 IP 192.168.1.10.37427 > 8.8.8.8.53: 38848+ [1au] A? detectportal.firefox.com. (53)
13:51:32.103101 IP 8.8.8.8.53 > 192.168.1.10.37427: 38848 3/0/1 CNAME detectportal.prod.mozaws.net., CNAME prod.detectportal.prod.cloudops.mozgcp.net., A 34.107.221.82 (164)
13:51:32.146179 IP 192.168.1.10.39130 > 34.107.221.82.80: Flags [S], seq 787965095, win 64240, options [mss 1460,sackOK,TS val 4235982321 ecr 0,nop,wscale 7], length 0
13:51:32.159527 IP 34.107.221.82.80 > 192.168.1.10.39130: Flags [S.], seq 198403640, ack 787965096, win 65535, options [mss 1430,sackOK,TS val 6275881 ecr 4235982321,nop,wscale 8], length 0
13:51:32.159564 IP 192.168.1.10.39130 > 34.107.221.82.80: Flags [.], ack 1, win 502, options [nop,nop,TS val 4235982334 ecr 6275881], length 0
13:51:32.162611 IP 192.168.1.10.39130 > 34.107.221.82.80: Flags [P.], seq 1:297, ack 1, win 502, options [nop,nop,TS val 4235982337 ecr 6275881], length 296: HTTP: GET /success.txt HTTP/1.1
13:51:32.174256 IP 34.107.221.82.80 > 192.168.1.10.39130: Flags [.], ack 297, win 261, options [nop,nop,TS val 6275896 ecr 4235982337], length 0

14. Zmiana formatu wyświetlania czasu

Przełączniki od -t do -ttttt pozwalają na zmianę formatu wyświetlania czasu, który pojawia się na początku każdej linii danych. W zależności od tego, jaki format jest nam wygodniejszy do wyświetlenia, możemy zupełnie pominąć wyświetlanie czasu (-t), wyświetlać różnicę czasu pomiędzy kolejnymi pakietami (-ttt), liczyć czas od początku przechwytywania (-ttttt), zobaczyć obecny czas w formacie „dzień i godzina” (-tttt), albo czas liczony od tzw. linux date, czyli od 1 stycznia 1970 (-tt).

Przykład: tcpdump -i eth0 -ttttt

$ tcpdump -i eth0 -ttttt
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
 00:00:00.000000 IP VM.ssh > 192.168.1.13.21528: Flags [P.], seq 3705323174:3705323302, ack 3983580164, win 501, length 128
 00:00:00.000105 IP VM.ssh > 192.168.1.13.21528: Flags [P.], seq 128:192, ack 1, win 501, length 64
 00:00:00.000228 IP VM.ssh > 192.168.1.13.21528: Flags [P.], seq 192:320, ack 1, win 501, length 128
 00:00:00.000276 IP 192.168.1.13.21528 > VM.ssh: Flags [.], ack 192, win 8210, length 0
 00:00:00.000327 IP VM.ssh > 192.168.1.13.21528: Flags [P.], seq 320:384, ack 1, win 501, length 64

15. Verbose

Przełączniki -v to -vvv pozwalają na wyświetlenie bardziej szczegółowych danych dotyczących komunikacji. Wyświetlane mogą być między innymi informacje o TTL, rozmiarze pakietu, opcje IP, a nawet dane z L7. W zależności od tego ile v dodamy do przełącznika, uzyskamy oczywiście inną szczegółowość danych, przy czym może się okazać, że dla niektórych przechwyconych danych będą one takie same dla -v, jak i dla -vvv.

Przykład: tcpdump -i eth0 -v

$ tcpdump -i eth0 -v
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:34:40.993088 IP (tos 0x10, ttl 64, id 11655, offset 0, flags [DF], proto TCP (6), length 104)
    VM.ssh > 192.168.1.13.21528: Flags [P.], cksum 0x83ca (incorrect -> 0x5fef), seq 3705333062:3705333126, ack 3983581316, win 501, length 64
12:34:40.993181 IP (tos 0x10, ttl 64, id 11656, offset 0, flags [DF], proto TCP (6), length 168)
    VM.ssh > 192.168.1.13.21528: Flags [P.], cksum 0x840a (incorrect -> 0x0a2b), seq 64:192, ack 1, win 501, length 128
12:34:40.993236 IP (tos 0x10, ttl 64, id 11657, offset 0, flags [DF], proto TCP (6), length 104)
    VM.ssh > 192.168.1.13.21528: Flags [P.], cksum 0x83ca (incorrect -> 0xe452), seq 192:256, ack 1, win 501, length 64
12:34:58.193262 IP (tos 0x0, ttl 128, id 34801, offset 0, flags [none], proto ICMP (1), length 60)
    192.168.1.13 > VM: ICMP echo request, id 1, seq 7, length 40
12:34:58.193300 IP (tos 0x0, ttl 64, id 3329, offset 0, flags [none], proto ICMP (1), length 60)
    VM > 192.168.1.13: ICMP echo reply, id 1, seq 7, length 40

16. Wyświetlanie zawartości pakietów w formacie ASCI

Korzystając z przełącznika -A możemy wyświetlić treść komunikacji w formacie ASCI. Dla niektórych protokołów wyświetlenie tych danych będzie nieprzydatne, ale dla innych takich jak http albo ICMP pozwoli zajrzeć do treści i szybciej diagnozować przyczyny problemów.

Przykład: tcpdump -i eth0 -A

$ tcpdump -i eth0 -A
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:03:33.062821 IP VM.38702 > 82.221.107.34.bc.googleusercontent.com.http: Flags [P.], seq 54301771:54302072, ack 2239212283, win 501, options [nop,nop,TS val 3300429786 ecr 1895218784], length 301: HTTP: GET /success.txt?ipv4 HTTP/1.1
E..aP.@.@.'v...."k.R...P.<.K.w.............
....p..`GET /success.txt?ipv4 HTTP/1.1
Host: detectportal.firefox.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

17. Wyświetlanie zawartości pakietów w formacie HEX

Zawartość pakietów można wyświetlać również w formacie HEX i służy do tego przełącznik -x

Przykład: tcpdump -i eth0 -x

$ tcpdump -i eth0 -x
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:12:13.912367 IP VM.38732 > 82.221.107.34.bc.googleusercontent.com.http: Flags [.], ack 2680183812, win 501, options [nop,nop,TS val 3300950635 ecr 3780474681], length 0
        0x0000:  4500 0034 286f 4000 4006 50dd c0a8 0112
        0x0010:  226b dd52 974c 0050 85d0 ebe4 9fc0 5c04
        0x0020:  8010 01f5 c19e 0000 0101 080a c4c0 826b
        0x0030:  e155 7739

18. Wyświetlanie zawartości pakietów w HEX i ASCI

Istnieje jeszcze możliwość równoczesnego wyświetlania danych w HEX i ASCI. Służy do tego przełącznik -X (duże X) a wynik działania komendy wygląda wtedy następująco:

Przykład: tcpdump -i eth0 -X

tcpdump -i eth0 -X
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:21:42.232322 IP VM.38750 > 82.221.107.34.bc.googleusercontent.com.http: Flags [.], ack 2606611082, win 501, options [nop,nop,TS val 3301518955 ecr 3781043002], length 0
        0x0000:  4500 0034 a29e 4000 4006 d6ad c0a8 0112  E..4..@.@.......
        0x0010:  226b dd52 975e 0050 e3f3 adc0 9b5d ba8a  "k.R.^.P.....]..
        0x0020:  8010 01f5 c19e 0000 0101 080a c4c9 2e6b  ...............k
        0x0030:  e15e 233a                                .^#:

Zapisywanie danych

19. Zapisywanie całej komunikacji do pliku

Często zdarza się, że komunikację możemy przeanalizować dopiero później albo musimy przeanalizować ją dokładniej niż to, co widać na ekranie. Przydaje się wtedy możliwość zapisania całej komunikacji do pliku pcap i możliwość jej późniejszej analizy np. w aplikacji Wireshark. Temat Wireshark’a i analizy plików pcap zasługuje na zupełnie osobny artykuł, ale tutaj skupimy się na sposobach nagrywania ruchu. Posłuży nam do tego przełącznik -w po którym podajemy ścieżkę, w której plik ma być zapisany oraz nazwę pliku z rozszerzeniem .pcap. Nagrywanie możemy przerwać za pomocą kombinacji klawiszy ctrl+c lub podać parametr -c ze wskazaniem ile pakietów ma się znaleźć w nagraniu.

Przykład: tcpdump -i eth0 -w /tmp/nagranie.pcap

20. Zapisywanie n pierwszych bajtów każdego z pakietów komunikacji do pliku

Przy długotrwałym nagrywaniu, kiedy może dojść do sytuacji, że plik z danymi będzie bardzo duży albo kiedy dane z L7 są nam niepotrzebne do analizy, możemy poprzestać na nagrywaniu jedynie n pierwszych bajtów pakietu. Ważne jest tutaj, żeby ta wartość nie była zbyt mała, i żeby nagrały się odpowiednie nagłówki L2, L3 i L4. Według mnie w przypadku większości komunikacji odpowiednią wartością będzie nagrywanie pierwszych 64 bajtów pakietów. W tym celu konieczne jest skorzystanie z przełącznika -s 64.

Przykład: tcpdump -i eth0 -s 64 -w /tmp/nagranie.pcap

21. Licznik danych podczas zapisywania

Jak pewnie zauważyłeś w poprzednich przykładach podczas nagrywania ruchu, dopóki nie przerwiemy procesu, nie wiemy, ile pakietów zostało przechwyconych i zapisanych. Możemy oczywiście wykorzystać przełącznik -c i zapisać konkretną liczbę pakietów, ale możemy też włączyć licznik pakietów i przerwać nagrywanie w momencie, kiedy sami dojdziemy do wniosku, że zapisaliśmy wystarczająco dużo danych. Do włączenia licznika służy parametr -v (tryb verbose). Licznik odświeżany jest co sekundę.

Przykład: tcpdump -i eth0 -v -w /tmp/nagranie.pcap

22. Wyświetlanie danych z pliku

Poza możliwością otwarcia nagrania w aplikacji Wireshark możemy również wyświetlić i na nowo przefiltrować zapisany wcześniej ruch. Według mnie Wireshark jest o wiele wygodniejszy, ale nie zawsze możemy z niego skorzystać, wybieramy wtedy parametr -r i wskazujemy ścieżkę do pliku z danymi.

Przykład: tcpdump -r /tmp/nagranie.pcap

$ tcpdump -r /tmp/nagranie.pcap
reading from file /tmp/nagranie.pcap, link-type EN10MB (Ethernet)
10:32:18.469063 IP VM.ssh > 192.168.1.13.1807: Flags [P.], seq 708540995:708541059, ack 284853948, win 501, length 64
10:32:18.469145 IP VM.ssh > 192.168.1.13.1807: Flags [P.], seq 64:192, ack 1, win 501, length 128
10:32:18.469248 IP 192.168.1.13.1807 > VM.ssh: Flags [.], ack 192, win 8208, length 0
10:32:18.469257 IP VM.ssh > 192.168.1.13.1807: Flags [P.], seq 192:256, ack 1, win 501, length 64
10:32:18.511058 IP 192.168.1.13.1807 > VM.ssh: Flags [.], ack 256, win 8208, length 0

23. Tcpreplay, czyli odtwarzanie zapisanych danych w sieci

Ostatni przykład to nie tcpdump tylko tcpreplay, narzędzie, którego możemy używać do odtwarzania nagranego ruchu w sieci. W przeciwieństwie do tcpdump z przełącznikiem -r dane nie są wyświetlane na ekranie, ale są wysyłane przez wskazany interfejs sieciowy do sieci. Oczywiście komputery, które odbiorą te pakiety, nie będą ich poprawnie przetwarzały, ale nie to jest przyczyną odtwarzania ruchu za pomocą tcpreplay. Tcpreplay możemy użyć np. do wysyłania nagranych danych do sniferów sieciowych, czyli urządzeń, których zadaniem nie jest odpowiadanie na ruch, ale jego analiza w celu generowania statystyk albo wykrywania włamań czy anomalii.

Podstawowa składnia tcpreplay jest bardzo prosta, a na koniec dostajemy bardzo przejrzystą statystykę odtworzonego ruchu.

Przykład: tcpreplay -i eth0 /tmp/nagranie.pcap

$ tcpreplay -i eth0 /tmp/nagranie.pcap
tcpreplay: Symbol `pcap_version' has different size in shared object, consider re-linking
Actual: 11 packets (1072 bytes) sent in 3.04 seconds
Rated: 352.3 Bps, 0.002 Mbps, 3.61 pps
Flows: 2 flows, 0.65 fps, 11 flow packets, 0 non-flow
Statistics for network device: eth0
        Successful packets:        11
        Failed packets:            0
        Truncated packets:         0
        Retried packets (ENOBUFS): 0
        Retried packets (EAGAIN):  0

Podsumowanie

Jeśli ten artykuł Ci się podobał, podziel się nim z innymi, którym może się on również przydać. A jeśli znasz jeszcze jakieś inne przydatne sposoby na użycie tcpdump, to zostaw komentarz, żeby kolejne osoby mogły z niego skorzystać. Trzymaj się ciepło i do kolejnej wizyty na moim blogu 🙂

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.