У другій частині розглядаються практичні інструменти аналізу трафіку та мережевої діагностики. Матеріал пояснює принципи побудови Ethernet-мосту, використання фільтрів BPF, роботу з tcpdump і tshark, а також можливості системи виявлення атак Snort. Текст допомагає сформувати цілісне розуміння того, як застосовувати FreeBSD для глибокого контролю мережі та безпеки без переходу до технічних деталей, які розкриті вже у самій статті.
В ОС FreeBSD підняти мережний міст можна між будь-яким числом мережевих інтерфейсів, більше того, вони не обов’язково мають бути типу Ethernet. Але нас у даному контексті цікавить міст із двох вбудованих Etherent портів, які видаються під певними іменами. Щоб з’ясувати які мережеві інтерфейси є в системі, скористаємося системною утилітою ifconfig , введемо команду:
sniffer@sniffer:~ % ifconfig -l re0 re1 lo0 wlan0 ng0
В результаті отримаємо простий список імен розділених пробілом інтерфейсів. У разі інтерфейси re0 і re1 це і є Ethernet порти. Більш детально інформацію про них можна отримати також за допомогою ifconfig :
sniffer@sniffer:~ % ifconfig re0
re0: flags=8902<BROADCAST,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=8209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE>
ether 68:1d:ef:47:de:0a
media: Ethernet autoselect (none)
status: no carrier
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
sniffer@sniffer:~ % ifconfig re1
re1: flags=8902<BROADCAST,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=8209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE>
ether 68:1d:ef:47:de:0b
media: Ethernet autoselect (none)
status: no carrier
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
Утиліта ifconfig відображає великий обсяг різної інформації про мережний інтерфейс, серед якої нас може зацікавити MAC адресу ( ether 68:1d:ef:47:de:0 і ether 68:1d:ef:47:de:0b ), а також наявність з’єднання з комутатором або іншим пристроєм ( status: no несучої частоти»).
Інформацію про те, як налаштувати Brigding (мережевий міст), можна легко отримати з вбудованого системного керівництва. Давайте заглянемо в нього, ввівши наступну команду:
sniffer@sniffer:~ % man bridge
IF_BRIDGE(4) FreeBSD Kernel Interfaces Manual IF_BRIDGE(4)
NAME
if_bridge – network bridge device
SYNOPSIS
To compile this driver into the kernel, place the following line in your
kernel configuration file:
device if_bridge
Alternatively, to load the driver as a module at boot time, place the
following lines in loader.conf(5):
if_bridge_load="YES"
bridgestp_load="YES"
DESCRIPTION
The if_bridge driver creates a logical link between two or more IEEE 802
networks that use the same (or “similar enough”) framing format. For
example, it is possible to bridge Ethernet and 802.11 networks together,
but it is not possible to bridge Ethernet and Token Ring together.
На першій сторінці керівництва нам пропонується додати два системних модуля (драйвера) в конфігураційний файл завантажувача /boot/loader.conf . Зробити це можна за допомогою утиліти sysrc , вказавши після ключа -f ім’я конфігураційного файлу:
sniffer@sniffer:~ % sudo sysrc -f /boot/loader.conf if_bridge_load="YES" Password: reffins if_bridge_load: -> YES sniffer@sniffer:~ % sudo sysrc -f /boot/loader.conf bridgestp_load="YES" bridgestp_load: -> YES
Перший драйвер, if_bridge , що продає потрібний нам функціонал мережного мосту. Другий драйвер, bridgestp , реалізує протокол Rapid Spanning Tree Protocol ( RSTP, 802.1w ) для мостового з’єднання, що дозволяє уникнути випадкових «зациклювань» у структурі Ethernet мережі.
Наступний етап – це власне створення мосту. У тому ж системному посібнику ( man bridge ) читаємо далі і бачимо, що для того, щоб у системі з’явився мережевий міст, необхідно додати наступні рядки в /etc/rc.conf :
EXAMPLES
The following when placed in the file /etc/rc.conf will cause a bridge
called “bridge0” to be created, and will add the interfaces “wlan0” and
“fxp0” to the bridge, and then enable packet forwarding. Such a
configuration could be used to implement a simple 802.11-to-Ethernet
bridge (assuming the 802.11 interface is in ad-hoc mode).
cloned_interfaces="bridge0"
...
For the bridge to forward packets, all member interfaces and the bridge
need to be up. The above example would also require:
...
ifconfig_bridge0="addm em0 addm em1 DHCP"
ifconfig_em0="up"
ifconfig_em1="up"
Наведений приклад створює новий інтерфейс bridge0 і додає до нього інтерфейси wlan0, fxp0, em0 та em1. У разі ці додаткові (вхідні) інтерфейси слід замінити на re0 і re1 . Параметр DHCP у налаштуванні bridge0 вказує на те, що міст працюватиме навіть як звичайний мережний інтерфейс, IP адреса на нього буде запитуватися у DHCP сервера. Це дуже корисна властивість мосту дозволить нам використовувати його як підлягаючий транспорт для mpd5 утиліти для організації зворотного тунелю. Підсумовуючи все вище сказане, отримаємо наступний список команд для налаштування мережевого мосту:
sniffer@sniffer:~ % sudo sysrc cloned_interfaces="bridge0" cloned_interfaces: -> bridge0 sniffer@sniffer:~ % sudo sysrc ifconfig_bridge0="addm re0 addm re1 SYNCDHCP" ifconfig_bridge0: -> addm re0 addm re1 SYNCDHCP sniffer@sniffer:~ % sudo sysrc ifconfig_re0="up" ifconfig_re0: -> up sniffer@sniffer:~ % sudo sysrc ifconfig_re1="up" ifconfig_re1: -> up
І, втім, все. Тепер нам потрібно перезавантажити операційну систему, щоб завантажилися два нові драйвери. Зробимо це командою reboot :
sniffer@sniffer:~ % sudo reboot Connection to 192.168.171.151 closed.
Відразу після введення цієї команди з’єднання SSH буде розірвано і машина піде на перезавантаження. За хвилину ми знову зможемо підключитися до неї командою ssh .
Підключимося до системи і подивимося як виглядає створений нами мережний інтерфейс bridge0 , ще раз скориставшись утилітою ifconfig :
sniffer@sniffer:~ % ifconfig bridge0
bridge0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
options=0
ether 58:9c:fc:10:ff:d7
id 00:00:00:00:00:00 priority 32768 hellotime 2 fwddelay 15
maxage 20 holdcnt 6 proto rstp maxaddr 2000 timeout 1200
root id 00:00:00:00:00:00 priority 32768 ifcost 0 port 0
member: re1 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP>
ifmaxaddr 0 port 2 priority 128 path cost 55
member: re0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP>
ifmaxaddr 0 port 1 priority 128 path cost 55
groups: bridge
nd6 options=9<PERFORMNUD,IFDISABLED>
Тут ми бачимо, що bridge0 містить два інші інтерфейси-учасники: member: re0 та member: re1 .
Після створення мережевого моста необхідно перевірити його роботу. Для цього сніфер слід підключити між досліджуваним хостом або мережевим пристроєм та основною мережею. Досліджуваний пристрій надалі позначається як DUT (Device Under Test).
Найпростішим прикладом для перевірки може слугувати офісний мережевий принтер — наприклад, HP LaserJet Pro 500. Для підключення використовується додатковий UTP патчкорд: ним DUT з’єднується з першим Ethernet-портом сніфера. Другим патчкордом, який раніше підключав принтер до комутатора, тепер з’єднується другий Ethernet-порт сніфера з офісним комутатором.
Через кілька секунд індикатори на портах починають активно блимати, що свідчить про проходження трафіку через міст. Команда ifconfig у такому разі відображає оновлену інформацію про стан інтерфейсів:
sniffer@sniffer:~ % ifconfig re0
re0: flags=1008943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
options=8209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE>
ether 68:1d:ef:47:de:0a
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
sniffer@sniffer:~ % ifconfig re1
re1: flags=1008943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
options=8209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE>
ether 68:1d:ef:47:de:0b
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
З висновку команди ми бачимо, що обидва інтерфейси re0 і re1 перейшли в робочий стан: на обох інтерфейсах висвітлюється status: active і до списку прапорів додався прапор UP .
Спробуємо підслухати трафік ICMP на мостовому з’єднанні за допомогою системної утиліти tcpdump . Вона до речі, входить у стандартне постачання ОС FreeBSD, тобто нічого встановлювати не потрібно.
Введемо команду:
sniffer@sniffer:~ % sudo tcpdump -i bridge0 icmp Password: reffins tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on bridge0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
Утиліта tcpdump запущена і слухає трафік мережі на мостовому з’єднанні, вибираючи з нього тільки ICMP пакети, про що говорить рядок icmp , що задає правило фільтрації (про правила ми поговоримо докладніше далі).
Далі відкриваємо нове вікно терміналу на робочому комп’ютері та вводжу команду ping :
rz@butterfly:~ % ping 192.168.169.14 PING 192.168.169.14 (192.168.169.14): 56 data bytes 64 bytes from 192.168.169.14: icmp_seq=0 ttl=254 time=4.501 ms 64 bytes from 192.168.169.14: icmp_seq=1 ttl=254 time=3.283 ms 64 bytes from 192.168.169.14: icmp_seq=2 ttl=254 time=5.427 ms ^C --- 192.168.169.14 ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 3.283/4.404/5.427/0.878 ms
Команда ping надсилає ICMP-запити на хост із указаною IP-адресою. У цьому прикладі адреса 192.168.169.14 відповідає офісному МФУ. Після надсилання декількох пакетів роботу ping можна перервати комбінацією Ctrl-C. Паралельно, у терміналі з підключенням через SSH до сніфера одразу з’являються повідомлення від утиліти tcpdump, які фіксують проходження ICMP-трафіку через міст:
20:20:36.309894 IP 192.168.176.155 > 192.168.169.14: ICMP echo request, id 63017, seq 0, length 64 20:20:36.310397 IP 192.168.169.14 > 192.168.176.155: ICMP echo reply, id 63017, seq 0, length 64 20:20:37.373156 IP 192.168.176.155 > 192.168.169.14: ICMP echo request, id 63017, seq 1, length 64 20:20:37.373573 IP 192.168.169.14 > 192.168.176.155: ICMP echo reply, id 63017, seq 1, length 64 20:20:38.437588 IP 192.168.176.155 > 192.168.169.14: ICMP echo request, id 63017, seq 2, length 64 20:20:38.437957 IP 192.168.169.14 > 192.168.176.155: ICMP echo reply, id 63017, seq 2, length 64
Для зупинки роботи tcpdump використовується комбінація Ctrl-C. Після її натискання відбувається повернення в оболонку tcsh, а перед завершенням утиліта виводить коротку статистику про зібраний трафік та параметри фіксації, що відбувався:
^C 6 packets captured 365 packets received by filter 0 packets dropped by kernel sniffer@sniffer:~ %
З повідомлень tcpdump ми бачимо, що через інтерфейс цей час пройшло багато пакетів, але правилам фільтра відповідало всього 6 пакетів. Інформацію про ці шість пакетів утиліта tcpdump вивела раніше, це три пари пакетів: типу ICMP echo request від 92.168.176.155 > 192.168.169.14 (до МФУ від мого робочого ПК), і типу ICMP ech6 rep1. 192.168.176.155 (відповідь від БФП). Очевидно, що tcpdump тепер може підглядати будь-який трафік через міст, як у бік МФУ, так і від нього в бік мережі. Далі ми трохи докладніше вивчимо роботу tcpdump та деяких інших утиліт для аналізу трафіку, а також ознайомимося з правилами фільтрації, що надаються вбудованим в ОС засобом під назвою Berkeley Packet Filter (BPF).
Перед тим, як перейти до опису способів аналізу трафіку, розглянемо кілька варіантів включення сніфера. Взагалі, способів включення сніфера може бути дуже багато, залежать вони від структури мережі, що експлуатується, і від способу організації керуючого каналу для доступу до сніфера. Нижче на мал. 8а, 8б, 8в і 8г наведено чотири способи включення сніфера в мережу, всі вони досить прості незважаючи на деяку захаращеність зображень. Розглянемо всі чотири варіанти.
Найпростіша схема включення сніфера (мал. 8а) полягає в тому, щоб підключити його в розріз між досліджуваним пристроєм (DUT) та іншою мережею. Це той спосіб, який був описаний трохи вище експерименту з МФУ. Канал управління сніффером у цьому випадку можна організувати через бездротову локальну мережу WiFi. Логічний шлях каналу управління позначений схемою червоною лінією.

Щоб підключитися до сніфера потрібно робочий ПК включений в ту ж мережу WiFi, що і сніфер, а також знання IP адреси який видається сніферу DHCP сервером. Якщо це домашня мережа або мережа підприємства, то з’ясувати IP сніфера не складе труднощів – досить заглянути в лог DHCP сервера або переглянути список підключених MAC адрес на домашньому WiFi маршрутизаторі і знайти там MAC адресу WiFi порту сніфера (заздалегідь введена команда ifconfig wlan0 ). Підключення до сніфера по SSH здійснюється командою ssh sniffer@xxxx , де xxxx — локальна IP адреса сніфера.
На мал. 8б наведена, по суті, та сама схема включення сніфера між DUT і комутатором локальної мережі, але канал управління організований через глобальну мережу Інтернет через тунель до PPTP/L2TP сервера. Для того, щоб у сніфера була можливість підняти тунель до заданого сервера, необхідно щоб усередині локальної мережі а) сніфер видавався локальний IP адресу по DHCP, і б) щоб з цього IP був доступ в Інтернет. При виконанні цих умов, сніффер під час завантаження підніме внутрішній мережний інтерфейс bridge0 і отримає IP адресу через DHCP. Далі вступить в дію утиліта mpd5, яка автоматично підніме PPTP/L2TP тунель, отримавши для нього дугою IP доступний для підключення зовні. Для доступу до сніфера SSH в цьому випадку використовуємо цей другий IP. Важливо щоб провайдер, що забезпечує PPTP/L2TP сервіс, видавав IP адресу, що глобально маршрутизується, інакше дістатися до сніфера не вийде.

Часто буває так, що мережа користувача має стик із глобальною мережею (з мережею провайдера послуг доступу до Інтернету) через порт Ethernet. У цьому випадку сніффер можна увімкнути між локальною мережею та мережею Інтернет-провайдера, як показано на мал. 8в. Щоб організувати канал управління сніффером, потрібно окремий обліковий запис на PPPoE сервері інтернет-провайдера, що забезпечує зв’язок.

Аналогічно попередньому варіанту, сніффер автоматично підніме тунель через PPPoE з’єднання з сервером провайдера і забезпечить собі IP адресу, що глобально маршрутизується, для встановлення SSH з’єднання з ним.
Важливо, що в такій схемі включення через сніффер проходитиме весь трафік мережі користувача, що може створити проблеми з його аналізом або з великим навантаженням на сніффер. Для аналізу в такій схемі використовуйте правила, що обмежують трафік лише IP адресою досліджуваного пристрою. Також важливо відзначити, що локальний трафік створюваний DUT не проходитиме через сніффер і випаде з аналізу, тобто досліджувати в такому разі можливо лише глобальний трафік між DUT і хостами в мережі Інтернет.
Та й останній варіант схеми включення, наведений на мал. 8г, дозволяє включити сніффер у домашній мережі, що має з’єднання з мережею провайдера по оптичному каналу (зазвичай це GPON). Сніффер встановлюється в розріз між ONU (оптичним кінцевим пристроєм) та домашнім маршрутизатором. При такому увімкненні сніферу буде доступна тільки та частина трафіку користувача, яка виходить в і приходить з глобальної мережі.
Канал керування організується також через PPPoE сервер провайдера. Але загалом ніхто не забороняє підключити сніффер до локального (домашнього) WiFi, а через нього, при необхідності мати віддалене управління, підняти PPTP/L2TP тунель до публічного сервера, як у попередніх двох варіантах.
Якщо Ви вирішили дослідити свою домашню мережу, Вам достатньо підключити сніффер як показано на цій схемі та керувати ним локально через свою домашню мережу WiFi, підключаючись по SSH безпосередньо.

Механізм фільтрації мережного трафіку призначений для того, щоб користувачеві (додатку) можна було вибрати (захопити) і проаналізувати тільки тип трафіку, що цікавить, трафік між певними хостами або навіть портами всередині хоста. Механізм фільтрації BPF вбудований в ОС FreeBSD, що називається, із коробки. А це означає, що для нього є сторінка системного керівництва.
Введемо команду man з параметром bpf і коротко ознайомимося зі змістом сторінки посібника з BPF:
sniffer@sniffer:~ % man bpf
BPF(4) FreeBSD Kernel Interfaces Manual BPF(4)
NAME
bpf – Berkeley Packet Filter
SYNOPSIS
device bpf
DESCRIPTION
The Berkeley Packet Filter provides a raw interface to data link layers
in a protocol independent fashion. All packets on the network, even
those destined for other hosts, are accessible through this mechanism.
The packet filter appears as a character special device, /dev/bpf. After
opening the device, the file descriptor must be bound to a specific
network interface with the BIOCSETIF ioctl. A given interface can be
shared by multiple listeners, and the filter underlying each descriptor
will see an identical packet stream.
З другого абзацу ми дізнаємося, що доступ до BPF здійснює через спеціальний файл-пристрій /dev/bpf . Подивимося, хто має доступ до цього файлу за допомогою утиліти ls , введемо команду:
niffer@sniffer:~ % ls -al /dev/bpf* crw------- 1 root wheel 0x27 Jul 10 18:38 /dev/bpf lrwxr-xr-x 1 root wheel 3 Jul 10 18:20 /dev/bpf0 -> bpf
Видно, що файл-пристрій /dev/bpf і символічне посилання на нього /dev/bpf0 належать групі wheel , при цьому група не має права доступу до цього файлу (у відповідному полі стоїть прочерк: — ). Це означає, що тільки користувач із привілеями адміністратора може отримувати доступ до BPF, тобто нам завжди доведеться використовувати утиліту sudo . При частому використанні це дуже зручно. Тому змінимо належність та права доступу до /dev/bpf , ввівши такі команди:
sniffer@sniffer:~ % sudo chmod g+w /dev/bpf sniffer@sniffer:~ % sudo chgrp network /dev/bpf
Подивись як змінилися атрибути та приналежність цього файлу:
sniffer@sniffer:~ % ls -al /dev/bpf crw-rw---- 1 root network 0x27 Jul 10 18:38 /dev/bpf
Тепер будь-який користувач у групі network може читати та писати ( rw ) у цей файл-пристрій, а значить для доступу до BPF нам більше не потрібно використовувати sudo (нагадаю, що користувач sniffer , під яким ми підключаємось до системи, входить до групи network ).
Тут є маленький аспект. Після перезавантаження операційної системи права доступу на цей файл повернуться до вихідного вигляду, а це зовсім не те, чого ми очікуємо. Існує системний механізм devfs, що відстежує та змінює права доступу до системних файлів, за допомогою нього ми можемо встановлювати права доступу на окремі пристрої так, як нам цього потрібно. Додамо, за допомогою редактора ee , у конфігураційний файл /etc/devfs.conf наступні два правила для bpf :
sniffer@sniffer:~ % sudo ee /etc/devfs.conf
Скопіюємо наступні рядки в буфер обміну:
own bpf* root:network perm bpf* 0660
І помістимо їх у файл. Вийдемо із редактора зі збереженням змін. Тепер у момент завантаження операційної системи devfs буде встановлювати потрібні нам права доступу до BPF і ми зможемо використовувати різні утиліти для аналізу трафіку без виклику утиліти sudo .
Відразу скажу, що тема BPF (Berkeley Packet Filter) досить велика, що сягає корінням у 1980-і роки до машин і систем виробництва Digital Equipment Corporation, і може вимагати написання окремої багатосторінкової публікації. Строго кажучи, BPF – це віртуальна машина всередині ядра операційної системи, зі своєю системою команд (своїми інструкціями) та своїми форматами даних. З цих інструкцій, аналогічно тому, як складається програма для центрального процесора з машинних кодів, складають програми для фільтруючого механізму (Filter Machine). Виконуючись всередині ядра операційної системи, BPF програми можуть не тільки аналізувати та фільтрувати мережевий трафік, але й здійснювати його модифікацію (підставляти та замінювати дані в пакетах «на льоту»), що робить BPF дуже потужним та важливим механізмом при організації систем безпеки, виявлення та автоматичного пасивного та активного протидії вторгненню . BPF дозволяє будувати дуже складні міжмережеві екрани (firewall-и), а операційні системи FreeBSD та OpenBSD, з BPF на борту, широко використовуються у промислових виробах та системах мережної безпеки. Але зараз мова не про це.
Якщо продовжити читання посібника з BPF ( man bpf ), ми побачимо, що його частина описує програмні механізми (API) мовою Сі і принципи створення BPF програм з користувацьких і системних додатків. Це не зовсім те, що нам потрібно, тому що ми не збираємося розробляти свої програми, а хочемо скористатися вже існуючими. Є спеціальна бібліотека libpcap (PCAP), яка використовується багатьма утилітами для захоплення, аналізу та фільтрації мережевого трафіку. Ця бібліотека надає програмам уніфікований інтерфейс до BPF на основі текстових правил, зрозумілих кінцевому користувачеві, що дозволяє використовувати BPF без додаткового програмування. З описом синтаксису мови для створення правил фільтра BPF можна ознайомитись на окремій сторінці системного посібника за командою man pcap-filter . Давайте коротко ознайомимося хоча б із першою сторінкою цього посібника:
sniffer@sniffer:~ % man pcap-filter
PCAP-FILTER(7) FreeBSD Miscellaneous Information Manual PCAP-FILTER(7)
NAME
pcap-filter - packet filter syntax
DESCRIPTION
pcap_compile(3) is used to compile a string into a filter program. The
resulting filter program can then be applied to some stream of packets
to determine which packets will be supplied to pcap_loop(3),
pcap_dispatch(3), pcap_next(3), or pcap_next_ex(3).
The filter expression consists of one or more primitives. Primitives
usually consist of an id (name or number) preceded by one or more
qualifiers. There are three different kinds of qualifier:
type type qualifiers say what kind of thing the id name or number
refers to. Possible types are host, net, port and portrange.
E.g., `host foo', `net 128.3', `port 20', `portrange 6000-6008'.
If there is no type qualifier, host is assumed.
dir dir qualifiers specify a particular transfer direction to and/or
from id. Possible directions are src, dst, src or dst, src and
dst, ra, ta, addr1, addr2, addr3, and addr4. E.g., `src foo',
`dst net 128.3', `src or dst port ftp-data'. If there is no dir
qualifier, `src or dst' is assumed. The ra, ta, addr1, addr2,
addr3, and addr4 qualifiers are only valid for IEEE 802.11
Wireless LAN link layers.
proto proto qualifiers restrict the match to a particular protocol.
Possible protocols are: ether, fddi, tr, wlan, ip, ip6, arp,
rarp, decnet, sctp, tcp and udp. E.g., `ether src foo', `arp
net 128.3', `tcp port 21', `udp portrange 7000-7009', `wlan
addr2 0:2:3:4:5:6'. If there is no proto qualifier, all
protocols consistent with the type are assumed. E.g., `src foo'
means `(ip6 or ip or arp or rarp) src foo', `net bar' means `(ip
or arp or rarp) net bar' and `port 53' means `(tcp or udp or
sctp) port 53' (note that these examples use invalid syntax to
illustrate the principle).
І трохи далі:
Primitives may be combined using:
A parenthesized group of primitives and operators.
Negation (`!' or `not').
Concatenation (`&&' or `and').
Alternation (`||' or `or').
Negation has the highest precedence. Alternation and concatenation
have equal precedence and associate left to right.
If an identifier is given without a keyword, the most recent keyword is
assumed. For example,
not host vs and ace
is short for
not host vs and host ace
which should not be confused with
not (host vs or ace)
У цій цитаті з керівництва міститься максимум знань, яких нам потрібно для складання складних фільтрів. Якщо коротко викласти сказане у посібнику, то правила фільтрації виглядають так:
Примітивне правило складається з трьох честей: type dir proto де: type – задає тип сутності, що визначається далі в правилі, це може бути host , net , port або portrange . dir – визначає яке з полів пакету буде аналізуватися : src , dst , addr1 , addr2 , і т.д. proto – вказує пакети , що відносяться до якого протоколу відповідатимуть цьому правилу : , icmp , tcp , udp і т. д. (їх дуже багато).
Будь-яка з частин правила може бути відсутня, що рівносильне виразу («any» – будь-який). Тобто якщо відсутній proto , то будуть аналізуватися пакети всіх протоколів.
Примітивні правила можуть об’єднуватися в більш складні правила за допомогою логічних операцій or , and і not , а так само вкладеної системи круглих дужок. Логічні операції можна висловлювати знаками: || , && або !
Для ясності розглянемо кілька простих прикладів:
Правило з одного слова icmp створить фільтр, який описує тільки Internet Control and Management Protocol (ICMP), тобто пакети створювані запитами команди ping та відповіді на них. Це правило ми вже використовували для тестування мережного моста у розділі 5.3 .
Правило: udp 5060 створить фільтр, який покриє UDP трафік тільки для портів 5060 (в обидві сторони). Це найпростіше правило виділення SIP пакетів із загального потоку мережного трафіку.
Правило: not port 22 створить фільтр, який виключить з трафіку, що захоплюється, всі пакети (TCP і UDP) у призначенні або джерелі яких присутній порт номер 22 . Це найпростіше правило для того, щоб відняти (видалити з аналізу) трафік, створений протоколом віддаленого доступу SSH. Дуже корисне правило, яке застосовується коли потрібно подивитися на весь мережевий трафік, але трафік віддаленого управління хостом (SSH) може забити висновок гігантським потоком марної інформації. Тут це правило приходить на допомогу.
Правило: dst host 192.168.168.14 створить фільтр, що виділяє потік пакетів у полі IP адреси призначення яких вказаний заданий хост. За допомогою цього правила можна підглянути трафік , що прямує у бік хоста 192.168.168.14 .
Правило: vlan 2 виділить всі Ethernet пакети типу 0x8100 у яких тег VLAN дорівнює 2 .
Трохи більш складне правило: vlan 4 and dst host 192.168.168.14 and not port 22 виділити трафік для VLAN = 2 і тільки у бік хоста 192.168.168.14 видалити з вибірки трафік протоколу SSH (порт 22 ) щоб не міш.
У BPF існують механізми у тому, щоб як розглядати заголовки пакетів, а й заглянути глибше у дані пакета (в payload). Такі правила глибокого аналізу пакетів прийнято називати Deep Packet Inspection (DPI). Нижче наведено кілька прикладів правил DPI:
Правило: ‘udp[8:4] = 0x5349502f && udp[12:4] = 0x322e3020’ дозволить вибрати з потоку тільки UDP пакети, що містять на самому початку блоку корисних даних (на початку payload) рядок символів: “ SIP/2.0 “ (включаючи пробіл), включаючи пробіл. Пакет з таким вмістом – це відповіді на запити протоколу SIP/2.0. Таке правило може бути корисним у тому випадку, коли пропрієтарна програма намагається «заховати» обмін за протоколом SIP вибираючи випадковий номер UDP порту.
Більш складне правило зі зворотним зв’язком: ‘tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x5353482d’ дозволяє виявити всі спроби встановити з’єднання протоколу SSH незалежно від того на якому TCP порту розташовується цей сервіс. Таке правило може бути дуже корисним для виявлення сканування портів SSH шкідливим ПЗ або спробами вторгнення.
Як це працює, швидше за все, вже стало зрозуміло. Перше правило вибирає з UDP пакета два значення по 4 байти, представляє їх у вигляді числа та порівнює із заданими константами. Цифра 8 у правилі udp[8:4] задає зсув 8 байт щодо початку UDP заголовка, а цифра 4 вказує на те, що потрібно взяти для порівняння чотири байти. Константа 0x5349502f являє собою рядок тексту “SIP/” в ASCII коді, а 0x322e3020 – рядок тексту ” 2.0″ разом із пробілом.
Друге правило набагато складніше. Це націлено на аналіз вмісту корисного навантаження TCP пакетів. З TCP пакетами є деяка складність – у них заголовок має змінну довжину, а значить дістатися корисного навантаження просто вказавши зміщення – не вийде. Для таких випадків можна скористатися фічею BPF, що дозволяє обчислити значення змінної виходячи з даних і використовувати її значення як зміщення для отримання іншого значення, яке вже буде порівнюватися з константою. У наведеному вище прикладі шматочок правила ((tcp[12:1] & 0xf0) >> 2) саме обчислює довжину заголовка, тобто отримує зміщення нульового байта корисного навантаження. Далі це значення підставляється як індекс (зміщення) і вибирається інше чотирибайтове значення для звірки на збіг з константою 0x5353482d , аналогічно випадку з UDP.
Далі ми спробуємо застосувати ці правила у дії живої мережі.
Правила DPI для аналізу трафіку створюють дуже велике навантаження на обчислювальну систему, особливо за інтенсивного потоку трафіку. Використовуючи кілька таких правил при середньому навантаженні на мережу можна легко «завісити» систему на сніффері або навіть відправити ядро в panic, тому діяти треба обережно – бажано додавати винятки зайвого (завідомо нас не цікавить) трафіку за допомогою примітивних правил типу src host , tcp port . Тепер зрозуміло навіщо ми проводили тести продуктивності Coremark та STREAM? 😉
Настав час познайомитися з ще однією потужною утилітою аналізу мережевого трафіку – WireShark . Ця утиліта напевно знайома багатьом мережевим інженерам та адмінам, у тому числі в середовищі Windows. WireShark має зручний графічний інтерфейс, що дозволяє не тільки захоплювати (записувати) і відображати окремі пакети, але й робити глибокий аналіз записаного трафіку з кількома проходами. WireShark вміє автоматично розділяти весь трафік на асоційовані потоки між кінцевими точками (парами host:port), дозволяє розкрутити TCP ланцюжки і виймати з усього обсягу пакетів послідовний потік корисних даних, що передаються. Іншими словами WireShark вміє підглядати і витягувати з потоку дані, що передаються користувальницьким додатком. У WireShark є гнучкі засоби пошуку за записаним обсягом даних та фільтрації на основі BPF. На рис. 9 нижче представлено вікно графічного інтерфейсу WireShark серед ОС Linux.

Однак, небагато мережевих інженерів знають про існування «консольного» варіанта WireShark, або точніше, варіанти цієї ж утиліти призначеного для текстового терміналу. Називається ця утиліта tshark . Вона входить у той же пакет програм із загальною назвою WireShark і використовує той самий бекенд, що і її графічний побратим.
Утиліта tshark має багатий набір опцій і параметрів командного рядка, але загальний підхід у неї такий самий як у утиліти tcpdump – за набором опцій слідує набір правил BPF, за одним винятком – синтаксис цих правил набагато багатший. Наприклад, у tshark можна вказати правило виду ‘http.request.method == “GET”‘ щоб отримувати лише пакети з запитами HTTP. Таке правило теж відноситься до класу DPI і всередині утиліти воно представляється як комбінації більш примітивних правил BPF. Користуватися утилітою tshark зручніше замість утиліти tcpdump у тому випадку, коли потрібно виконати саме глибокий аналіз корисного навантаження, що передається по мережі.
У tshark є своя сторінка системного керівництва, яку можна викликати командою man tshark . Пропоную ознайомимося з нею:
sniffer@sniffer:~ % man tshark
TSHARK(1) TSHARK(1)
NAME
tshark - Dump and analyze network traffic
SYNOPSIS
tshark [ -i <capture interface>|- ] [ -f <capture filter> ] [ -2 ]
[ -r <infile> ] [ -w <outfile>|- ] [ options ] [ <filter> ]
tshark -G [ <report type> ] [ --elastic-mapping-filter <protocols> ]
[ -C <profile> ]
tshark -h|--help
tshark -v|--version
DESCRIPTION
TShark is a network protocol analyzer. It lets you capture packet data
from a live network, or read packets from a previously saved capture
file, either printing a decoded form of those packets to the standard
output or writing the packets to a file. TShark's native capture file
format is pcapng format, which is also the format used by Wireshark and
various other tools.
Without any options set, TShark will work much like tcpdump. It will
use the pcap library to capture traffic from the first available
network interface and displays a summary line on the standard output
for each received packet.
...
У посібнику сказано, що tshark (розробники вважають за краще писати назву з великих – TShark ) у багатьох випадках поводиться подібно до утиліти tcpdump і це дуже зручно, тому що багато адміністраторів Unix систем звикли до утиліти tcpdump та її набору параметрів. tshark у плані іменування опцій і складання правил дуже схожий на tcpdump .
Перейдемо від слів до справи — опробуємо наведені у попередньому розділі DPI правила обох утилітах. Для цього підключаемо сніффер у розріз між IP-відеодомофоном і мережею, таким самим способом як це було описано в розділі 5.3 з пропусканням трафіку конторського МФУ.
Слід зазначити, що при вказівці складних правил у командному рядку їх слід обрамляти одинарними лапками, інакше оболонка tcsh може інтерпретувати символи логічних операцій та дужок на власний розсуд і ми можемо отримати зовсім не той результат.
Викликаємо утиліту tcpdump та передамо їй наступне BPF правило для глибокого аналізу трафіку:
sniffer@sniffer:~ % tcpdump -n -i bridge0 -s 1500 -X -vv 'udp[8:4] = 0x5349502f && udp[12:4] = 0x322e3020'
Через кілька секунд ми побачимо перші пакети обміну IP-домофона із SIP проксі-сервером. Нагадаю, що це складне правило аналізує вміст корисного навантаження UDP пакетів з метою визначити та захопити пакети SIP відповідей (на нашу зручність вони містять рядок SIP/2.0 на самому початку payload). Це правило не реагує на запити SIP! Одна з таких «спійманих» відповідей виглядатиме так:
tcpdump: listening on bridge0, link-type EN10MB (Ethernet), snapshot length 1500 bytes
00:26:23.478943 IP (tos 0x68, ttl 254, id 375, offset 0, flags [none], proto UDP (17), length 412)
72.243.211.106.53520 > 192.168.168.139.5060: [udp sum ok] SIP, length: 384
SIP/2.0 100 Trying
Via: SIP/2.0/UDP 192.168.168.139:5060;branch=z9hG4bK-gdklpgig931861861291050861291.b;rport
0x0000: 4568 019c 0177 0000 fe11 92e1 4df2 6f6a Eh...w......M.oj
0x0010: c0a8 a88b d110 13c4 0188 5447 5349 502f ..........TGSIP/
0x0020: 322e 3020 3130 3020 5472 7969 6e67 0d0a 2.0.100.Trying..
0x0030: 5669 613a 2053 4950 2f32 2e30 2f55 4450 Via:.SIP/2.0/UDP
0x0040: 2031 3932 2e31 3638 2e31 3638 2e31 3339 .192.168.168.139
0x0050: 3a35 3036 303b 6272 616e 6368 3d7a 3968 :5060;branch=z9h
0x0060: 4734 624b 2d67 646b 6c70 6769 6739 3331 G4bK-gdklpgig931
0x0070: 3836 3138 3631 3239 3130 3530 3836 3132 8618612910508612
0x0080: 3931 2e62 3b72 706f 7274 0d0a 4672 6f6d 91.b;rport..From
0x0090: 3a20 22d0 94d0 bed0 bcd0 bed1 84d0 bed0 :.".............
0x00a0: bd22 203c 7369 703a 3230 3140 6661 626d .".<sip:201@exam
0x00b0: 6963 726f 2e72 753e 3b74 6167 3d46 726f ples.xx>;tag=Fro
0x00c0: 6d54 6167 2d67 646b 6c70 6769 6739 3331 mTag-gdklpgig931
0x00d0: 3836 3138 3631 3239 3130 3530 3836 3132 8618612910508612
0x00e0: 3931 2e62 0d0a 546f 3a20 3c73 6970 3a32 91.b..To:.<sip:2
0x00f0: 3031 4066 6162 6d69 6372 6f2e 7275 3e0d [email protected]>.
0x0100: 0a44 6174 653a 2054 6875 2c20 3130 204a .Date:.Thu,.10.J
0x0110: 756c 2032 3032 3520 3136 3a33 323a 3235 ul.2025.16:32:25
0x0120: 2047 4d54 0d0a 4361 6c6c 2d49 443a 2067 .GMT..Call-ID:.g
0x0130: 646b 6c70 6769 6739 3331 3836 3138 3631 dklpgig931861861
0x0140: 3239 3130 3530 3836 3132 3931 2e62 0d0a 291050861291.b..
0x0150: 5365 7276 6572 3a20 4369 7363 6f2d 5349 Server:.Cisco-SI
0x0160: 5047 6174 6577 6179 2f49 4f53 2d31 322e PGateway/IOS-12.
0x0170: 780d 0a43 5365 713a 2032 3833 2052 4547 x..CSeq:.283.REG
0x0180: 4953 5445 520d 0a43 6f6e 7465 6e74 2d4c ISTER..Content-L
0x0190: 656e 6774 683a 2030 0d0a 0d0a ength:.0....
Обмін по SIP протоколу зазвичай не шифрується, тобто передається в чистому текстовому вигляді (plain text), тому по вмісту пакета ми може точно визначити, що перед нами відповідь «SIP/2.0 100 Trying» від SIP-проксі з адресою 72.243.211.106 на запит «REGISTER. У тексті пакету жирним виділено ті байти (то шматочок блоку корисного навантаження), який вхопилося правило. Очевидно, якщо мати уявлення про формат корисного навантаження, то не складно скласти BPF правило для того, щоб вихоплювати з потоку будь-які цікаві для аналізу пакети. Але тільки якщо ці дані не були передані у зашифрованому вигляді. 🙂
sniffer@sniffer:~ % tshark -n -i bridge0 -s 1500 -V 'udp[8:4] = 0x5349502f && udp[12:4] = 0x322e3020'
Зробимо цей же фокус, але вже за допомогою утиліти tshark . Формат команди дуже схожий на той, що ми тільки-но використовували для утиліти tcpdump :
При першому збігу отримаємо в терміналі наступне повідомлення від tshark :
Capturing on 'bridge0'
Frame 1: 426 bytes on wire (3408 bits), 426 bytes captured (3408 bits) on interface bridge0, id 0
Section number: 1
Interface id: 0 (bridge0)
Interface name: bridge0
Encapsulation type: Ethernet (1)
Arrival Time: Jul 11, 2025 00:54:19.286236877 +05
UTC Arrival Time: Jul 10, 2025 19:54:19.286236877 UTC
Epoch Arrival Time: 1752177259.286236877
[Time shift for this packet: 0.000000000 seconds]
[Time delta from previous captured frame: 0.000000000 seconds]
[Time delta from previous displayed frame: 0.000000000 seconds]
[Time since reference or first frame: 0.000000000 seconds]
Frame Number: 1
Frame Length: 426 bytes (3408 bits)
Capture Length: 426 bytes (3408 bits)
[Frame is marked: False]
[Frame is ignored: False]
[Protocols in frame: eth:ethertype:ip:udp:sip]
Ethernet II, Src: e8:39:35:b1:10:ee, Dst: fe:4a:eb:ea:b4:61
Destination: fe:4a:eb:ea:b4:61
.... ..1. .... .... .... .... = LG bit: Locally administered address (this is NOT the factory default)
.... ...0 .... .... .... .... = IG bit: Individual address (unicast)
Source: e8:39:35:b1:10:ee
.... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
.... ...0 .... .... .... .... = IG bit: Individual address (unicast)
Type: IPv4 (0x0800)
[Stream index: 0]
Internet Protocol Version 4, Src: 72.243.211.106, Dst: 192.168.168.139
0100 .... = Version: 4
.... 0101 = Header Length: 20 bytes (5)
Differentiated Services Field: 0x68 (DSCP: AF31, ECN: Not-ECT)
0110 10.. = Differentiated Services Codepoint: Assured Forwarding 31 (26)
.... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
Total Length: 412
Identification: 0x01a9 (425)
000. .... = Flags: 0x0
0... .... = Reserved bit: Not set
.0.. .... = Don't fragment: Not set
..0. .... = More fragments: Not set
...0 0000 0000 0000 = Fragment Offset: 0
Time to Live: 254
Protocol: UDP (17)
Header Checksum: 0x92af [validation disabled]
[Header checksum status: Unverified]
Source Address: 72.243.211.106
Destination Address: 192.168.168.139
[Stream index: 0]
User Datagram Protocol, Src Port: 53520, Dst Port: 5060
Source Port: 53520
Destination Port: 5060
Length: 392
Checksum: 0x5e47 [unverified]
[Checksum Status: Unverified]
[Stream index: 0]
[Stream Packet Number: 1]
[Timestamps]
[Time since first frame: 0.000000000 seconds]
[Time since previous frame: 0.000000000 seconds]
UDP payload (384 bytes)
Session Initiation Protocol (100)
Status-Line: SIP/2.0 100 Trying
Status-Code: 100
[Resent Packet: False]
Message Header
Via: SIP/2.0/UDP 192.168.168.139:5060;branch=z9hG4bK-gdklpgig931861861291050861291.b;rport
Transport: UDP
Sent-by Address: 192.168.168.139
Sent-by port: 5060
Branch: z9hG4bK-gdklpgig931861861291050861291.b
RPort: rport
From: "Домофон" <sip:[email protected]>;tag=FromTag-gdklpgig931861861291050861291.b
SIP from display info: "Домофон"
SIP from address: sip:[email protected]
SIP from address User Part: 201
SIP from address Host Part: samples.xx
SIP from tag: FromTag-gdklpgig931861861291050861291.b
To: <sip:[email protected]>
SIP to address: sip:[email protected]
SIP to address User Part: 201
SIP to address Host Part: samples.xx
Date: Thu, 10 Jul 2025 17:00:21 GMT
Call-ID: gdklpgig931861861291050861291.b
[Generated Call-ID: gdklpgig931861861291050861291.b]
Server: Cisco-SIPGateway/IOS-12.x
CSeq: 308 REGISTER
Sequence Number: 308
Method: REGISTER
Content-Length: 0
Висновок у tshark буде набагато більш насиченим. Для кожного пакету ця утиліта видає такий аналіз:
аналізу Ethernet II (MAC) заголовка;
аналізу Internet Protocol (IP) заголовка;
аналізу User Datagram Protocol (UDP) заголовка;
та аналіз Session Initiation Protocol (SIP) пакета.
Утиліта tshark спробує проаналізувати буквально кожен біт захопленого пакета і видати максимум наявної в неї інформації. З наведеного вище лістингу ми бачимо, що tshark точно визначила, що це саме SIP пакет, що містить відповідь на запит «REGISTER» і досконало розписала нам вміст кожного поля.
Варто відзначити, що утиліта tcpdump теж виконує деякий аналіз (парсинг) MAC та IP заголовків, проте аналіз SIP вона робити не здатна. Хоча вивести вміст SIP пакета у текстовому вигляді можливо.
Тепер пробуємо більш складне (друге) правило і подивимося, як з ним справляються обидві утиліти. Нагадаю, що це правило спочатку знаходить у TCP пакеті розташування корисного навантаження, а потім намагається визначити в ній рядок тексту SSH_ на самому початку, що є ознакою хендшейка по протоколу SSH.
Спочатку запустимо утиліту tcpdump з наступними параметрами:
sniffer@sniffer:~ % tcpdump -n -i bridge0 -s 1500 -X -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x5353482d'
Далі відкривається ще одне вікно термінала на робочому ПК, після чого здійснюється спроба встановити SSH-з’єднання з IP-домофоном, який працює за адресою 192.168.168.139 — ця інформація була визначена під час попереднього етапу. На домофоні має бути заздалегідь запущений демон sshd на порту 22/tcp, інакше встановити з’єднання буде неможливо.
Виконуемо наступну команду на робочому ПК:
rz@butterfly:~ % ssh [email protected]
І тут же спостерігаю в терміналі сніфера наступне повідомлення від tcpdump , що містить дамп “пійманого” пакета:
tcpdump: listening on bridge0, link-type EN10MB (Ethernet), snapshot length 1500 bytes
00:25:10.212128 IP (tos 0x48, ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 90)
192.168.176.155.37196 > 192.168.168.139.22: Flags [P.], cksum 0x63d4 (correct), seq 3500301681:3500301719, ack 2008447800, win 257, options [nop,nop,TS val 2915515975 ecr 962763132], length 38: SSH: SSH-2.0-OpenSSH_9.9 FreeBSD-20250219
0x0000: 4548 005a 0000 4000 3f06 60de c0a8 b09b EH.Z..@.?.`.....
0x0010: c0a8 a88b 914c 0016 d0a2 5d71 77b6 7b38 .....L....]qw.{8
0x0020: 8018 0101 63d4 0000 0101 080a adc7 3e47 ....c.........>G
0x0030: 3962 997c 5353 482d 322e 302d 4f70 656e 9b.|SSH-2.0-Open
0x0040: 5353 485f 392e 3920 4672 6565 4253 442d SSH_9.9.FreeBSD-
0x0050: 3230 3235 3032 3139 0d0a 20250219..
У цьому прикладі tcpdump успішно відфільтрував TCP-пакет із загального потоку, керуючись вмістом корисного навантаження. Так само, як і в попередньому експерименті, виділено байти, що відповідають умові фільтрації та збігаються з указаним правилом.
Зі вмісту пакета видно, що ssh клієнт входить до складу пакету OpenSSH і працює під управлінням ОС FreeBSD, а по рядку містить дату складання клієнта навіть можна припустити якоїсь версії. Ось так, підглянувши всього один пакет, можна вже досить багато дізнатися про користувача. 🙂
Опробуємо це правило з утилітою tshark , ввівши таку команду:
sniffer@sniffer:~ % tshark -n -i bridge0 -s 1500 -V 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x5353482d'
І виконаємо спробу з’єднання SSH з IP-домофоном аналогічно попередньому досвіду. У вікні терміналу сніфера відразу отримаємо довгий лістинг з аналізом TCP пакета від tshark :
Capturing on 'bridge0'
Frame 1: 104 bytes on wire (832 bits), 104 bytes captured (832 bits) on interface bridge0, id 0
Section number: 1
Interface id: 0 (bridge0)
Interface name: bridge0
Encapsulation type: Ethernet (1)
Arrival Time: Jul 11, 2025 00:36:25.038883854 +05
UTC Arrival Time: Jul 10, 2025 19:36:25.038883854 UTC
Epoch Arrival Time: 1752176185.038883854
[Time shift for this packet: 0.000000000 seconds]
[Time delta from previous captured frame: 0.000000000 seconds]
[Time delta from previous displayed frame: 0.000000000 seconds]
[Time since reference or first frame: 0.000000000 seconds]
Frame Number: 1
Frame Length: 104 bytes (832 bits)
Capture Length: 104 bytes (832 bits)
[Frame is marked: False]
[Frame is ignored: False]
[Protocols in frame: eth:ethertype:ip:tcp:ssh]
Ethernet II, Src: e8:39:35:b1:10:ee, Dst: fe:4a:eb:ea:b4:61
Destination: fe:4a:eb:ea:b4:61
.... ..1. .... .... .... .... = LG bit: Locally administered address (this is NOT the factory default)
.... ...0 .... .... .... .... = IG bit: Individual address (unicast)
Source: e8:39:35:b1:10:ee
.... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
.... ...0 .... .... .... .... = IG bit: Individual address (unicast)
Type: IPv4 (0x0800)
[Stream index: 0]
Internet Protocol Version 4, Src: 192.168.176.155, Dst: 192.168.168.139
0100 .... = Version: 4
.... 0101 = Header Length: 20 bytes (5)
Differentiated Services Field: 0x48 (DSCP: AF21, ECN: Not-ECT)
0100 10.. = Differentiated Services Codepoint: Assured Forwarding 21 (18)
.... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
Total Length: 90
Identification: 0x0000 (0)
010. .... = Flags: 0x2, Don't fragment
0... .... = Reserved bit: Not set
.1.. .... = Don't fragment: Set
..0. .... = More fragments: Not set
...0 0000 0000 0000 = Fragment Offset: 0
Time to Live: 63
Protocol: TCP (6)
Header Checksum: 0x60de [validation disabled]
[Header checksum status: Unverified]
Source Address: 192.168.176.155
Destination Address: 192.168.168.139
[Stream index: 0]
Transmission Control Protocol, Src Port: 45404, Dst Port: 22, Seq: 1, Ack: 1, Len: 38
Source Port: 45404
Destination Port: 22
[Stream index: 0]
[Stream Packet Number: 1]
[Conversation completeness: Incomplete (0)]
..0. .... = RST: Absent
...0 .... = FIN: Absent
.... 0... = Data: Absent
.... .0.. = ACK: Absent
.... ..0. = SYN-ACK: Absent
.... ...0 = SYN: Absent
[Completeness Flags: [ Null ]]
[TCP Segment Len: 38]
Sequence Number: 1 (relative sequence number)
Sequence Number (raw): 2043450806
[Next Sequence Number: 39 (relative sequence number)]
Acknowledgment Number: 1 (relative ack number)
Acknowledgment number (raw): 2021031524
1000 .... = Header Length: 32 bytes (8)
Flags: 0x018 (PSH, ACK)
000. .... .... = Reserved: Not set
...0 .... .... = Accurate ECN: Not set
.... 0... .... = Congestion Window Reduced: Not set
.... .0.. .... = ECN-Echo: Not set
.... ..0. .... = Urgent: Not set
.... ...1 .... = Acknowledgment: Set
.... .... 1... = Push: Set
.... .... .0.. = Reset: Not set
.... .... ..0. = Syn: Not set
.... .... ...0 = Fin: Not set
[TCP Flags: ·······AP···]
Window: 257
[Calculated window size: 257]
[Window size scaling factor: -1 (unknown)]
Checksum: 0x8b83 [unverified]
[Checksum Status: Unverified]
Urgent Pointer: 0
Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps
TCP Option - No-Operation (NOP)
Kind: No-Operation (1)
TCP Option - No-Operation (NOP)
Kind: No-Operation (1)
TCP Option - Timestamps: TSval 2682966770, TSecr 963437961
Kind: Time Stamp Option (8)
Length: 10
Timestamp value: 2682966770
Timestamp echo reply: 963437961
[Timestamps]
[Time since first frame in this TCP stream: 0.000000000 seconds]
[Time since previous frame in this TCP stream: 0.000000000 seconds]
[SEQ/ACK analysis]
[Bytes in flight: 38]
[Bytes sent since last PSH flag: 38]
TCP payload (38 bytes)
SSH Protocol
Protocol: SSH-2.0-OpenSSH_9.9 FreeBSD-20250219
[Direction: client-to-server]
Аналогічно тому, як це було з SIP пакетом, утиліта tshark видала детальний аналіз пакета, що є частиною SSH хендшейка, що складається з чотирьох розділів:
аналізу Ethernet II (MAC) заголовка;
аналізу Internet Protocol (IP) заголовка;
аналізу Transmission Control Protocol (TCP) заголовка;
та аналізу SSH Protocol (SSH) пакета.
Наведу ще один приклад, що демонструє можливості утиліти tshark з декодування потоку даних із загального трафіку. Припустимо, що у нас є певний пристрій, той же IP-домофон, з Web-адмінкою на борту і нам потрібно з’ясувати текст HTTP запитів та відповідей на них, зокрема, підглянути пароль для проходження авторизації (причини для цього можуть бути суто технічні). Послідовність дій така:
Спочатку ми запишемо весь HTTP трафік для даного хоста (192.168.168.139) в окремий файл з іменем dump-192.168.168.139.pcap . Команда для запису виглядає так:
sniffer@sniffer:~ % tshark -i bridge0 -w dump-192.168.168.139.pcap port 80 Capturing on 'bridge0'
Після запуску утиліта tshark починає виводити лічильник, що безперервно збільшується та відображає кількість зафіксованих пакетів. Далі необхідно дочекатися, поки користувач виконає кілька HTTP-запитів. У межах експерименту це може бути звичайне відкриття браузера та перехід до веб-адмінки досліджуваного пристрою. Утиліта tshark показує наступне:
134 ^C
Після переходу до веб-інтерфейсу пристрою лічильник зафіксованих пакетів у tshark різко зростає, що свідчить про активний HTTP-трафік. Для завершення запису достатньо натиснути Ctrl-C.
Тепер нам потрібно подивитися які TCP потоки були записані та вивести їх ідентифікатори (числа від нуля та вище), щоб далі декодувати кожен потік окремо. Так як нас цікавлять тільки HTTP запити та відповіді на них, то вводимо наступну команду із зазначенням фільтра:
sniffer@sniffer:~ % tshark -n -r dump-192.168.168.139.pcap -2 -R "http.request or http.response" -T fields -e tcp.stream 0 0 1 3 3 1 4 4
Утиліта tshark видає нам наступні ідентифікатори потоків, в яких вона виявила HTTP трафік: 0 , 1 , 3 і 4 . Запам’ятаємо їх.
Тепер ми можемо декодувати трафік кожного потоку наступною командою, вказавши номер потоку наприкінці (цифра 0 після «ascii»):
sniffer@sniffer:~ % tshark -n -r dump-192.168.168.139.pcap -z follow,tcp,ascii,0
Утиліта видає вміст 0-го потоку:
===================================================================
Follow: tcp,ascii
Filter: tcp.stream eq 0
Node 0: 192.168.176.155:54742
Node 1: 192.168.168.139:80
378
GET / HTTP/1.1
Host: 192.168.168.139
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i
176
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
Server: SIPHomePhone/2.0
Content-Type: text/html
168
<html>
<head><meta http-equiv="refresh" content="0; url=admin_new.cgi"></head>
<body><p>The page has moved to: <a href="admin_new.cgi">this page</a></p></body>
</html>
===================================================================
Бачимо, що Web-адмінка даного пристрою після стандартного запиту «GET /» відфутболила браузер користувача на інший url=admin_new.cgi . Це означає, що браузер зробить ще один запит. Тому декодуємо наступний потік, вводимо команду для декодування потоку номер 1 :
sniffer@sniffer:~ % tshark -n -r dump-192.168.168.139.pcap -z follow,tcp,ascii,1
У відповідь отримуємо текст запиту та гігантський «респонз» на нього:
===================================================================
Follow: tcp,ascii
Filter: tcp.stream eq 1
Node 0: 192.168.176.155:59591
Node 1: 192.168.168.139:80
391
GET /admin_new.cgi HTTP/1.1
Host: 192.168.168.139
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i
72
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Server: SIPHomePhone/2.0
1385
Content-type: text/html; charset=utf-8
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="cache-control" content="no-cache"/>
<meta http-equiv="pragma" content="no-cache"/>
<link rel='stylesheet' id='theme-link' href='spectre.min.css'>
<link rel='stylesheet' id='iconlib-link' href='spectre-icons.css'>
<style>
#navbar-fabmicro a:hover {background-color:#f7f7f7;}
.menu-active {font-weight:bold;}
…
</script>
</div>
<hr>
<div class="text-center">{SID: <b>1466511685677080494854530CA38107</b>} {Serial: <b>1659112279</b>} {Source: default_config}</div>
</body>
</html>
===================================================================
Із отриманої відповіді було вилучено більшу частину HTML-коду сторінки, оскільки для даного експерименту ці елементи не містять цінної інформації. Все найцікавіше знаходиться в HTTP заголовках, а саме ось у цьому:
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
Такий заголовок вказує на те, що Web-сервер попросив клієнта провести авторизацію типу Basic , а це означає, що всередині закодованого рядка у форматі Base64 міститься логін і пароль у відкритому тексті. Що ж, залишилося лише декодувати цей рядок наступною командою:
sniffer@sniffer:~ % echo YWRtaW46cGFzc3dvcmQ= | base64 -d admin:password
І ми відразу дізнаємося, що користувач застосував логін: admin , і пароль: password . Ціль досягнута!
Хочу зауважити, що 99% трафіку, що передається по мережах, в даний час піддається шифруванню за допомогою різних алгоритмів і протоколів (SSL, TLS), тому ось так просто підслухати паролі для будь-якого потоку користувача в сучасних реаліях просто не можливо. Наведений вище приклад здебільшого змодельований і показаний для демонстрації можливостей утиліти tshark із вилучення корисного навантаження з потоку трафіку.
Але також і зауважу, що ця утиліта має ключ -o за допомогою якого можна вказати на RSA ключ від SSL сертифіката і тоді tshark автоматично декодує і розшифрує SSL/TLS трафік. Таким чином, завдання прослуховування зводиться до того, де взяти ключ. 😉
Ще одна корисна утиліта про яку хочеться розповісти – це trafshow . Ця утиліта була написана нашим співвітчизником Володимиром Воробйовим із Новосибірського Держ. Університету у далеких 90-х роках минулого сторіччя. Утиліта до цього дня підтримується і чудово працює на багатьох Unix системах, що мають BPF API. У стандартне постачання ОС FreeBSD вона не входить, але знаходиться в репозиторії у вигляді окремого пакета з однойменною назвою, тобто встановити її можна однією командою:
sniffer@sniffer:~ % sudo pkg install trafshow
Подібно tcpdump і tshark , утиліта trafshow приймає як параметри командного рядка набір BPF правил. Однак завдання утиліти не розкладати трафік до окремих пакетів, а навпаки – групувати (підсумовувати трафік) потоками і відображати поточну інтенсивність кожного потоку у вигляді списку. Для кожного потоку утиліта trafshow відображає хост та порт джерела та призначення пакетів, а також поточну інтенсивність в одиницях CPS (Characters per Second, тобто «байт за секунду») та суму накопиченого трафіку (у байтах) за час спостереження. Утиліта trafshow добре підходить для моніторингу поточного навантаження мережі, виявлення небажаних джерел трафіку, а також корисна при боротьбі з DDoS атаками.
Утиліта trafshow завжди працює у текстовому інтерактивному режимі. Це означає, що користувач може переміщатися по списку потоків в реальному часі (переміщаючи курсор вгору або вниз), вибравши потік, що цікавить, і натиснувши Enter може отримувати дампи пакетів в HEX і ASCII форматі для даного потоку. Вихід із вибраного потоку здійснюється натисканням клавіші Esc. На рис. 10 показано вікно терміналу в якому запущена утиліта trafshow .

Для демонстрації роботи trafshow утиліта запускається на сніфері з попередньо визначеним набором правил, які виключають небажаний та несуттєвий трафік. У цьому випадку до небажаних потоків належать SSH і GRE (тунель PPTP), через які здійснюється підключення до пристрою.
Якщо ці протоколи не відфільтрувати, вони створюватимуть ефект «самопідсилення»: дані, що відображає trafshow, одночасно проходитимуть через той самий інтерфейс, провокуючи позитивний зворотний зв’язок і потенційно перевантажуючи мережевий інтерфейс.
Тому вводимо наступну команду, вказавши фільтр:
sniffer@sniffer:~ % trafshow -i bridge0 not port 22 and not arp and not proto gre
В окремому вікні термінала запускається утиліта ping на IP-адресу домофона. Запуск здійснюється в режимі flood, що дозволяє створити максимально інтенсивний потік ICMP-трафіку для подальшого спостереження в trafshow. Для цього введу наступну команду на своєму робочому ПК:
rz@butterfly:~ % sudo ping -f 192.168.168.139 Password: PING 192.168.168.139 (192.168.168.139): 56 data bytes .....
У процесі «Flood Ping» утиліта ping безперервно передає в мережу пакети типу ICMP Echo-Request розміром по 56 байт (за замовчуванням) не чекаючи відповіді на них. Якщо протягом певного часу відповідь на переданий пакет не надходить, такий пакет вважається втраченим і утиліта ping відображає в термінал символ «точка» («.»), що дозволяє оцінити інтенсивність втрат у реальному часі.
Перейдемо у вікно терміналу підключеного до машини сніффера і поспостерігаємо на процес, що відображається в утиліті trafshow . Ми побачимо вікно, зразковий зміст якого показано на мал. 11.

Ми бачимо, що trafshow зафіксувала три потоки: ICMP echo-request, ICMP echo-reply та IGMP. Потік IGMP – це одиничний пакет від комутатора та в ньому передано всього 28 байт. А ось потоки ICMP мають досить високу інтенсивність – по 60 КБ/сек (кілобайт за секунду) у кожному напрямку. У нижньому рядку утиліта trafshow показує загальне завантаження мережного інтерфейсу і сумарне число переданих байт.
Якщо зараз натиснути клавішу Enter і увійти в перший потік, утиліта trafshow почне відображати безперервний потік захоплених пакетів. Як це виглядає, показано на мал. 12 нижче.

Зупинимо «Flood Ping» і запустимо його ще раз, вказавши значно більший розмір корисного навантаження, наприклад 1400 байт:
rz@butterfly:~ % sudo ping -s 1400 -f 192.168.168.139 PING 192.168.168.139 (192.168.168.139): 1400 data bytes ......................
Перше що впадає у вічі — інтенсивність втрат значно зросла, це по більшому числу «точок» і їх появи. Перейдемо у вікно терміналу машини сніфера і подивимося, що нам показує утиліта trafshow . На мал. 13а видно, що швидкість (CPS) суттєво зросла і тепер становить близько 460 КБ/сек або 3,6 Мбіт/сек, що для мережі FastEthernet (саме такий тип Ethernet порту на IP-домофоні) становить менше ніж 5% її пропускної спроможності! Можна зробити припущення про те, що або в мережі, або на пристрої є проблеми.
Під час повторного тестування в режимі Flood Ping, цього разу виконаного безпосередньо з машини-сніфера (IP-домофон підключений до неї напряму через UTP-патчкорд), були отримані значно інші результати. На зразку, поданому у мал. 123, показник CPS сягнув 3257 КБ/с, що становить приблизно 32% від максимально можливої пропускної здатності, а втрати склали лише два пакети (менше 0,01%).
Подальший аналіз показав, що низька пропускна здатність і підвищений packet loss у двох попередніх тестах були спричинені саме використанням Wi-Fi-мережі, через яку виконувалося підключення робочого ноутбука. Ситуація наочно підтвердила відому істину: навіть у, здавалося б, очевидних сценаріях інколи виникають несподівані технічні нюанси.

Розповідь про аналіз мережевого трафіку була б неповною без згадки про таку чудову утиліту, або навіть правильніше сказати — системи, як SNORT Intrusion Prevention System . Цей комплекс складається з утиліти snort та великого обсягу скриптів та плагінів написаних різними мовами, різними людьми з різних компаній.
Розробка SNORT як простої утиліти для виявлення підозрілого трафіку розпочалася у 1998 році невеликою командою інженерів компанії Sourcefire під керівництвом Мартіна Реша (Martin Roesch). Уже в 2009 році SNORT був включений до «Зали слави відкритого програмного забезпечення», створеної журналом InfoWorld.
У 2013 році проєкт SNORT разом із командою розробників придбала компанія Cisco Systems, яка й надалі активно розвиває цей відкритий і безкоштовний продукт. Сьогодні SNORT вважається одним із провідних рішень у сфері виявлення атак, запобігання вторгненням та активного захисту мереж.
Багато комерційних міжмережевих екранів включають SNORT як основний компонент системи захисту, формуючи навколо нього дорогі апаратні рішення. Водночас сама утиліта залишається безплатною та доступною для будь-кого, хто працює з мережевими інструментами й знає, як налаштовувати системи моніторингу.
І так, SNORT входить до репозиторію пакетів ОС FreeBSD, тому його легко встановити командою:
sniffer@sniffer:~ % sudo pkg install snort3
Щоб отримати практичну користь від SNORT, його досить просто встановити. Потрібна глибока інтеграція з операційною системою (зокрема із вбудованим у ядро PF фільтром), написання своїх правил та скриптів. Також потрібно провести глибоку перебудову мережі, без чого SNORT просто марний. Але все це є інженеру середньої руки, головне — вміти читати документацію з SNORT і не боятися експериментувати.
У межах цього матеріалу не розглядатимуться інструкції чи детальні поради щодо налаштування SNORT — тема надто об’ємна і потребує окремого великого огляду. Основна мета тут полягає у тому, щоб продемонструвати можливості інструмента та привернути увагу читача до його практичного застосування.
Разом із тим кілька прикладів використання SNORT на базі нашого сніфера все ж будуть наведені, але перед цим варто коротко зупинитися на теоретичних основах. Утиліта snort (так називається основний компонент комплексу) може працювати в одному з трьох режимів:
«Сніффер» – аналізує трафік, що проходить повз, у спробі відшукати в ньому щось що відповідає заданим правилам, дуже схожий на ( tshark з опціями -Y і -R ).
«Логгер пакетів» — зберігає пакети, що проходять повз, у файли-дампи для подальшого аналізу. Причому є ціла система створення і ведення цих файлів так як записуваного трафіку може бути величезна кількість і snort чудово з цим справляється.
«Детектор вторгнень» ( NIDS) – глибоко аналізує прохідний трафік і намагається визначити, ґрунтуючись на величезній базі правил, що постійно оновлюються, спроби вторгнення, сканування портів, спуфінгу або DDoS атак. У разі виявлення (спрацювання тригерів), snort може включати «логер пакетів», а також автоматично формувати та додавати правила до PF для відсікання підозрілого трафіку.
Одним із найчастіших провісників атаки на мережеву інфраструктуру є сканування TCP та UDP портів у мережі (або на машині) жертви. Атакуючий проводить сканування щоб з’ясувати потенційні слабкі місця на «тілі» жертви та згодом атакувати їх. Тому детектування процесу сканування портів та оперативна реакція на виявлення такої події є першорядною справою при грамотно побудованому захисті. Слід зазначити, що процес сканування портів може бути дуже витонченим і взагалі погано піддаватися процесу детектування. Тим не менш, ми розглянемо простий і досить часто використовуваний приклад – сканування за допомогою відправки порожніх TCP пакетів зі встановленим прапором SYN (запит на встановлення з’єднання). Атакуючий генерує потік таких пакетів, при цьому перебираючи випадковим чином номер порту. Хост. на якому є сервіс, що слухає на порту, відповідає на запит у спробі провести хендшейк, тому що для нього це частина стандартної процедури, що фіксується атакуючим. Не всякий TCP-SYN пакет з нульовим розміром корисного навантаження є ознакою сканування, але за традицією, що склалася, при установці з’єднання TCP клієнт зазвичай в першому ж пакеті висилає шматочок даних майбутнього запиту. Тому появи порожніх TCP-SYN є досить рідкісною подією. Поява таких пакетів на мережі у великій кількості вже можна вважати тривожним сигналом.
За допомогою утиліти snort дуже легко детектувати такі пакети, це можна зробити навіть не вдаючись до тонких налаштувань всієї системи SNORT, а просто вказавши утиліти правило прямо в командному рядку. Введемо наступну команду:
sniffer@sniffer:~ % snort -i bridge0 -A fast --rule 'alert tcp any any -> any any (flags:S; dsize:0; msg:"Possible NMAP TCP port scan"; sid: 1231213;)'
Відкриємо інше вікно терміналу на робочому ПК та виконаємо сканування TCP портів на IP адресі нашого IP-домофона за допомогою утиліти nmap :
rz@butterfly:~ % sudo nmap -v 192.168.168.139 Starting Nmap 7.94 ( https://nmap.org ) at 2025-07-12 18:12 +05 Initiating Ping Scan at 18:12 Scanning 192.168.168.139 [4 ports] ... PORT STATE SERVICE 22/tcp open ssh 80/tcp open http
Видно, що утиліта nmap виявила два відкритих порти: 22/tcp для SSH і 80/tcp для HTTP (Web-адмінка). Переключимося у вікно машини сніфера і спостерігаємо повідомлення наступного вигляду:
07/15-02:55:58.000929 [**] [1:1231213:0] "Possible NMAP TCP port scan" [**] [Priority: 0] {TCP} 192.168.176.155:62246 -> 192.168.168.139:4126
07/15-02:55:58.001269 [**] [1:1231213:0] "Possible NMAP TCP port scan" [**] [Priority: 0] {TCP} 192.168.176.155:62246 -> 192.168.168.139:24800
07/15-02:55:58.001488 [**] [1:1231213:0] "Possible NMAP TCP port scan" [**] [Priority: 0] {TCP} 192.168.176.155:62246 -> 192.168.168.139:7106
07/15-02:55:58.001674 [**] [1:1231213:0] "Possible NMAP TCP port scan" [**] [Priority: 0] {TCP} 192.168.176.155:62246 -> 192.168.168.139:2998
07/15-02:55:58.001842 [**] [1:1231213:0] "Possible NMAP TCP port scan" [**] [Priority: 0] {TCP} 192.168.176.155:62246 -> 192.168.168.139:60020
Вже непогано! Але таке однорядкове правило не може впоратися з більш витонченими видами сканування, наприклад з приманкою (decoy). Тому як ще один приклад розглянемо використання вбудованого в SNORT 3 плагіна з однойменною назвою «port_scan».
Як зазначалося раніше, SNORT 3 постачається з великою кількістю плагінів, серед яких є модуль port_scan. Цей плагін не охоплює всі можливі сценарії сканування, проте здатен виявляти значну частину їх різновидів.
Для перевірки роботи port_scan потрібно внести зміни до конфігураційного файлу утиліти snort, оскільки за замовчуванням цей плагін вимкнений, що передбачено з низки технічних причин. Запустимо редактор її так:
sniffer@sniffer:~ % sudo ee /usr/local/etc/snort/snort.lua
Знайдемо у файлі рядок, що містить установку змінної port_scan = , розкоментуємо її і надамо значення:
port_scan = default_hi_port_scan
Далі, шукаємо рядок ips = , розкоментуємо його та встановимо таке значення:
ips =
{
-- use this to enable decoder and inspector alerts
enable_builtin_rules = true,
}
Зберігаємо зміни і виходимо з ee . Запускаємо утиліту snort з наступними параметрами:
sniffer@sniffer:~ % snort -c /usr/local/etc/snort/snort.lua -i bridge0 -A fast
Після запуску утиліта snort здійснює читання та синтаксичну перевірку всіх своїх конфігураційних файлів (їх, до речі, може бути дуже багато), і підвантажує описані там правила. Наприкінці вона видає деяку статистику за завантаженими правилами:
--------------------------------------------------
pcre counts
pcre_rules: 1080
pcre_native: 1080
--------------------------------------------------
ips policies rule stats
id loaded shared enabled file
0 4862 1 4862 /usr/local/etc/snort/snort.lua
--------------------------------------------------
rule counts
total rules loaded: 4862
duplicate rules: 1
text rules: 4236
builtin rules: 626
option chains: 4862
chain headers: 948
flowbits: 48
flowbits not checked: 23
--------------------------------------------------
Після перевірки та завантаження конфігів, утиліта snort переходить у робочий режим. Тим часом відкриваемо нове вікно терміналу на своєму робочому ПК і за допомогою утиліти nmap намагаемось виконати кілька видів сканування тієї самої IP адреси:
# TCP-SYNC rz@butterfly:~ % sudo nmap -v 192.168.168.139 # UDP scan rz@butterfly:~ % sudo nmap -v -sU 192.168.168.139 # IP scan rz@butterfly:~ % sudo nmap -v -sO 192.168.168.139
Під час кожного запуску nmap у терміналі сніфера з’являються повідомлення, що відповідають конкретному типу виконуваного сканування. Це дає змогу наочно спостерігати, як різні режими nmap відображаються в мережевому трафіку:
07/12-21:06:02.701981 [**] [122:1:1] "(port_scan) TCP portscan" [**] [Priority: 3] {TCP} 192.168.168.139:5950 -> 192.168.176.155:61333
07/12-21:06:02.702141 [**] [122:1:1] "(port_scan) TCP portscan" [**] [Priority: 3] {TCP} 192.168.176.155:61333 -> 192.168.168.139:617
07/12-21:06:02.702208 [**] [122:1:1] "(port_scan) TCP portscan" [**] [Priority: 3] {TCP} 192.168.168.139:617 -> 192.168.176.155:61333
07/12-21:06:02.702372 [**] [122:1:1] "(port_scan) TCP portscan" [**] [Priority: 3] {TCP} 192.168.176.155:61333 -> 192.168.168.139:9009
07/12-21:06:02.702434 [**] [122:1:1] "(port_scan) TCP portscan" [**] [Priority: 3] {TCP} 192.168.168.139:9009 -> 192.168.176.155:61333
07/12-21:06:02.703011 [**] [122:1:1] "(port_scan) TCP portscan" [**] [Priority: 3] {TCP}
07/12-21:04:38.489675 [**] [122:17:1] "(port_scan) UDP portscan" [**] [Priority: 3] {UDP} 192.168.176.155:47076 -> 192.168.168.139:34578
07/12-21:04:38.489820 [**] [122:17:1] "(port_scan) UDP portscan" [**] [Priority: 3] {UDP} 192.168.176.155:47076 -> 192.168.168.139:17207
07/12-21:04:38.490334 [**] [122:17:1] "(port_scan) UDP portscan" [**] [Priority: 3] {ICMP} 192.168.168.139 -> 192.168.176.155
07/12-21:04:38.496755 [**] [122:17:1] "(port_scan) UDP portscan" [**] [Priority: 3] {UDP} 192.168.176.155:47076 -> 192.168.168.139:18821
07/12-21:04:39.660300 [**] [122:17:1] "(port_scan) UDP portscan" [**] [Priority: 3] {UDP} 192.168.176.155:47078 -> 192.168.168.139:18821
07/12-21:04:39.660512 [**] [122:17:1] "(port_scan) UDP portscan" [**] [Priority: 3] {UDP} 192.168.176.155:47078 -> 192.168.168.139:17207
07/12-21:03:56.396242 [**] [122:9:1] "(port_scan) IP protocol scan" [**] [Priority: 3] {ICMP} 192.168.168.139 -> 192.168.176.155
07/12-21:03:56.737086 [**] [122:9:1] "(port_scan) IP protocol scan" [**] [Priority: 3] {IP} 192.168.176.155 -> 192.168.168.139
07/12-21:03:57.064270 [**] [122:9:1] "(port_scan) IP protocol scan" [**] [Priority: 3] {IP} 192.168.176.155 -> 192.168.168.139
07/12-21:03:57.385228 [**] [122:9:1] "(port_scan) IP protocol scan" [**] [Priority: 3] {IP} 192.168.176.155 -> 192.168.168.139
Як уже зазначалося, утиліту snort можна налаштувати на відправлення попереджувальних повідомлень (alert) через протокол syslog на централізований сервер моніторингу або на запис таких подій у базу даних. Також можливе автоматичне блокування трафіку з IP-адрес, що генерують підозрілу активність.
Однак детальне налаштування цих можливостей виходить за рамки цього матеріалу й може бути самостійно опрацьоване читачем.
У цьому розділі наведено швидкі інструкції з розгортання мережевого моніторингу (сніфера). Було підготовлено завантажувальний образ операційної системи FreeBSD 14.3 та набір скриптів для автоматичного виконання всіх налаштувань, описаних у статті. Додатково створено короткий cheat-sheet і кілька супровідних інструкцій у форматі Markdown. Усі матеріали об’єднано в один репозиторій та опубліковано на GitHub для зручності використання.
Тому виконуємо команду: git clone https://github.com/pointcheck/sniffer.git та читаємо README.md.
Пряме посилання на завантажувальний образ: https://github.com/pointcheck/sniffer/raw/refs/heads/master/Sniffer-FreeBSD-14.3-bootable.img.xz
Потиснутий образ займає близько 1ГБ дискового простору.
1. Вставте вільний USB Flash накопичувач у порт USB Вашого робочого ПК. Потрібно накопичувач розміром не більше 5ГБ.
2. Розпакуйте завантажений образ і запишіть його на USB носій наступною командою:
Для ОС FreeBSD:
sudo sh -c "xz -d -c Sniffer-FreeBSD-14.3-bootable.img.xz | dd of=/dev/da0 bs=1m conv=sync status=progress"
Для Linux :
sudo sh -c "xz -d -c Sniffer-FreeBSD-14.3-bootable.img.xz | dd of=/dev/sdb bs=1m conv=sync status=progress"
Різниця тільки в іменуванні пристрою USB накопичувача. Користувачам Windows доведеться заморочитися з Rufus або аналогічною утилітою.
3. Після закінчення запису переставте USB накопичувач зі свого ПК в міні-ПК, з якого Ви збираєтеся зробити сніффер, і завантажте міні-ПК з цього USB носія. Сніффром може виступати будь-яка x86 сумісна машина з двома портами Ethernet, один з портів може бути зовнішнім USB-Ethernet. Не забудьте зайти в BIOS і встановити пріоритет завантаження з USB носія.
4. Після завантаження ОС FreeBSD зайдіть у систему під користувачем sniffer використовуючи пароль reffins . Про всяк випадок пароль root-а: 1234 . Поміняйте його на більш правильний, на Ваш погляд, командою passwd .
5. Запустіть скрипт для налаштування WiFi щоб мати віддалений доступ до машини сніфера:
sudo ./sniffer_setup_wifi.pl
Скрипт просканує радіоефір і покаже доступні SSID ідентифікатори WiFi точок, після чого попросить ввести ім’я однієї з них, потім попросить ввести пароль PSK . Скрип збереже ці дані /etc/wpa_supplicant.conf і перезапустить мережу.
6. Підключіть обидва Ethernet порти міні-ПК у розріз між досліджуваним пристроєм (DUT) та мережею за допомогою двох UTP патч-кордів. Запустіть скрипт для налаштування Ethernet Bridging:
sudo ./sniffer_setup_bridge.pl
Скрип відобразить наявні у Вашій системі мережні інтерфейси і попросить ввести імена мережевих інтерфейсів (по одному за раз), які потрібно об’єднати в мережевий міст. В результаті створить новий мережний інтерфейс bridge0 , додасть відповідні рядки до конфігураційного файлу /etc/rc.conf і перезапустить мережевий стек та сервіси. У цей момент, при підключенні через WiFi, у Вас може зникнути з’єднання з машиною.
7. Запустіть скрипт (опціонально) для налаштування mpd5 на організацію PPTP, L2TP та PPPOE тунелів для віддаленого підключення до машини сніфера з Інтернету:
sudo ./sniffer_setup_mpd5.pl
Скрипт попросить Вас вибрати тип тунелю (можна вибрати відразу всі три), вказати ім’я користувача, пароль та IP адресу сервера. В результаті скрипт створить конфігураційний файл /usr/local/etc/mpd5/mpd.conf і покладе поряд два скрипти ifup.sh та ifdown.sh .
Важливо! Цей скрипт налаштує систему використання кількох таблиць маршрутизації ( FIB), це стандартний спосіб в ОС FreeBSD організації ” source routing “. Необхідно це для того, щоб усі три тунелі не заважали один одному, тому що кожен з них матиме свій “default route”. Скрипт ifup.sh запускатиме копію sshd для обслуговування з’єднань лише заданого тунелю. Якщо у Вас налаштовані та підключені всі три типи тунелів, то в системі буде чотири копії sshd (одна копія системна, на нульовому FIB).
8. Перезавантажте машину сніфера командою:
sudo reboot
9. Ще раз увійдіть до системи (підключіться через ssh або з консолі). У Вашому розпорядженні утиліти tcpdump , tshark , trafshow та snort .
10. Короткий “cheat-sheet” знаходиться у файлі cheasheet.md . Переглянути вміст файлу можна командою:
more cheatsheet.md
11. Рекомендую підвісити «cheat-sheet» як «Message of The Day» щоб він відображався при кожному вході в систему. Зробити це можна наступною послідовністю команд: 12. Декілька інструкцій з типовими операціями знаходяться в .md файлах у каталозі користувача sniffer , прочитати їх можна наступними командами:
sudo cp cheatsheet.md /etc/motd.template sudo service motd restart
more rule_sip.md more rule_ssh.md more rule_http_password.md more snort.md
Після деякого часу роботи зі сніфером у Вас очікувано виникне бажання зробити свій (на базі поточної системи) завантажувальний образ для USB накопичувача. Зробити це допоможуть наступні два скрипти:
1. Щоб створити завантажувальний накопичувач USB на базі поточної системи, підключіться до машини сніфера, при цьому операційна система повинна бути завантажена з SSD або HDD ( /dev/ada0 ). Вставте вільний накопичувач USB і запустіть наступний скрипт:
sudo ./make_bootable_usb.sh
Цей скрип повністю знищить дані на USB, перестворить нову таблицю розділів, виконає розмітку файлових систем, додати EFI завантажувач і скопіює поточну систему.
Після виконання цього скрипту у Вас з’явиться ще один USB накопичувач.
2. Щоб зробити файл-образ ( .img.xz ) з цього USB накопичувача, який Ви зможете викласти на Github або поділитися ним з друзями, виконайте наступний скрипт:
sudo ./make_image.sh
У цій частині ми зібрали воєдино всі практичні інструменти, які перетворюють підготовлену платформу на справжній засіб мережевої діагностики. Розглянуті принципи створення Ethernet-мосту, варіанти підключення та схеми включення сніфера дозволяють адаптувати його під будь-які умови — від домашніх мереж до віддалених сценаріїв роботи через тунель. Використання BPF-фільтрів, tcpdump, tshark та аналіз окремих протоколів формують гнучку систему спостереження за трафіком, а інтеграція Snort дає можливість не лише спостерігати, а й виявляти підозрілу активність.
У підсумку виходить компактний, керований і доволі потужний інструмент, який легко масштабувати під власні задачі — діагностику несправностей, аналіз навантаження, виявлення аномалій або дослідження поведінки мережевих пристроїв. Цей підхід показує, що навіть на базі доступного обладнання й відкритих технологій можна створити професійний робочий інструмент, який нічим не поступається дорогим комерційним рішенням у своїй категорії.