В Интернете представлено довольно мало информации о том, как можно простым способом организовать port mirroring на базе FreeBSD. Такая задача может встать перед администраторами крупных ресурсов, для организации анализа трафика другим хостом. Поэтому, я и решил написать эту короткую заметку.
В данной статье будет рассмотрена только принципиальная организация mirroring-а средствами netgraph. В качестве примера, рассмотрим, как можно реализовать это средствами модуля one2many и eiface - виртуального сетевого интерфейса. Очевидно, в "боевых" условиях, копировать трафик требуется на реальный интерфейс, это также будет затронуто в статье.
Прежде всего, убедимся, что ядро собрано с поддержкой netgraph:
$ grep NETGRAPH$ /sys/conf/options
Далее запустим утилиту ngctl для конфигурации netgraph. В нашем случае, будем отображать трафик re0 на виртуальный интерфейс. Для понимания работы с ngctl были добавлены комментарии, начинающиеся с символа '#'. Такой формат комментариев не поддерживается утилитой ngctl, поэтому не стоит их туда копировать.
# создадим ноду one2many, которая будет копировать трафик
# и подключим её к хуку lower целевого интерфейса (re0)
+ mkpeer re0: one2many lower one
# посмотрим список нод. Обращаться к созданной ноде можно по ID [2f]
+ list
There are 7 total nodes:
Name: re0 Type: ether ID: 00000001 Num hooks: 1
Name: re1 Type: ether ID: 00000002 Num hooks: 0
Name: re2 Type: ether ID: 00000003 Num hooks: 0
Name: tap0 Type: ether ID: 00000008 Num hooks: 0
Name: vboxnet0 Type: ether ID: 00000009 Num hooks: 0
Name: ngctl75459 Type: socket ID: 0000002e Num hooks: 0
Name: <unnamed> Type: one2many ID: 0000002f Num hooks: 1
# для простоты переименуем ноду в mirr
+ name [2f]: mirr
# посмотрим результат
+ list
There are 7 total nodes:
Name: re0 Type: ether ID: 00000001 Num hooks: 1
Name: re1 Type: ether ID: 00000002 Num hooks: 0
Name: re2 Type: ether ID: 00000003 Num hooks: 0
Name: tap0 Type: ether ID: 00000008 Num hooks: 0
Name: vboxnet0 Type: ether ID: 00000009 Num hooks: 0
Name: ngctl75459 Type: socket ID: 0000002e Num hooks: 0
Name: mirr Type: one2many ID: 0000002f Num hooks: 1
# посмотрим хуки ноды mirr
+ show mirr:
Name: mirr Type: one2many ID: 0000002f Num hooks: 1
Local hook Peer name Peer type Peer ID Peer hook
---------- --------- --------- ------- ---------
one re0 ether 00000001 lower
# сразу не забудем вернуть входящий трафик в ядро ;)
+ connect mirr: re0: many0 upper
# создадим виртуальный интерфейс и подключим его хук ether к хуку many1 ноды mirr
+ mkpeer mirr: eiface many1 ether
# посмотрим хуки ноды mirr теперь
+ show mirr:
Name: mirr Type: one2many ID: 0000002f Num hooks: 3
Local hook Peer name Peer type Peer ID Peer hook
---------- --------- --------- ------- ---------
many0 re0 ether 00000001 upper
many1 ngeth0 eiface 00000030 ether
one re0 ether 00000001 lower
+
Готово! Теперь сетевой трафик копируется на виртуальный интерфейс ngeth0. Для его прослушивания можно воспользоваться командой
$ tcpdump -pni ngeth0
И на десерт: простая команда для netgraph, позволяющая отображать трафик на реальный интерфейс. Как вы уже наверное догадались, после включения ноды one2many в граф, для отображения трафика с re0 например на re1, нужно подключить хук re1:lower к mirr:many2. Это можно сделать вот такой командой:
+ connect re1: mirr: lower many2
После выполнения которой, трафик сразу начинает копироваться в интерфейс re1. Данное действие необходимо выполнять внимательно, т.к. если в качестве выходного интерфейса выбрать боевой, соединение с сервером будет мгновенное утеряно. Всем удачного port mirroring-а!