├── README.md └── tcpdump_advanced_filters.txt /README.md: -------------------------------------------------------------------------------- 1 | cheatsheat-tcpdump 2 | ================== 3 | 4 | cheatsheat-tcpdump 5 | 6 | 1) The most examples came from: 7 | 8 | Sebastien Wains 9 | 10 | http://www.wains.be 11 | 12 | -------------------------------------------------------------------------------- /tcpdump_advanced_filters.txt: -------------------------------------------------------------------------------- 1 | tcpdump advanced filters 2 | ======================== 3 | 4 | Sebastien Wains 5 | http://www.wains.be 6 | 7 | $Id: tcpdump_advanced_filters.txt 36 2013-06-16 13:05:04Z sw $ 8 | 9 | 10 | Notes : 11 | 12 | Basic syntax : 13 | ============== 14 | 15 | Filtering hosts : 16 | ----------------- 17 | 18 | - Match any traffic involving 192.168.1.1 as destination or source 19 | # tcpdump -i eth1 host 192.168.1.1 20 | 21 | - As soure only 22 | # tcpdump -i eth1 src host 192.168.1.1 23 | 24 | - As destination only 25 | # tcpdump -i eth1 dst host 192.168.1.1 26 | 27 | 28 | Filtering ports : 29 | ----------------- 30 | 31 | - Match any traffic involving port 25 as source or destination 32 | # tcpdump -i eth1 port 25 33 | 34 | - Source 35 | # tcpdump -i eth1 src port 25 36 | 37 | - Destination 38 | # tcpdump -i eth1 dst port 25 39 | 40 | 41 | Network filtering : 42 | ------------------- 43 | 44 | # tcpdump -i eth1 net 192.168 45 | # tcpdump -i eth1 src net 192.168 46 | # tcpdump -i eth1 dst net 192.168 47 | 48 | 49 | Protocol filtering : 50 | -------------------- 51 | 52 | # tcpdump -i eth1 arp 53 | # tcpdump -i eth1 ip 54 | 55 | # tcpdump -i eth1 tcp 56 | # tcpdump -i eth1 udp 57 | # tcpdump -i eth1 icmp 58 | 59 | 60 | Let's combine expressions : 61 | --------------------------- 62 | 63 | Negation : ! or "not" (without the quotes) 64 | Concatanate : && or "and" 65 | Alternate : || or "or" 66 | 67 | - This rule will match any TCP traffic on port 80 (web) with 192.168.1.254 or 192.168.1.200 as destination host 68 | # tcpdump -i eth1 '((tcp) and (port 80) and ((dst host 192.168.1.254) or (dst host 192.168.1.200)))' 69 | 70 | - Will match any ICMP traffic involving the destination with physical/MAC address 00:01:02:03:04:05 71 | # tcpdump -i eth1 '((icmp) and ((ether dst host 00:01:02:03:04:05)))' 72 | 73 | - Will match any traffic for the destination network 192.168 except destination host 192.168.1.200 74 | # tcpdump -i eth1 '((tcp) and ((dst net 192.168) and (not dst host 192.168.1.200)))' 75 | 76 | 77 | Advanced header filtering : 78 | =========================== 79 | 80 | Before we continue, we need to know how to filter out info from headers 81 | 82 | proto[x:y] : will start filtering from byte x for y bytes. ip[2:2] would filter bytes 3 and 4 (first byte begins by 0) 83 | proto[x:y] & z = 0 : will match bits set to 0 when applying mask z to proto[x:y] 84 | proto[x:y] & z !=0 : some bits are set when applying mask z to proto[x:y] 85 | proto[x:y] & z = z : every bits are set to z when applying mask z to proto[x:y] 86 | proto[x:y] = z : p[x:y] has exactly the bits set to z 87 | 88 | 89 | Operators : >, <, >=, <=, =, != 90 | 91 | 92 | This may not be clear in the first place but you'll find examples below involving these. 93 | 94 | 95 | Of course, it is important to know what the protocol headers look like before diving into more advanced filters. 96 | 97 | 98 | IP header 99 | --------- 100 | 101 | 0 1 2 3 102 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 103 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 104 | |Version| IHL |Type of Service| Total Length | 105 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 106 | | Identification |Flags| Fragment Offset | 107 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 108 | | Time to Live | Protocol | Header Checksum | 109 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 110 | | Source Address | 111 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 112 | | Destination Address | 113 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 114 | | Options | Padding | <-- optional 115 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 116 | | DATA ... | 117 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 118 | 119 | I'll consider we are only working with the IPv4 protocol suite for these examples. 120 | 121 | In an ideal world, every field would fit inside one byte. This is not the case, of course. 122 | 123 | Are IP options set ? 124 | -------------------- 125 | 126 | Let's say we want to know if the IP header has options set. We can't just try to filter out the 21st byte 127 | because if no options are set, data start at the 21st byte. We know a "normal" header is usually 20 bytes 128 | (160 bits) long. With options set, the header is longer than that. The IP header has the header 129 | length field which we will filter here to know if the header is longer than 20 bytes. 130 | 131 | +-+-+-+-+-+-+-+-+ 132 | |Version| IHL | 133 | +-+-+-+-+-+-+-+-+ 134 | 135 | Usually the first byte has a value of 01000101 in binary. 136 | 137 | Anyhow, we need to divide the first byte in half... 138 | 139 | 0100 = 4 in decimal. This is the IP version. 140 | 0101 = 5 in decimal. This is the number of blocks of 32 bits in the headers. 5 x 32 bits = 160 bits or 20 bytes. 141 | 142 | The second half of the first byte would be bigger than 5 if the header had IP options set. 143 | 144 | We have two ways of dealing with that kind of filters. 145 | 146 | 1. Either try to match a value bigger than 01000101. This would trigger matches for IPv4 traffic with IP options set, 147 | but ALSO any IPv6 traffic ! 148 | 149 | In decimal 01000101 equals 69. 150 | 151 | Let's recap how to calculate in decimal. 152 | 153 | 0 : 0 \ 154 | 1 : 2^6 = 64 \ First field (IP version) 155 | 0 : 0 / 156 | 0 : 0 / 157 | - 158 | 0 : 0 \ 159 | 1 : 2^2 = 4 \ Second field (Header length) 160 | 0 : 0 / 161 | 1 : 2^0 = 1 / 162 | 163 | 64 + 4 + 1 = 69 164 | 165 | The first field in the IP header would usually have a decimal value of 69. 166 | If we had IP options set, we would probably have 01000110 (IPv4 = 4 + header = 6), which in decimal equals 70. 167 | 168 | This rule should do the job : 169 | # tcpdump -i eth1 'ip[0] > 69' 170 | 171 | Somehow, the proper way is to mask the first half/field of the first byte, because as mentionned earlier, 172 | this filter would match any IPv6 traffic. 173 | 174 | 2. The proper/right way : "masking" the first half of the byte 175 | 176 | 0100 0101 : 1st byte originally 177 | 0000 1111 : mask (0xf in hex or 15 in decimal). 0 will mask the values while 1 will keep the values intact. 178 | ========= 179 | 0000 0101 : final result 180 | 181 | You should see the mask as a power switch. 1 means on/enabled, 0 means off/disabled. 182 | 183 | The correct filter : 184 | 185 | In binary 186 | # tcpdump -i eth1 'ip[0] & 15 > 5' 187 | 188 | or 189 | 190 | In hexadecimal 191 | # tcpdump -i eth1 'ip[0] & 0xf > 5' 192 | 193 | I use hex masks. 194 | 195 | Recap.. That's rather simple, if you want to : 196 | - keep the last 4 bits intact, use 0xf (binary 00001111) 197 | - keep the first 4 bits intact, use 0xf0 (binary 11110000) 198 | 199 | 200 | DF bit (don't fragment) set ? 201 | ----------------------------- 202 | 203 | Let's now trying to know if we have fragmentation occuring, which is not desirable. Fragmentation occurs 204 | when a the MTU of the sender is bigger than the path MTU on the path to destination. 205 | 206 | Fragmentation info can be found in the 7th and 8th byte of the IP header. 207 | 208 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 209 | |Flags| Fragment Offset | 210 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 211 | 212 | Bit 0: reserved, must be zero 213 | Bit 1: (DF) 0 = May Fragment, 1 = Don't Fragment. 214 | Bit 2: (MF) 0 = Last Fragment, 1 = More Fragments. 215 | 216 | The fragment offset field is only used when fragmentation occurs. 217 | 218 | If we want to match the DF bit (don't fragment bit, to avoid IP fragmentation) : 219 | 220 | The 7th byte would have a value of : 221 | 01000000 or 64 in decimal 222 | 223 | # tcpdump -i eth1 'ip[6] = 64' 224 | 225 | 226 | Matching fragmentation ? 227 | ------------------------ 228 | 229 | - Matching MF (more fragment set) ? This would match the fragmented datagrams but wouldn't match the last 230 | fragment (which has the 2nd bit set to 0). 231 | # tcpdump -i eth1 'ip[6] = 32' 232 | 233 | The last fragment have the first 3 bits set to 0... but has data in the fragment offset field. 234 | 235 | - Matching the fragments and the last fragments 236 | # tcpdump -i eth1 '((ip[6:2] > 0) and (not ip[6] = 64))' 237 | 238 | A bit of explanations : 239 | "ip[6:2] > 0" would return anything with a value of at least 1 240 | We don't want datagrams with the DF bit set though.. the reason of the "not ip[6] = 64" 241 | 242 | If you want to test fragmentation use something like : 243 | ping -M want -s 3000 192.168.1.1 244 | 245 | 246 | Matching datagrams with low TTL 247 | ------------------------------- 248 | 249 | The TTL field is located in the 9th byte and fits perfectly into 1 byte. 250 | The maximum decimal value of the TTL field is thus 255 (11111111 in binary). 251 | 252 | This can be verified : 253 | $ ping -M want -s 3000 -t 256 192.168.1.200 254 | ping: ttl 256 out of range 255 | 256 | +-+-+-+-+-+-+-+-+ 257 | | Time to Live | 258 | +-+-+-+-+-+-+-+-+ 259 | 260 | We can try to find if someone on our network is using traceroute by using something like this on the gateway : 261 | # tcpdump -i eth1 'ip[8] < 5' 262 | 263 | 264 | Matching packets longer than X bytes 265 | ------------------------------------ 266 | 267 | Where X is 600 bytes 268 | 269 | # tcpdump -i eth1 'ip[2:2] > 600' 270 | 271 | 272 | More IP filtering 273 | ----------------- 274 | 275 | We could imagine filtering source and destination addresses directly in decimal addressing. 276 | We could also match the protocol by filtering the 10th byte. 277 | 278 | It would be pointless anyhow, because tcpdump makes it already easy to filter out that kind of info. 279 | 280 | 281 | TCP header 282 | ---------- 283 | 284 | 0 1 2 3 285 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 286 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 287 | | Source Port | Destination Port | 288 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 289 | | Sequence Number | 290 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 291 | | Acknowledgment Number | 292 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 293 | | Data | |C|E|U|A|P|R|S|F| | 294 | | Offset| Res. |W|C|R|C|S|S|Y|I| Window | 295 | | | |R|E|G|K|H|T|N|N| | 296 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 297 | | Checksum | Urgent Pointer | 298 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 299 | | Options | Padding | 300 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 301 | | data | 302 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 303 | 304 | - Matching any TCP traffic with a source port > 1024 305 | # tcpdump -i eth1 'tcp[0:2] > 1024' 306 | 307 | - Matching TCP traffic with particular flag combinations 308 | 309 | The flags are defined in the 14th byte of the TCP header. 310 | 311 | +-+-+-+-+-+-+-+-+ 312 | |C|E|U|A|P|R|S|F| 313 | |W|C|R|C|S|S|Y|I| 314 | |R|E|G|K|H|T|N|N| 315 | +-+-+-+-+-+-+-+-+ 316 | 317 | In the TCP 3-way handshakes, the exchange between hosts goes like this : 318 | 319 | 1. Source sends SYN 320 | 2. Destination answers with SYN, ACK 321 | 3. Source sends ACK 322 | 323 | - If we want to match packets with only the SYN flag set, the 14th byte would have a binary 324 | value of 00000010 which equals 2 in decimal. 325 | # tcpdump -i eth1 'tcp[13] = 2' 326 | 327 | - Matching SYN, ACK (00010010 or 18 in decimal) 328 | # tcpdump -i eth1 'tcp[13] = 18' 329 | 330 | - Matching either SYN only or SYN-ACK datagrams 331 | # tcpdump -i eth1 'tcp[13] & 2 = 2' 332 | 333 | We used a mask here. It will returns anything with the ACK bit set (thus the SYN-ACK combination as well) 334 | 335 | Let's assume the following examples (SYN-ACK) 336 | 337 | 00010010 : SYN-ACK packet 338 | 00000010 : mask (2 in decimal) 339 | -------- 340 | 00000010 : result (2 in decimal) 341 | 342 | Every bits of the mask match ! 343 | 344 | - Matching PSH-ACK packets 345 | # tcpdump -i eth1 'tcp[13] = 24' 346 | 347 | - Matching any combination containing FIN (FIN usually always comes with an ACK so we either 348 | need to use a mask or match the combination ACK-FIN) 349 | # tcpdump -i eth1 'tcp[13] & 1 = 1' 350 | 351 | - Matching RST flag 352 | # tcpdump -i eth1 'tcp[13] & 4 = 4' 353 | 354 | Actually, there's an easier way to filter flags : 355 | # tcpdump -i eth1 'tcp[tcpflags] == tcp-ack' 356 | 357 | - Matching all packages with TCP-SYN or TCP-FIN set : 358 | # tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 359 | 360 | 361 | By looking at the TCP state machine diagram (http://www.wains.be/pub/networking/tcp_state_machine.jpg) 362 | we can find the different flag combinations we may want to analyze. 363 | 364 | Ideally, a socket in ACK_WAIT mode should not have to send a RST. It means the 3 way handshake has not completed. 365 | We may want to analyze that kind of traffic. 366 | 367 | 368 | Matching SMTP data : 369 | -------------------- 370 | 371 | I will make a filter that will match any packet containing the "MAIL" command from SMTP exchanges. 372 | 373 | I use something like http://www.easycalculation.com/ascii-hex.php to convert values from ASCII to hexadecimal. 374 | 375 | "MAIL" in hex is 0x4d41494c 376 | 377 | The rule would be : 378 | 379 | # tcpdump -i eth1 '((port 25) and (tcp[20:4] = 0x4d41494c))' 380 | 381 | It will check the bytes 21 to 24. "MAIL" is 4 bytes/32 bits long.. 382 | 383 | This rule would not match packets with IP options set. 384 | 385 | This is an example of packet (a spam, of course) : 386 | 387 | # tshark -V -i eth0 '((port 25) and (tcp[20:4] = 0x4d41494c))' 388 | Capturing on eth0 389 | Frame 1 (92 bytes on wire, 92 bytes captured) 390 | Arrival Time: Sep 25, 2007 00:06:10.875424000 391 | [Time delta from previous packet: 0.000000000 seconds] 392 | [Time since reference or first frame: 0.000000000 seconds] 393 | Frame Number: 1 394 | Packet Length: 92 bytes 395 | Capture Length: 92 bytes 396 | [Frame is marked: False] 397 | [Protocols in frame: eth:ip:tcp:smtp] 398 | Ethernet II, Src: Cisco_X (00:11:5c:X), Dst: 3Com_X (00:04:75:X) 399 | Destination: 3Com_X (00:04:75:X) 400 | Address: 3Com_X (00:04:75:X) 401 | .... ...0 .... .... .... .... = IG bit: Individual address (unicast) 402 | .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) 403 | Source: Cisco_X (00:11:5c:X) 404 | Address: Cisco_X (00:11:5c:X) 405 | .... ...0 .... .... .... .... = IG bit: Individual address (unicast) 406 | .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) 407 | Type: IP (0x0800) 408 | Internet Protocol, Src: 62.163.X (62.163.X), Dst: 192.168.X (192.168.X) 409 | Version: 4 410 | Header length: 20 bytes 411 | Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00) 412 | 0000 00.. = Differentiated Services Codepoint: Default (0x00) 413 | .... ..0. = ECN-Capable Transport (ECT): 0 414 | .... ...0 = ECN-CE: 0 415 | Total Length: 78 416 | Identification: 0x4078 (16504) 417 | Flags: 0x04 (Don't Fragment) 418 | 0... = Reserved bit: Not set 419 | .1.. = Don't fragment: Set 420 | ..0. = More fragments: Not set 421 | Fragment offset: 0 422 | Time to live: 118 423 | Protocol: TCP (0x06) 424 | Header checksum: 0x08cb [correct] 425 | [Good: True] 426 | [Bad : False] 427 | Source: 62.163.X (62.163.X) 428 | Destination: 192.168.X (192.168.XX) 429 | Transmission Control Protocol, Src Port: 4760 (4760), Dst Port: smtp (25), Seq: 0, Ack: 0, Len: 38 430 | Source port: 4760 (4760) 431 | Destination port: smtp (25) 432 | Sequence number: 0 (relative sequence number) 433 | [Next sequence number: 38 (relative sequence number)] 434 | Acknowledgement number: 0 (relative ack number) 435 | Header length: 20 bytes 436 | Flags: 0x18 (PSH, ACK) 437 | 0... .... = Congestion Window Reduced (CWR): Not set 438 | .0.. .... = ECN-Echo: Not set 439 | ..0. .... = Urgent: Not set 440 | ...1 .... = Acknowledgment: Set 441 | .... 1... = Push: Set 442 | .... .0.. = Reset: Not set 443 | .... ..0. = Syn: Not set 444 | .... ...0 = Fin: Not set 445 | Window size: 17375 446 | Checksum: 0x6320 [correct] 447 | [Good Checksum: True] 448 | [Bad Checksum: False] 449 | Simple Mail Transfer Protocol 450 | Command: MAIL FROM:\r\n 451 | Command: MAIL 452 | Request parameter: FROM: 453 | 454 | 455 | Matching HTTP data : 456 | -------------------- 457 | 458 | Let's make a filter that will find any packets containing GET requests 459 | The HTTP request will begin by : 460 | 461 | GET / HTTP/1.1\r\n (16 bytes counting the carriage return but not the backslashes !) 462 | 463 | If no IP options are set.. the GET command will use the byte 20, 21 and 22 464 | Usually, options will take 12 bytes (12nd byte indicates the header length, which should report 32 bytes). 465 | So we should match bytes 32, 33 and 34 (1st byte = byte 0). 466 | 467 | Tcpdump is only able to match data size of either 1, 2 or 4 bytes, we will take the following ASCII 468 | character following the GET command (a space) 469 | 470 | "GET " in hex : 47455420 471 | 472 | # tcpdump -i eth1 'tcp[32:4] = 0x47455420' 473 | 474 | 475 | Matching HTTP data (exemple taken from tcpdump man page) : 476 | 477 | # tcpdump -i eth1 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' 478 | 479 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 480 | ip[2:2] = | Total Length | 481 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 482 | 483 | +-+-+-+-+-+-+-+-+ 484 | ip[0] = |Version| IHL | 485 | +-+-+-+-+-+-+-+-+ 486 | 487 | +-+-+-+-+-+-+-+-+ 488 | ip[0]&0xf = |# # # #| IHL | <-- that's right, we masked the version bits with 0xf or 00001111 in binary 489 | +-+-+-+-+-+-+-+-+ 490 | 491 | +-+-+-+-+ 492 | | Data | 493 | tcp[12] = | Offset| 494 | | | 495 | +-+-+-+-+ 496 | 497 | So what we are doing here is "(IP total length - IP header length - TCP header length) != 0" 498 | 499 | We are matching any packet that contains data. 500 | 501 | 502 | We are taking the IHL (total IP lenght 503 | 504 | 505 | Matching other interesting TCP things : 506 | --------------------------------------- 507 | 508 | SSH connection (on any port) : 509 | We will be looking for the reply given by the SSH server. 510 | OpenSSH usually replies with something like "SSH-2.0-OpenSSH_3.6.1p2". 511 | The first 4 bytes (SSH-) have an hex value of 0x5353482D. 512 | 513 | # tcpdump -i eth1 'tcp[(tcp[12]>>2):4] = 0x5353482D' 514 | 515 | If we want to find any connection made to older version of OpenSSH (version 1, which are insecure and subject to MITM attacks) : 516 | The reply from the server would be something like "SSH-1.99.." 517 | 518 | # tcpdump -i eth1 '(tcp[(tcp[12]>>2):4] = 0x5353482D) and (tcp[((tcp[12]>>2)+4):2] = 0x312E)' 519 | 520 | Explanation of >>2 can be found below in the reference section. 521 | 522 | 523 | UDP header 524 | ---------- 525 | 526 | 0 7 8 15 16 23 24 31 527 | +--------+--------+--------+--------+ 528 | | Source | Destination | 529 | | Port | Port | 530 | +--------+--------+--------+--------+ 531 | | | | 532 | | Length | Checksum | 533 | +--------+--------+--------+--------+ 534 | | | 535 | | DATA ... | 536 | +-----------------------------------+ 537 | 538 | Nothing really interesting here. 539 | 540 | If we want to filter ports we would use something like : 541 | # tcpdump -i eth1 udp dst port 53 542 | 543 | 544 | ICMP header 545 | ----------- 546 | 547 | See different ICMP messages : 548 | http://img292.imageshack.us/my.php?image=icmpmm6.gif 549 | 550 | We will usually filter the type (1 byte) and code (1 byte) of the ICMP messages. 551 | 552 | Here are common ICMP types : 553 | 554 | 0 Echo Reply [RFC792] 555 | 3 Destination Unreachable [RFC792] 556 | 4 Source Quench [RFC792] 557 | 5 Redirect [RFC792] 558 | 8 Echo [RFC792] 559 | 11 Time Exceeded [RFC792] 560 | 561 | We may want to filter ICMP messages type 4, these kind of messages are sent in case of congestion of the network. 562 | # tcpdump -i eth1 'icmp[0] = 4' 563 | 564 | 565 | If we want to find the ICMP echo replies only, having an ID of 500. By looking at the image with all the ICMP packet description 566 | we see the ICMP echo reply have the ID spread across the 5th and 6th byte. For some reason, we have to filter out with the value in hex. 567 | 568 | # tcpdump -i eth0 '(icmp[0] = 0) and (icmp[4:2] = 0x1f4)' 569 | 570 | 571 | References 572 | ---------- 573 | 574 | tcpdump man page : http://www.tcpdump.org/tcpdump_man.html 575 | Conversions : http://easycalculation.com/hex-converter.php 576 | Filtering HTTP requests : http://www.wireshark.org/tools/string-cf.html 577 | Filtering data regardless of TCP options : http://www.wireshark.org/lists/wireshark-users/201003/msg00024.html 578 | 579 | Just in case the post disappears, here's a copy of the last URL : 580 | 581 | From: Sake Blok 582 | Date: Wed, 3 Mar 2010 22:42:29 +0100 583 | Or if your capturing device is capable of interpreting tcpdump style filters (or more accurately, BPF style filters), you could use: 584 | 585 | tcp[(((tcp[12:1] & 0xf0) >> 2) + 8):2] = 0x2030 586 | 587 | Which in English would be: 588 | - take the upper 4 bits of the 12th octet in the tcp header ( tcp[12:1] & 0xf0 ) 589 | - multiply it by four ( (tcp[12:1] & 0xf0)>>2 ) which should give the tcp header length 590 | - add 8 ( ((tcp[12:1] & 0xf0) >> 2) + 8 ) gives the offset into the tcp header of the space before the first octet of the response code 591 | - now take two octets from the tcp stream, starting at that offset ( tcp[(((tcp[12:1] & 0xf0) >> 2) + 8):2] ) 592 | - and verify that they are " 0" ( = 0x2030 ) 593 | 594 | Of course this can give you false positives, so you might want to add a test for "HTTP" and the start of the tcp payload with: 595 | 596 | tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x48545450 597 | 598 | resulting in the filter: 599 | 600 | tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x48545450 and tcp[(((tcp[12:1] & 0xf0) >> 2) + 8):2] = 0x2030 601 | 602 | A bit cryptic, but it works, even when TCP options are present (which would mess up a fixed offset into the tcp data). 603 | 604 | --------------------------------------------------------------------------------