همیشه برای بعضی از کاربران سؤالاتی مطرح است که از کدام برنامه برای log گیری شبکه استفاده نمایند. تا زمانی که این خواسته کاربران مشخص نباشد این سؤال بدون جواب باقی میماند.
خوب مسلماً برنامههای زیادی با کاربردهای زیادی هستند انواع monitoring شبکه را داریم که هریک بنا به رسته خود مورد بحث قرار میگیرد و باز در بحث sniffing تقسیمبندی های متفاوتی همانند log گیری حجم اطالاعات شبکه، capture کردن دادهها، ابزاری برای برنامهسازی و غیره موجودند که همزمان با زمان و پروتکلها تغییر میکنند.
اما چرا tcpdump ؟ زمانی که کاربری بخواهد در مورد packet ها تحقیق کند باید آنها capture کرده و حال یا از آنها log گرفته و این log مهم است و یا کار با یک grep حل میشود. سؤالی که مطرح میشود این است که wireshark نیز همین کار را انجام میدهد چرا از آن استفاده نشود؟ مسلماً یک کاربر شبکه همزمان بر روی چندین سرور باید برود که هیچ کنسول گرافیکی وجود ندارد و بقیه قضیا… اما اگر در مورد کاربرد wireshark میخواهید بپرسید در برنامهسازی به شدت کاربرد دارد.
۱. خود برنامه tcpdump
کار با با tcpdump به دو بخش خود برنامه آن و بخش filter نویسی برای آن تقسیم میشود. به طوری که حتی manual page های آنان متفاوت میباشد. برای خود آن باید (8)tcpdump را مطالعه کرد و برای filter نویسی در tcpdump باید (7)pcap-filter را مطالعه کرد.
این برنامه جزو پروژه pcap میباشد که یک library قوی برای capture کردن packet ها میباشد.
بهتر است یک مرور کلی بر روی option های اصلی آن داشته باشیم تا به اصل قضیه یعنی نوشتن فیلتر بپردازیم.
همه چیز با تعیین interface مربوطه شروع میشود:
1 2 3 4 5 6 7 8 9 10 11 12 |
root@debian:/home/mohsen# 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 21:55:38.963133 IP dev32.1900 > 239.255.255.250.1900: UDP, length 94 21:55:39.512530 IP debian.47888 > google-public-dns-a.google.com.domain: 33222+ PTR? 250.255.255.239.in-addr.arpa. (46) 21:55:39.516780 IP dev32.1900 > 239.255.255.250.1900: UDP, length 94 21:55:39.774315 IP google-public-dns-a.google.com.domain > debian.47888: 33222 NXDomain 0/1/0 (103) 21:55:40.175894 IP dev32.1900 > 239.255.255.250.1900: UDP, length 94 ^C 5 packets captured 7 packets received by filter 0 packets dropped by kernel |
بله، در بالا به tcpdump گفتیم به eth0 گوش فرا دهد.
اما بیایید کمی فرمت خروجی را بررسی کنیم:
عملگر < بین دو host قرار میگیرند و نشانگر ورودی خروجی سیستم میباشند به خط زیر نگاه کنید:
1 |
21:55:39.774315 IP google-public-dns-a.google.com.domain > debian.47888: 33222 NXDomain 0/1/0 (103) |
hostname سیستم شخصی من debian میباشد packet از سیستم google-public-dns-a.google.com به سیستم من انتقال پیدا کرده است. همانطور که از نامش پیداست resolve کردن بوده یک NXDomain بوده است. به زودی چشمتان با بقیه مقادیر آشنا میشود.
option های خانواده v- :
v- همانطور که از نامش پیداست verbose mode است. این verbose mode برای فرمت خروجی استفاده میشود.
vv- بستهها را باز میکند. و فیلدهای بیشتری را به نمایش میگذارد.
vvv- به صورت کامل گزینهها را نمایش میدهد.
نکته: اینجا مثال نمیاوریم چون فرض بر این است که کاربری شما را نمیدانیم، به عنوان مثال، گاهی برای شخصی باید یک log بگیرید و به عنوان سند برایش بفرستید که بهتر است log شما کامل باشد. اما نه گاهی نیاز است از tcpdump فقط یک grep گرفته که باز بسته به این که از چه چیزی میخواهید grep بگیرید به آن باید گزینه اضافه کنید چون کار خود را سخت کردهاید. پس شما باید خود نیازسنجی کنید تا به نتیجه بهتری برسید.
پس خواهشی که وجود دارد نکته بالا را در تمام مثالها رعایت فرمایید.
اما چند مثال ساده:
همانند سایر دستورات مثل netstat شما میتوانید hostname ها را ندید گرفته و از فرمت IP آنها استفاده نمایید همانند زیر :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
root@debian:/home/mohsen# 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 03:07:30.191457 IP 192.168.1.1.32865 > 239.255.255.250.1900: UDP, length 328 03:07:30.300709 IP 192.168.1.1.32865 > 239.255.255.250.1900: UDP, length 328 03:07:30.408663 IP 192.168.1.1.32865 > 239.255.255.250.1900: UDP, length 337 03:07:30.518178 IP 192.168.1.1.32865 > 239.255.255.250.1900: UDP, length 337 03:07:30.627724 IP 192.168.1.1.32865 > 239.255.255.250.1900: UDP, length 392 03:07:30.737305 IP 192.168.1.1.32865 > 239.255.255.250.1900: UDP, length 392 03:07:30.804819 IP 74.125.195.189.443 > 192.168.1.4.43132: Flags [P.], seq 2104755659:2104755718, ack 652043965, win 1653, options [nop,nop,TS val 166742941 ecr 4375072], length 59 03:07:30.804895 IP 192.168.1.4.43132 > 74.125.195.189.443: Flags [.], ack 59, win 940, options [nop,nop,TS val 4381302 ecr 166742941], length 0 03:07:30.847981 IP 192.168.1.1.32865 > 239.255.255.250.1900: UDP, length 402 03:07:30.956411 IP 192.168.1.1.32865 > 239.255.255.250.1900: UDP, length 402 ^C 10 packets captured 10 packets received by filter 0 packets dropped by kernel |
tcpdump یک option دارد که به ما کمک میکند که تعداد بسته را مشخص کنیم البته بدرد این مقاله میخورد، در دنیای واقعی کاربرد کمی دارد ولی به درد آمار در ساعت میخورد.
بیایید دستور زیر را بررسی نماییم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
root@debian:/home/mohsen# tcpdump -i eth0 -n -c2 -A -vvv tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 03:11:49.131499 IP (tos 0x0, ttl 4, id 0, offset 0, flags [DF], proto UDP (17), length 356) 192.168.1.1.32865 > 239.255.255.250.1900: [udp sum ok] UDP, length 328 E..d..@..............a.l.P..NOTIFY * HTTP/1.1 HOST: 239.255.255.250:1900 CACHE-CONTROL: max-age=100 LOCATION: http://192.168.1.1:49152/description.xml NT: upnp:rootdevice NTS: ssdp:alive SERVER: Linux/2.6.22.15, UPnP/1.0, Portable SDK for UPnP devices/1.3.1 X-User-Agent: redsonic USN: uuid:bc329e00-1dd8-11b2-8601-0026755d2a2e::upnp:rootdevice 03:11:49.239209 IP (tos 0x0, ttl 4, id 0, offset 0, flags [DF], proto UDP (17), length 356) 192.168.1.1.32865 > 239.255.255.250.1900: [udp sum ok] UDP, length 328 E..d..@..............a.l.P..NOTIFY * HTTP/1.1 HOST: 239.255.255.250:1900 CACHE-CONTROL: max-age=100 LOCATION: http://192.168.1.1:49152/description.xml NT: upnp:rootdevice NTS: ssdp:alive SERVER: Linux/2.6.22.15, UPnP/1.0, Portable SDK for UPnP devices/1.3.1 X-User-Agent: redsonic USN: uuid:bc329e00-1dd8-11b2-8601-0026755d2a2e::upnp:rootdevice 2 packets captured 4 packets received by filter 0 packets dropped by kernel |
تحلیل پارامترهای tcpdump: در ابتدا به آن interface را معرفی کردیم و گفتیم همه چی را بهه صورت numeric برگردان. سپس با c2- به آن گفتیم دو بسته را capture کن. پارامتر A- میگوید هر نوع بستهای را capture کند که این اصلاً خوب نیست و در جلوتر با آن برخورد اساسی میشود. و در نهایت به صورت full بسته و optionهای آن را از tcpdump درخواست کردیم.
تحلیل بستهها: کافیست کمی با چشم به آن دو بسته که با blank line از هم جدا شدهاند دقت کنیم. دو بسته از نوع UDP که با طول ۳۵۶ میباشند و TTL برابر ۴. البته جزییات خیلی بیشتر قابل رویت هستند. همانطور که قبلاً گفته شد vvv- خیلی از بستهها را بازنموده و این ۲ بسته از نوع Cache میباشند به طوری کهX-User-Agent آنها هم مشخص است.
به سادگی میتوان گزینه server را در آن grep کرده و نتیجه زیر را حاصل کرد:
1 2 3 4 5 6 7 |
root@debian:/home/mohsen# tcpdump -i eth0 -n -c2 -A -vvv |grep -i server tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 2 packets captured 8 packets received by filter 0 packets dropped by kernel SERVER: Linux/2.6.22.15, UPnP/1.0, Portable SDK for UPnP devices/1.3.1 SERVER: Linux/2.6.22.15, UPnP/1.0, Portable SDK for UPnP devices/1.3.1 |
نکته: دل به این grep کردن خوش نکنیم و به مثالهای جلوتر که برسیم میفهمیم که هر چقدر جلوتر برویم فهممان را باید از شبکه بیشتر کنیم.
آیا بسته با vvv- باز شد؟ بله اما هنوز ابزار شما کمی ناقص است. قبلاً xx- کوچک بود که به صورت hex هدرهایی را باز مینمود اما deprecate شد. به دو دلیل:
-
پروتکلهای جدید را حمایت نمیکند.
-
به صورت ASCII پرینت نمیکند.
همان xx- را اگر به صورت upercase یعنی XX- به کار ببریم همه چی تغییر میکند.به مثال زیر نگاه کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
root@debian:/home/mohsen# tcpdump -i eth0 -n -c1 -A -vvv -xx tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 03:57:01.757946 IP (tos 0x88, ttl 39, id 37674, offset 0, flags [none], proto TCP (6), length 111) 74.125.195.189.443 > 192.168.1.4.43132: Flags [P.], cksum 0xf122 (correct), seq 2104786500:2104786559, ack 652173423, win 1653, options [nop,nop,TS val 169713897 ecr 5118382], length 59 0x0000: 1803 7360 b44e 0026 755d 2a2e 0800 4588 0x0010: 006f 932a 0000 2706 2ff0 4a7d c3bd c0a8 0x0020: 0104 01bb a87c 7d74 7e44 26df 606f 8018 0x0030: 0675 f122 0000 0101 080a 0a1d a0e9 004e 0x0040: 19ae 1703 0300 3600 0000 0000 0003 399c 0x0050: f906 ed6e 12d0 6d67 f7d6 59a7 8996 0faa 0x0060: 98cb 05a4 feb2 0175 4821 eca2 bb83 bd32 0x0070: dd5d c36e 8314 d4ed f235 4c93 5e 1 packet captured 2 packets received by filter 0 packets dropped by kernel |
حالا همان را با upercase انجام میدهیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
root@debian:/home/mohsen# tcpdump -i eth0 -n -c1 -A -vvv -XX tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 03:57:52.310213 IP (tos 0x0, ttl 64, id 47728, offset 0, flags [DF], proto UDP (17), length 61) 192.168.1.4.34498 > 8.8.8.8.53: [udp sum ok] 36690+ A? play.google.com. (33) 0x0000: 0026 755d 2a2e 1803 7360 b44e 0800 4500 .&u]*...s`.N..E. 0x0010: 003d ba70 4000 4011 ae83 c0a8 0104 0808 .=.p@.@......... 0x0020: 0808 86c2 0035 0029 74b0 8f52 0100 0001 .....5.)t..R.... 0x0030: 0000 0000 0000 0470 6c61 7906 676f 6f67 .......play.goog 0x0040: 6c65 0363 6f6d 0000 0100 01 le.com..... 1 packet captured 5 packets received by filter 0 packets dropped by kernel root@debian:/home/mohsen# |
دومی برای grep عالی است. با تجربه کاری به یاد دارم همکارم با همین vvv- و XX- حمله کننده به سایت را توانست شناسایی کند که به کدام سایت میخواهد حمله کند. تنها با grep……!!!! البته فیلترهایی هم نوشت که در جلوتر توضیح میدهم.
رکورد در فایل :
بله ممکن است شما بخواهید کل capture را در فایل بنویسید این ۲ راه دارد:
-
شما کل دستور tcpdump را با یک IO/Redirection در یک فایل ذخیره نمایید.
-
با w- در یک فایل ینوسید:
1 2 3 4 5 |
root@debian:/home/mohsen# tcpdump -i eth0 -n -c1 -A -vvv -XX -w `date +%Y_%m_%d.pcap` tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 1 packet captured 5 packets received by filter 0 packets dropped by kernel |
که فایل روبرو ذخیره میشد:
1 |
2015_03_14.pcap |
نکته: پسوند اینگونه فایلها pcap میباشد.
نکته: ممکن است بخواهید گزینه زمان را از خروجی حذف نمایید که میتوانید از خانواده t- استفاده نمایید. اما توصیه میشود برای گرفتن log برای کسی یا جایی که مستند است این کار را انجام ندهید.
حال که گوشهای از option های tcpdump را فراگرفتید میتوان filter نوشتن را فراگرفت.
۲. نوشتن filter
برای اول کار filter نویسی باید ۴ عملگر اصلی شرطی آن را دانست:
-
and یا همان &&
-
not یا همان !
-
or یا همان ||
-
عملگر تساوی یا همان ==
در جلوتر بعضی از عملگرهای پیشرفتهتر را نیز توضیح خواهیم داد. (البته در مثال)
1 2 3 4 5 6 7 8 |
root@debian:/home/mohsen# tcpdump -i eth0 -n -c2 'dst port 80 or 443' tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 05:02:55.093879 IP 192.168.1.4.58878 > 10.10.34.34.443: Flags [S], seq 2334601873, win 29200, options [mss 1460,sackOK,TS val 6112375 ecr 0,nop,wscale 7], length 0 05:02:56.633867 IP 192.168.1.4.48764 > 74.125.195.100.443: Flags [P.], seq 3792460615:3792460656, ack 1332089255, win 397, options [nop,nop,TS val 6112759 ecr 3204520238], length 41 2 packets captured 4 packets received by filter 0 packets dropped by kernel |
همانطور که در فرمان بالا دیدید مسیر بستهها را به بیرون محدود کرده و پورتها را به پورت SSL وب و پورت عادی وب محدود کردیم. این بدان معناست که هرچه request وب داشتیم capture میشود.
1 2 3 4 5 6 7 8 |
root@debian:/home/mohsen# tcpdump -i eth0 -n -c2 'dst port 995 or 465' tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 05:28:27.850431 IP 192.168.1.4.58666 > 198.23.143.231.995: Flags [S], seq 3003232596, win 29200, options [mss 1460,sackOK,TS val 6495564 ecr 0,nop,wscale 7], length 0 05:28:28.175118 IP 192.168.1.4.58666 > 198.23.143.231.995: Flags [.], ack 1659429373, win 229, options [nop,nop,TS val 6495645 ecr 3266956330], length 0 2 packets captured 3 packets received by filter 0 packets dropped by kernel |
درخواست بالا به پورتهای مقصد pops و smpts را capture کردیم.
این چنین میتوان هم از عملگر and استفاده کرد و هم محدود به یک host شد:
1 2 3 4 5 6 7 8 |
root@debian:/home/mohsen# tcpdump -i eth0 -c2 'src port 443 or 80 ' and host google.com tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 05:37:39.889315 IP wj-in-f139.1e100.net.http > debian.35368: Flags [.], ack 3030103160, win 341, options [nop,nop,TS val 1627400588 ecr 6631017], length 0 05:37:39.905789 IP wj-in-f139.1e100.net.http > debian.35369: Flags [.], ack 3973516011, win 341, options [nop,nop,TS val 3679981984 ecr 6631021], length 0 2 packets captured 7 packets received by filter 0 packets dropped by kernel |
نکته: host میتواند IP باشد.
با دستور زیر src host را محدود کردیم به یکی از کلایتهای شبکه و با دو پروتکل arp و یا icmp آن را and کردیم و از همین ماشین آن را ping کردیم و جواب گرفتیم:
1 2 3 4 5 6 7 8 |
root@debian:/home/mohsen# tcpdump -i eth0 -c2 'src host 192.168.1.1 and ( arp or icmp )' tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 05:52:33.558905 IP 192.168.1.1 > debian: ICMP echo reply, id 9862, seq 19, length 64 05:52:34.560079 IP 192.168.1.1 > debian: ICMP echo reply, id 9862, seq 20, length 64 2 packets captured 3 packets received by filter 0 packets dropped by kernel |
فرمان زیر از عملگر =! اسفاده کرده بود و در خود (8)tcpdump ولی حیفم اومد که براتون نگذارم این تمام type های icmp رو پرینت میگره به جز ping و pong درواقع type های echo و echo reply:
1 |
root@debian:/home/mohsen# tcpdump -i eth0 'icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply' |
برای اینکه در خروجی چیزی ببینید، در همین host باید icmp را با دستور زیر بست:
1 |
root@debian:/home/mohsen# iptables -A INPUT -p icmp -j REJECT |
سپس به یک host دیگر رفته و سعی کنیم به این host دسترسی پیدا کنیم و پیغام زیر را در همین host میبینیم:
1 2 3 4 5 6 7 8 9 10 |
root@debian:/home/mohsen# tcpdump -A -i eth0 'icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply' tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 06:09:44.546077 IP debian > 192.168.1.8: ICMP debian protocol 1 port 5965 unreachable, length 92 E..p;~..@...................E..T.>..@..............M....U........ ..................... !"#$%&'()*+,-./01234567 06:09:45.603283 IP debian > 192.168.1.8: ICMP debian protocol 1 port 13870 unreachable, length 92 E..p<v..@...................E..T.B..@.. ..........6.....U........ ..................... !"#$%&'()*+,-./01234567 |
نکته: زمانی که از src و یا dst برای host استفاده نشود ترافیک بین دو host باید capture شود به مثال زیر دقت شود:
1 2 3 4 5 6 7 8 9 |
root@debian:/home/mohsen# tcpdump -A -i eth0 host 192.168.1.1 and host 192.168.1.8 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 06:20:45.792313 IP 192.168.1.8 > 192.168.1.1: ICMP echo request, id 3845, seq 0, length 64 E..T....@.............BW....U..;...Z. ..................... !"#$%&'()*+,-./01234567 06:20:45.792328 IP 192.168.1.8 > 192.168.1.1: ICMP echo request, id 3845, seq 0, length 64 E..T....@.............BW....U..;...Z. ..................... !"#$%&'()*+,-./01234567 |
ماشینی که بر روی آن tcpdump گرفتیم IP آن 4 میباشد و درواقع ما اینجا sniff کردیم.
برای تست کردن handshaking میتوان از filter های زیر استفاده کرد:
1 2 3 4 5 6 7 8 9 10 11 12 |
ACK packets: ‘tcp[13] & 16 != 0‘ PSH packets: ‘tcp[13] & 8 != 0‘ RST packets: ‘tcp[13] & 4 != 0‘ SYN packets: ‘tcp[13] & 2 != 0′ FIN packets: ‘tcp[13] & 1 != 0‘ SYN-ACK packets: ‘tcp[13] = 18‘ |
tcpdump بزرگتر از آن است که بخواهم در tutorial ساده تمام عملگرهای آن را بگویم و یا filter های آن را اشاره کنم. هر گونه filter آن به یک گونه error بر میخورد که این خود تجربهایست برای یک sysadmin. اما امیدوارم توانسته باشم شما را با آن آشنا کرپده باشم.
خوشمان آمد .
in amal gar عملگر =!
chi kar mikone?
این عملگر به معنای عدم تساوی است. همانند زبان C. البته شما یک کاربرد در tcpdump بگید تا اون رو تحلیل کنیم.