Filtrare in base al protocollo
Per filtrare in base al protocollo, nell'espressione infiliamo semplicemente tcp, udp, icmp.
Filtrare in base alle porte
- port <porta> filtra solo i pacchetti riguardanti la porta specificata
- portrange 10-1000' filtra solo i pacchetti riguardanti il range di porte specificato
- src port <porta> e dst port <porta> fanno esattamente quello che suggeriscono
- src portrange a-b e dst portrange a-b idem
Filtri sul contenuto binario (leggi FLAG)
Qui si va un po' più nel complicato. Possiamo avere l'esigenza di filtrare certi pacchetti in base a come hanno i flag settati. Per dirlo a tcpdump, occorre fare un filtraggio sul contenuto binario.
Consideriamo l'header TCP. Esso è composto da 20 byte, con il primo numerato a partire da 0. I flag si trovano nel 13° byte, e hanno un bit a testa. Se guardiamo il byte che contiene i flag, le associazioni tra bit e flag sono le seguenti:
<no> <no> URG ACK PSH RST SYN FIN
I primi 2 bit sono riservati e non si usano. Quando si settano i flag, si portano a 1 i relativi bit. Ad esempio, per avere SYN e ACK settati, avremmo il 13° byte con questa forma:
00010010
il che, in decimale, si traduce con 21 + 24 = 18.
Se invece vogliamo i flag URG, SYN e FIN, avremmo
00100011
Ok che questa combinazione di flag è un po' strana, però sarebbe 20 + 21 + 25 = 35.
Per dire a tcpdump di fare questo tipo di controlli, usiamo l'espressione tcp[numerobyte] = <valore>. Ad esempio, tcp[13] = 35 controllerà URG, SYN e FIN.
Ma tutto questo NON basta. Il controllo fatto qui sopra dice: controlla che i flag siano solo ed esclusivamente quelli. Se controllo quelli con il flag SYN, vuol dire che tutti quelli che hanno il SYN sì settato, ma anche qualcos'altro, non vengono considerati.
Entrano quindi in gioco le maschere binarie. Per vedere che cosa sono, occorre sapere che cosa sia l'AND logico. Ecco due esempi chiarificatori:
1) 01010101 AND
00000100 =
--------
00000100
2) 01010101 AND
00000010 =
--------
00000000
Basta fare l'AND bit a bit, e si ottiene il risultato. Come è noto, solo 1 AND 1 = 1. E a che cosa ci serve? Ecco a cosa ci serve:
01010101 AND
00000100 =
--------
00000100
00000100 AND
00000100 =
--------
00000100
11111111 AND
00000100 =
--------
00000100
Dovrebbe essere autoesplicativo: se sto controllando un singolo bit, non mi importa che cosa valgano gli altri, perché il risultato dell'AND dipende SOLO da quel bit. Quindi, tornando alla nostra voglia di filtrare tutti i pacchetti che hanno sicuramente il SYN settato, e degli altri bit va bene qualsiasi cosa, noi potremmo dire a tcpdump una cosa così: tcp[13] & 2 != 0, che tradotto vuol dire:
- fai l'AND bit a bit tra il 13°
guerriero byte e 2 in binario
- il risultato è diverso da 0? Bene! Se no scartalo.
ACHTUNG!
Per evitare cose strane con i caratteri & etc., che la shell può interpretare come vuole, è meglio mettere questo tipo di filtri tra le virgolette, per avere una cosa come
tcpdump -n -i eth0 "tcp[13] & 2 != 0 or tcp[13] & 16 != 0" -r file.dump
Notiamo anche che abbiamo combinato più condizioni con l'operatore logico OR. Ci sono anche gli AND etc.
Filtro binario su più byte
Qui vogliamo arrivare al massimo della figosità. Possiamo dire a tcpdump cose del genere:
tcp[0:2] = 80
e quello che fa è controllare i byte che partono da 0. Quanti ne controlla? 2, perché glielo abbiamo detto noi. Ad esempio, tcp[6:4] controlla i byte 6, 7, 8 e 9, cioè 4 a partire da 6.
Sta roba serve per andare a controllare altre cose dell'header tcp, ad esempio i flag di frammentazione e roba del genere.