Dzięki Wireshark możemy analizować dane pobrane z sieci. Czasem jednak plik .pcap, który musimy poddać analizie może być bardzo duży. Może to wynikać z tego, że niepoprawnie zbieraliśmy zbyt dużo danych i nie ustawiliśmy odpowiednich filtrów już na etapie zbierania. Inna przyczyna to fakt, że zbieraliśmy wszystko, gdyż nie do końca wiedzieliśmy, jakie dane mogą nam być przydatne do analizy naszego problemu. W programie znajdziemy na szczęście bardzo wiele funkcji filtrowania jak i analityki zebranych danych, w tym śledzenia komunikacji wskazanych urządzeń. Możliwości filtrowania są bardzo potężne i złożone, jest tak wiele pól, operatorów i opcji, że ich kombinacja staje się przytłaczająca. Podstawy filtrowania musi jednak znać każdy inżynier sieciowy czy systemowy.

Proste filtry wyświetlania

Filtry definiujemy w polu wyrażeń regularnych, które znajduje się w górnej części okna aplikacji. Najprostszy filtr wyświetlania to taki, który wyświetla pojedynczy protokół. Aby wyświetlić tylko pakiety zawierające określony protokół wystarczy, że wpiszemy nazwę protokołu w pasku narzędzi filtra wyświetlania. Na przykład, aby wyświetlić tylko pakiety TCP, wpiszemy tcp. Podobnie, aby wyświetlić tylko pakiety IP wystarczy, że wpiszemy ip. Możemy w ten sposób także filtrować protokoły warstw wyższych. Bardzo często chcemy filtrować jedynie połączenia HTTP, FTP czy SIP. Możemy w tym celu posłużyć się portami charakterystycznymi dla danego protokołu, o czym za chwilę, albo po prostu wpisać jego nazwę. W naszym przykładzie wystarczy że wpiszemy odpowiednio http, ftp albo sip.

Budując filtry korzystając z naszego protokołu możemy także filtrować rekordy, biorąc pod uwagę specyfikę danego protokołu. Przykładowo jeżeli chcemy wyświetlić w komunikacji protokołu HTTP jedynie żądania (HTTP REQUEST) w polu filtra musimy wpisać http.request. Jak można zauważyć, sposób konstruowania filtrów przypomina trochę programowanie obiektowe, w których odwołujemy się do pól charakterystycznych dla obiektu danego typu. Na szczęście nie musimy uczyć się wszystkiego na pamięć. Edytując filtr bezpośrednio w polu paska narzędzi filtra program sam będzie nam podpowiadał możliwe obiekty. W rzeczywistości rzadko się zdarza, że odwołujemy się jedynie do protokołów budując filtry, staramy się odnosić do jego specyficznych elementów, dlatego też warto znać podstawy działania każdego z protokołów, których działanie będziemy filtrować i analizować.

Porównywanie wartości

Budując filtry bardzo często będziemy posługiwali się wyrażeniami regularnymi, w szczególności tymi, które odnoszą się do porównywania różnych wartości. Możemy tworzyć filtry wyświetlania, które porównują wartości przy użyciu wielu różnych operatorów. Przykładowo, jeżeli chcemy wyświetlić jedynie rekordy, w których w polu nadawcy lub odbiorcy pakietu IP znajduje się adres 192.168.0.1 wystarczy, że zdefiniujemy filtr ip.addr == 192.168.0.1. Operator == (ang. equal) wskazuje, że poszukujemy jedynie rekordów. które spełniają zadaną przez nas wartość. Wyszukiwanie po adresach IP możemy jeszcze dodatkowo zawęzić szukając wskazanego adresu tylko w polu nadawcy (ip.src == 192.168.0.1) lub tylko w polu odbiorcy (ip.src == 192.168.0.1). W identyczny sposób możemy skorzystać z operatora != (non-equal), wykluczając rekordy dla których spełniona jest zależność z wyświetlania. Na przykład, aby odfiltrować pakiety zawierające adres 192.168.0.1 wystarczy, że jako filtr wyświetlania ustawimy ip.addr == 192.168.0.1.

Nieco więcej matematycznych możliwości operowania na wartościach mamy operując na numerach portów, długościach pakietów czy innych numerycznych wartościach. Oprócz operatora == możemy także określać przedziały poszukiwanych wartości. Mogą to być zarówno przedziały otwarte jak i zamknięte. Na przykład filtr tcp.dstport > 25670 oznacza numery portów docelowych połączenia TCP większe od 25670. Natomiast filtr tcp.dstport >= 25670 wyświetli nam rekordy, które docelowy port połączenia jest większy bądź równy 25670. W jaki sposób możemy zatem wyświetlić jedynie rekordy, w których port docelowy połączenia jest równy 25670? Na dwa sposoby. Pierwszy to skorzystanie z operatora == dzięki, któremu zdefiniujemy filtr tcp.dstport == 25670. Możemy również wyświetlić wartość za pomocą logicznego operatora łączenia (operator AND) i złączyć ze sobą dwa filtry tcp.dstport >= 25672 && tcp.dstport  <= 25672.

Filtrowanie złożone

Jak już wcześniej wspomniałem filtrowanie dostępne w Wireshark może odnosić się do specyficznych wartości przenoszonych w poszczególnych polach analizowanego protokołu. Przydatny w takiej sytuacji będzie dla nas szczególnie operator contains, za pomocą którego szukamy ciągu znaków, który musi znaleźć się w analizowanym polu. Może on znajdować się zarówno na początku, na końcu lub gdziekolwiek w środku zawartości analizowanego pola. Jeżeli szukamy rekordów w protokole SIP odnoszących się do dzwonienia na numery telefoniczne z polski i wiemy, że numer telefonu zapisany jest jako nazwa użytkownika w polu To, to możemy do tego celu użyć filtra sip.To contains „+48”. Oczywiście musimy wiedzieć, że numer telefonu w analizowanych danych zapisanych jest jako „+48” a nie „0048”. Pamiętajmy także, że poszukiwaną wartość traktujemy jako ciąg znaków przysięgę dlatego musimy zapisać ją w cudzysłowem.

Innym, często używanym złożonym filtrowaniem wyszukujemy w protokole HTTP połączeń, do określonej domeny lub grupy domen. Załóżmy, że poszukujemy połączeń do domeny, która zaczyna się od słów „mojasiec”, ale nie wiemy czy adres ma zakończenie „.net”, „.com”, czy ”.pl”. Zamiast kolejno wpisywać wszystkie kombinacje adresów możemy zbudować jeden filtr http.host matches „mojasiec\\.(net|com|pl)”. Na takich złożonych filtrach operujemy operatorami logicznymi tak, jak w logice matematycznej. Już wcześniej zastosowaliśmy logiczny operator AND. W tym filtrze w nawiasach pomiędzy operatorami ( i ) umieszczone są wartości, które mają zostać oddzielnie sprawdzone. Operator | (ang. OR) to logiczny operator rozdzielności. Podwójny znak \\ jest niezbędny, aby znak . (kropka) traktować jako znak w ciągu, a nie znak specjalny w filtrze.

Innym ciekawym i często stosowanym filtrem jest operator przynależności do zbioru. Załóżmy, że znamy listę potencjalnych wartości portów połączenia TCP i chcemy wyświetlić jedynie te, których port źródłowy lub docelowy zawierają się w znanym nam zbiorze. Przykładowo, taki zbiór mogą tworzyć porty 80 i 443 odnoszące się do połączeń ze stronami www. W takiej sytuacji nasz filtr możemy zapisać jako tcp.port == 80 || tcp.port == 443 lub alternatywnie jako tcp.port in {80, 443}. Drugi ze sposobów daje nam elastyczniejsze możliwości operowania na zakresach zbiorów. Zapis tcp.port in {80, 443..445} oznacza, że analizowana wartość numeryczna portu musi wynosić 80 lub zawierać się w przedziale od 443 do 445 włącznie. W podobny, wygodny sposób oznaczać możemy zbiory zawierające adresy IP: ip.addr in {192.168.0.1 .. 192.168.0.10, 192.168.1.1..192.168.1.10}.