Tcpdump

Bana kalırsa bir networkçü için olmazsa olmaz şeylerden birisi Wireshark, diğeri de tcpdump’tır. İletişim için kullanılan mesajlaşmaları en ham haliyle görebileceğiniz ve anlamlandırabileceğiniz, yer yer protokol anlamak için yer yer de troubleshooting için kullanmak isteyeceğiniz tcpdump’tan bahsediyorum.

Sadece network mühendisleri değil, ses ekiplerinden sistem ekiplerine herkes çok temel kontroller için bile kullanabiliyor bu programı. Örneğin ulaşamadığınız bir porta verilen ICMP yanıtı ne? Ping paketleri karşı uca ulaşıyor mu yoksa yolda bir yerde mi kayboluyor? Gönderilen mesajların boyutu ne? SIP contact adresi yanlış mı girilmiş?

Aradığınızı muhtemelen tcpdump ile bulacaksınız. : )

Örnekler

Standart bir çıktı:

root@ip-172-31-22-143:~# tcpdump -c 10
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
11:19:19.723616 IP ip-172-31-22-143.eu-central-1.compute.internal.ssh > x.x.x.x.dsl.static.turk.net.10816: Flags [P.], seq 320:384, ack 1, win 284, length 64
11:19:19.723816 IP ip-172-31-22-143.eu-central-1.compute.internal.44612 > ip-172-31-0-2.eu-central-1.compute.internal.domain: 1049+ PTR? x.x.x.x.in-addr.arpa. (43)
...

Sadece ICMP paketleri:

root@ip-172-31-22-143:~# tcpdump icmp

Bu cihaza ya da bu cihazdan dışarıya bir yere ping atmayı deneyin bakalım. Tcpdump’ı CTRL + C ile sonlandırabilirsiniz.

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

11:24:28.449759 IP x.x.x.x.dsl.static.turk.net > ip-172-31-22-143.eu-central-1.compute.internal: ICMP echo request, id 1, seq 7, length 40
11:24:28.449784 IP ip-172-31-22-143.eu-central-1.compute.internal > x.x.x.x.dsl.static.turk.net: ICMP echo reply, id 1, seq 7, length 40

Sadece 8.8.8.8 ile yapılan iletişim:

root@ip-172-31-22-143:~# tcpdump host 8.8.8.8
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

11:27:26.104170 IP ip-172-31-22-143.eu-central-1.compute.internal > google-public-dns-a.google.com: ICMP echo request, id 9008, seq 1, length 64
11:27:26.126807 IP google-public-dns-a.google.com > ip-172-31-22-143.eu-central-1.compute.internal: ICMP echo reply, id 9008, seq 1, length 64

Biraz daha toparlanmış bir çıktı istiyorsanız:

root@ip-172-31-22-143:~# tcpdump -ttttnnvv icmp
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
2017-05-01 11:51:54.949377 IP (tos 0x0, ttl 119, id 21024, offset 0, flags [none], proto ICMP (1), length 60)
    x.x.x.x > 172.31.22.143: ICMP echo request, id 1, seq 19, length 40
2017-05-01 11:51:54.949404 IP (tos 0x0, ttl 64, id 31385, offset 0, flags [none], proto ICMP (1), length 60)
    172.31.22.143 > x.x.x.x: ICMP echo reply, id 1, seq 19, length 40

Kullanımı

  • -t veya -tttt : Paketlerin zaman bilgisini okunabilir hale getiriyor. t sayısı arttıkça daha okunaklı hale geliyor.
  • -n ve -nn : n hostname’leri çözmemeyi sağlarken nn hostname’leri ve portları çözmeyi engelliyor.
  • -v, -vv, -vvv : Paket detay bilgilerini göstermeyi sağlarken

Belli başlı diğer seçenekler:

  • -i any : Tüm interface’leri dinle.
  • -i eth0 : Sadece eth0 interface’ini dinle.
  • -n : Hostname’leri çözümleme.
  • -nn : Hostname’leri ya da port isimlerini çözümleme.
  • -t : Bu zaman damgalarını insan okuyacak!
  • -tttt : Bu zaman damgalarını gerçekten insan okuyacak, azıcık insaf. :(
  • -X : Paket içeriğini hem hexadecimal hem den ascii olarak göster.
  • -XX : Paket içeriğini hem hexadecimal hem den ascii olarak gösterirken ethernet header’larını da ekle.
  • -c : Belirtilen sayıda paketten sonra capture’ı durdur.
  • -e : Ethernet headerlarını da çıktıya ekle.
  • -w : Çıktıları belirtilen dosya ismiyle kaydetmeye yarıyor. En çok kullanılan seçenek belki de; çıktıları -w ile .pcap olarak yazdırıp Wireshark ile incelemek.

Tabi bunlar yeterli değil. Yukarıdaki argümanlar çoğunlukla çıktının nasıl olacağını belirliyor. Önemli olan nereyi, nasıl dinleyeceğimiz. Hangi interface’e hangi ip:port’tan gelen ne çeşit istekleri incelemek istiyorsak bunları uygun bir dille belirtmek gerek.

Uygun dil

Tcpdump syntax’i Wireshark’ın capture filter’ı ile aynı seçeneklere sahiptir.

  • Host belli bir ip’yi ya da domain’i temsil eder. Örn: tcpdump host 192.168.1.1 ya da tcpdump host gunhanoral.com
  • Net network’ün kısaltmasıdır. Örn: tcpdump net 192.168.0.0/24 ya da tcpdump net 192.168.0.0 mask 255.255.255.0
  • Port parametresiyle port belirtilebilir. Çok şaşıracaksınız, tcpdump port 80 komutu 80 portunu kullanan trafiği gösterir.
    • libpcap belirli bir versiyonun üzerindeyse portrange de çalışacaktır: tcpdump portrange 100-200
  • Src ve dst sırasıyla kaynak ve hedef noktaların belirlenmesinde yardımcı olur. Örn: tcpdump src net 192.168.1.0/24
  • Protokol ismi kullanmanız o protokole ait paketlerin filtrelenmesini sağlar. tcpdump arp
  • En güzeli de tüm bu parametreleri and, or, not gibi boolean mantığına uygun bir biçimde birlikte kullanabilmemiz!
    • tcpdump not broadcast and not multicast
    • tcpdump port not 53 and not arp
    • tcpdump host 192.168.1.1 or host 192.168.1.3
    • tcpdump ‘host gunhanoral.com and not (port 80 or port 25)’
    • tcpdump ‘src net 192.168.0.0/16 and dst net (10.0.0.0/8 or 172.16.0.0/16)’

Bu dili kullanarak bir uygulama yapalım. Son dönemde ortalığı kasıp kavuran Wannacry bildiğiniz üzere SMB portu (139) üzerinden yayılıyordu. Gelin sistemimize bu porttan gelen bir şey var mı bakalım.

tcpdump -ttttnnvv port 139

Yeterli bir süre beklememe rağmen sonuç alamadım. Ben de bu porta telnet olmaya karar verdim:

tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
2017-06-15 18:23:29.733650 IP (tos 0x0, ttl 127, id 19970, offset 0, flags [DF], proto TCP (6), length 52)
    x.x.x.x.58114 > y.y.y.y.139: Flags [S], cksum 0x65c2 (correct), seq 2540976548, win 8192, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
2017-06-15 18:23:29.733718 IP (tos 0x0, ttl 64, id 49439, offset 0, flags [DF], proto TCP (6), length 40)
    y.y.y.y.139 > x.x.x.x.58114: Flags [R.], cksum 0xc681 (correct), seq 0, ack 2540976549, win 0, length 0
2017-06-15 18:23:30.234072 IP (tos 0x0, ttl 127, id 19972, offset 0, flags [DF], proto TCP (6), length 52)
    x.x.x.x.58114 > y.y.y.y.139: Flags [S], cksum 0x65c2 (correct), seq 2540976548, win 8192, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
2017-06-15 18:23:30.234227 IP (tos 0x0, ttl 64, id 49467, offset 0, flags [DF], proto TCP (6), length 40)
    y.y.y.y.139 > x.x.x.x.58114: Flags [R.], cksum 0xc681 (correct), seq 0, ack 1, win 0, length 0
2017-06-15 18:23:30.734781 IP (tos 0x0, ttl 127, id 19974, offset 0, flags [DF], proto TCP (6), length 48)
    x.x.x.x.58114 > y.y.y.y.139: Flags [S], cksum 0x79d1 (correct), seq 2540976548, win 8192, options [mss 1460,nop,nop,sackOK], length 0
2017-06-15 18:23:30.734823 IP (tos 0x0, ttl 64, id 49483, offset 0, flags [DF], proto TCP (6), length 40)
    y.y.y.y.139 > x.x.x.x.58114: Flags [R.], cksum 0xc681 (correct), seq 0, ack 1, win 0, length 0

Görüldüğü üzere x.x.x.x ip’li bilgisayarımdan y.y.y.y ip’si 139 nolu porta bağlanmaya çalıştım ama yapılan üç denemede de TCP SYN isteğime RST cevabı geldi.

Derin mevzular

Kendimize rehber olarak tcpdump manpage alalım ve SYN paketlerini filtreleyelim. SYN bayrağının havada olduğu TCP paketlerine bakacak olursak 13. oktetin değerinin 2 olmasını bekleriz. Zaten bu beklentimiz sonuç da verecektir:

# tcpdump -ttttnnvv port 139 and tcp[13] == 2
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
2017-06-15 18:38:54.743018 IP (tos 0x0, ttl 127, id 22877, offset 0, flags [DF], proto TCP (6), length 52)
    x.x.x.x.58238 > y.y.y.y.139: Flags [S], cksum 0x8972 (correct), seq 1266246003, win 8192, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
2017-06-15 18:38:55.243962 IP (tos 0x0, ttl 127, id 22879, offset 0, flags [DF], proto TCP (6), length 52)
    x.x.x.x.58238 > y.y.y.y.139: Flags [S], cksum 0x8972 (correct), seq 1266246003, win 8192, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
2017-06-15 18:38:55.744739 IP (tos 0x0, ttl 127, id 22881, offset 0, flags [DF], proto TCP (6), length 48)
    x.x.x.x.58238 > y.y.y.y.139: Flags [S], cksum 0x9d81 (correct), seq 1266246003, win 8192, options [mss 1460,nop,nop,sackOK], length 0

Peki neden? Alın teri değil, copy paste:

0                            15                              31
-----------------------------------------------------------------
|          source port          |       destination port        |
-----------------------------------------------------------------
|                        sequence number                        |
-----------------------------------------------------------------
|                     acknowledgment number                     |
-----------------------------------------------------------------
|  HL   | rsvd  |C|E|U|A|P|R|S|F|        window size            |
-----------------------------------------------------------------
|         TCP checksum          |       urgent pointer          |
-----------------------------------------------------------------

Her bir satır 32 bit, yani 4 oktet. TCP flaglerimiz 4. satırda. Birlikte sayalım:

  1. İlk satır 0’ıncı ve 3’üncü oktet aralığını gösteriyor.
  2. İkinci satırımız 4-7 arası
  3. 8-11 arası
    1. oktet offset ve reserved bitler. 13. oktet… aradığımız bayraklar.

SYN flag’i (sağdan sayarsak) kaçıncı bitinde peki bu oktet’in? İkinci sırasında. Sadece SYN’in aktif olduğu flag bit şeklinde nasıl yazılır? 00000010. Bu da eşittir 2. Yani sadece RST flag’i havada olacak olsa beklentimiz ne olurdu? 3 mü? Hayır. 00000100 = 4. ACK-SYN paketlerini nasıl buluruz? 13. oktet değeri 00010010 = 16 + 2 = 18.

Deneyelim:

# tcpdump -ttttnnvv tcp[13] == 18

Aldığımız yanıt:

2017-06-15 18:51:18.003595 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52)
    y.y.y.y.22 > x.x.x.x.58371: Flags [S.], cksum 0x34ce (incorrect -> 0x1b1c), seq 2640079490, ack 1360160, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0

Not: Flags [S.] aslen S ve A flaglerini temsil ediyor. SYN + ACK yani. Kaynak

Peki yanında ACK olsun olmasın ben herhangi bir SYN paketini yakalamak istiyorum. Yukarıdaki filtreler bu konuda bize yardımcı olmayacaktır zira bu filtreler spesifik olarak ilk örnekte sadece S bitinin 1 olduğu; ikinci örnekte de sadece S ve A bitlerinin 1 olduğu durumları arayacak şekilde dizayn edilmiştir.

Ne yapmalı, ne etmeli, bir oyunbazlık bir şeytanlık:

SYN biti hangisiydi? 2.bit. Yani biz herhangi bir flag değerini 00000010 ile boolean mantık olarak AND’lersek sonucu 00000010 veren her flag değerinin SYN biti aktiftir.

Deneyelim:

01010101	01000010	11111111
00000010	00000010	00000010
--------	--------	--------
00000000	00000010	00000010

Sanki doğru yoldayız. AND işlemini & olarak yazmalıyız. Ancak bash bu özel karakteri background için kullanacaktır, o yüzden tırnak içine almalıyız.

# tcpdump -ttttnnvv 'tcp[13] & 2 == 2'
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
2017-06-15 19:35:31.874196 IP (tos 0x0, ttl 127, id 5650, offset 0, flags [DF], proto TCP (6), length 52)
    x.x.x.x.58897 > y.y.y.y.22: Flags [S], cksum 0x9526 (correct), seq 3756179255, win 8192, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
2017-06-15 19:35:31.874257 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52)
    y.y.y.y.22 > x.x.x.x.58897: Flags [S.], cksum 0x34ce (incorrect -> 0x2fb9), seq 2075498391, ack 3756179256, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0

Tabi bu işlemler sadece TCP’ye özel değil. Bir çok farklı işlem yapılabilir:

  • Evil Bit‘i set olanlar: tcpdump 'ip[6] & 128 != 0'
  • HTTP GET: tcpdump 'tcp[32:4] = 0x47455420'
  • TTL’i 10’dan az olanlar: tcpdump 'ip[8] < 10'

Leave a comment