Настройка IP Accounting

Поскольку IP accounting очень тесно связан с IP firewall, для их настройки используется одна программа. В зависимости от реализации это ipfwadm, ipchains или iptables. Синтаксис команды очень похож на используемый при задании правил firewall.

Общий синтаксис для IP accounting с ipfwadm:

# ipfwadm -A [direction] [command] [parameters]

Появился новый параметр direction. Он принимает значения in, out или both. Все значения считаются с точки зрения linux-машины, так что in задает входящий трафик, out задает исходящий трафик, а both оба типа сразу.

Общий синтаксис для ipchains и iptables:

# ipchains -A chain rule-specification
# iptables -A chain rule-specification

Команды ipchains и iptables позволяют Вам определять направление в стиле, больше похожем на определения правил. IP Firewall Chains не позволяет настроить правила для обоих направлений сразу, но позволяет настроить правила в наборе forward, чего старая реализация не умела.

Команды очень похожи на свои аналоги для правил firewall за исключением того, что стратегии здесь не применяются. Мы можем добавлять, вставлять, удалять и просматривать список правил учета. В случае ipchains и iptables, все имеющие силу правила считаются правилами для учета, и любая команда, которая не определяет опцию -j, выполняет только учет.

Параметры спецификации правила для учета IP такие же, как и для IP firewall.

Учет по адресам

Давайте на примере покажем, как мы использовали бы учет IP.

Допустим, у нас есть Linux-роутер, который обслуживает два департамента Virtual Brewery. Он имеет два устройства Ethernet, eth0 и eth1, по одному на департамент, и одно устройство PPP, ppp0, для связи через быстродействующую последовательную связь с университетским городком Groucho Marx University.

Для составления счетов мы хотим знать общее количество трафика, сгенерированного каждым из отделов по последовательной связи, и для целей управления мы хотим знать общий трафик между двумя отделами.

Следующая таблица показывает используемые нами адреса и интерфейсы:

Интерфейс Адрес Сетевая маска
eth0 172.16.3.0 255.255.255.0
eth1 172.16.4.0 255.255.255.0

Для ответа на вопрос, сколько данных каждый отдел передает по PPP, мы могли бы использовать правило, которое напоминает:

# ipfwadm -A both -a -W ppp0 -S 172.16.3.0/24 -b
# ipfwadm -A both -a -W ppp0 -S 172.16.4.0/24 -b
или:
# ipchains -A input -i ppp0 -d 172.16.3.0/24
# ipchains -A output -i ppp0 -s 172.16.3.0/24
# ipchains -A input -i ppp0 -d 172.16.4.0/24
# ipchains -A output -i ppp0 -s 172.16.4.0/24
или с iptables:
# iptables -A FORWARD -i ppp0 -d 172.16.3.0/24
# iptables -A FORWARD -o ppp0 -s 172.16.3.0/24
# iptables -A FORWARD -i ppp0 -d 172.16.4.0/24
# iptables -A FORWARD -o ppp0 -s 172.16.4.0/24

Первая половина каждого набора правил задает подсчет всех данных, передаваемых по интерфейсу ppp0 с исходным адресом или адресом назначения 172.16.3.0/24. Здесь полезна опция -b в ipfwadm и iptables. Вторая половина каждого набора правил задает то же самое, но для второй сети Ethernet.

Для ответа на вопрос, сколько трафика проходит между департаментами, нужно правило, которое выглядит следующим образом:

# ipfwadm -A both -a -S 172.16.3.0/24 -D 172.16.4.0/24 -b
или:
# ipchains -A forward -s 172.16.3.0/24 -d 172.16.4.0/24 -b
или:
# iptables -A FORWARD -s 172.16.3.0/24 -d 172.16.4.0/24
# iptables -A FORWARD -s 172.16.4.0/24 -d 172.16.3.0/24
Эти правила будут считать все пакеты с исходящими адресами сети одного департамента и адресом назначения в сети другого.

Учет по портам сервисов

Предположим, мы хотим также знать, какой именно трафик преобладает на связи через PPP. Например, надо выяснить, сколько данных проходит по протоколам FTP, smtp и World Wide Web.

Для сбора этой информации пригоден такой скрипт с правилами:

#!/bin/sh
# Collect FTP, smtp and www volume statistics for data carried on our
# PPP link using ipfwadm
#
ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 ftp ftp-data
ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 smtp
ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 www
или:
#!/bin/sh
# Collect ftp, smtp and www volume statistics for data carried on our
# PPP link using ipchains
#
ipchains -A input -i ppp0 -p tcp -s 0/0 ftp-data:ftp
ipchains -A output -i ppp0 -p tcp -d 0/0 ftp-data:ftp
ipchains -A input -i ppp0 -p tcp -s 0/0 smtp
ipchains -A output -i ppp0 -p tcp -d 0/0 smtp
ipchains -A input -i ppp0 -p tcp -s 0/0 www
ipchains -A output -i ppp0 -p tcp -d 0/0 www
или:
#!/bin/sh
# Collect ftp, smtp and www volume statistics for data carried on our
# PPP link using iptables.
#
iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport ftp-data:ftp
iptables -A FORWARD -o ppp0 -m tcp -p tcp --dport ftp-data:ftp
iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport smtp
iptables -A FORWARD -o ppp0 -m tcp -p tcp --dport smtp
iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport www
iptables -A FORWARD -o ppp0 -m tcp -p tcp --dport www

Здесь есть пара интересных свойств. Во-первых, мы определили протокол. Когда мы определяем порты в наших правилах, мы должны также определить протокол потому, что TCP и UDP имеют отдельные наборы портов. Так как все эти услуги основаны на TCP, мы определяем именно этот протокол. Во-вторых, мы определили два сервиса, ftp и ftp-data в одной команде. ipfwadm позволяет определять одиночные порты, диапазоны портов или произвольные списки портов. Команда ipchains позволяет определять любой одиночный порт или диапазон портов. Запись "ftp-data:ftp" означает "порты с ftp-data (20) по ftp (21)", так можно кодировать порты в ipchains и iptables. Когда вы имеете список портов в правиле учета, это означает, что любые данные для любого из портов в списке будут добавлены к общему количеству для этой записи. Поскольку FTP использует два порта, команды и данные, мы добавили их вместе к общему трафику FTP. Наконец, мы определили исходный адрес как 0/0, что соответствует всем адресам и требуется ipfwadm и ipchains для определения портов.

Теперь нас интересует соотношение полезного трафика по FTP, SMTP и World Wide Web к трафику по другим протоколам. Для этого зададим такие правила:

# ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 ftp ftp-data smtp www
# ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 1:19 22:24 26:79 81:32767

Если вы уже исследовали ваш файл /etc/services, вы увидите, что второе правило покрывает все порты за исключением (ftp, ftp-data, smtp и www).

Как сделать это с командами ipchains или iptables, ведь они позволяют только один параметр в спецификации порта? Мы можем эксплуатировать определяемые пользователем цепочки в учете так же легко, как в правилах firewall. Рассмотрим следующий подход:

# ipchains -N a-essent
# ipchains -N a-noness
# ipchains -A a-essent -j ACCEPT
# ipchains -A a-noness -j ACCEPT
# ipchains -A forward -i ppp0 -p tcp -s 0/0 ftp-data:ftp -j a-essent
# ipchains -A forward -i ppp0 -p tcp -s 0/0 smtp -j a-essent
# ipchains -A forward -i ppp0 -p tcp -s 0/0 www -j a-essent
# ipchains -A forward -j a-noness
Здесь мы создаем две определяемых пользователем цепочки: a-essent, где мы фиксируем данные для полезного трафика и a-noness, где мы собираем данные для всего остального. Затем добавим правила к цепочке forward, которые соответствуют полезным сервисам и задают переход в цепочку a-essent , которая только считает трафик. Последнее правило в нашей цепочке forward задает переход к цепочке a-noness, где тоже есть только одно правило, считающее трафик. Правило, которое переходит к цепочке a-noness, не будет достигнуто любым пакетом из полезных сервисов, поскольку они будут приняты в их собственной цепочке. Наши счетчики для полезных и остальных услуг будут доступны только в правилах внутри тех цепочек. Это только один подход, который вы могли бы избрать. Реализация того же самого подхода для iptables:
# iptables -N a-essent
# iptables -N a-noness
# iptables -A a-essent -j ACCEPT
# iptables -A a-noness -j ACCEPT
# iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport ftp-data:ftp -j a-essent
# iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport smtp -j a-essent
# iptables -A FORWARD -i ppp0 -m tcp -p tcp --sport www -j a-essent
# iptables -A FORWARD -j a-noness

Это выглядит достаточно простым. К сожалению, имеется маленькая, но неизбежная проблема при попытке делать учет сервисным типом. Мы обсуждали в одной из предыдущих глав роль MTU в работе с сетями TCP/IP. MTU определяет самый большой пакет, который будет передан на сетевое устройство. Когда пакет получен маршрутизатором, и этот пакет больше, чем MTU интерфейса, который должен его передать, маршрутизатор выполняет фрагментацию (fragmentation). Маршрутизатор разбивает большой пакет на маленькие части не больше, чем MTU интерфейса, и затем передает эти части. Маршрутизатор формирует новые заголовки для получившихся пакетов, по которым получатель сможет восстановить исходный пакет. К сожалению, в течение фрагментации значение порта будет потеряно для всего, кроме первого фрагмента. Это означает, что учет IP не может правильно считать фрагментированные пакеты, а только первые фрагменты или нефрагментированные пакеты. Имеется маленькая хитрость ipfwadm, которая позволяет считать пакеты, даже не зная порт второго и последующих фрагментов. Первая версия программного обеспечения Linux accounting назначала фрагментам поддельный номер порта 0xFFFF, который мы могли перехватывать для учета. Мы фиксируем вторые и последующие фрагменты, используя правило:

# ipfwadm -A both -a -W ppp0 -P tcp -S 0/0 0xFFFF

Реализация IP chains имеет немного более сложное решение, но результат тот же самый. При использовании команды ipchains надо использовать правило:

# ipchains -A forward -i ppp0 -p tcp -f
Для iptables подойдет правило:
# iptables -A FORWARD -i ppp0 -m tcp -p tcp -f

Это правило не будет сообщать нам, каков первоначальный порт для этих данных, но по крайней мере мы способны видеть, сколько из наших данных являются фрагментами.

В ядрах 2.2 вы можете выбирать при настройке ядра опцию, которая решает эту проблему, если ваша Linux-машина действует как одиночная точка доступа к сети. Если вы включили при построении ядра опцию IP: always defragment, все пакеты будут повторно собраны маршрутизатором Linux перед маршрутизацией и передачей. Эта операция выполняется перед firewall, и учетный блок видит пакеты. Таким образом, фрагментов просто не будет. В ядрах 2.4 откомпилируйте и загрузите netfilter с модулем forward-fragment.

Учет по пакетам ICMP

Протокол ICMP не использует сервисные номера портов, так что сбор статистики по нему труднее. ICMP использует ряд различных типов пакетов. Многие из их безобидны и нормальны, в то время, как другие появляются только при специальных обстоятельствах. Иногда пытаются обвалить систему, посылая огромное число пакетов ICMP. Эта атака называется ping flooding. Против такой атаки хорош IP firewall, а IP accounting позволит узнать, кто это сделал.

ICMP не использует порты в отличие от TCP и UDP. Вместо них используются типы сообщений ICMP. Мы можем создать правила, чтобы учитывать каждый тип сообщений ICMP. Для этого нужно определить тип сообщения ICMP вместо номера порта в команде ipfwadm. Типы сообщений перечислены в разделе "Типы пакетов ICMP" главы 9.

Для сбора данных о передаче пакетов ICMP по всем типам сообщений используйте правило:

# ipfwadm -A both -a -P icmp -S 0/0 8
# ipfwadm -A both -a -P icmp -S 0/0 0
# ipfwadm -A both -a -P icmp -S 0/0 0xff
или в ipchains:
# ipchains -A forward -p icmp -s 0/0 8
# ipchains -A forward -p icmp -s 0/0 0
# ipchains -A forward -p icmp -s 0/0 -f
или в iptables:
# iptables -A FORWARD -m icmp -p icmp --sports echo-request
# iptables -A FORWARD -m icmp -p icmp --sports echo-reply
# iptables -A FORWARD -m icmp -p icmp -f
Первое правило собирает информацию относительно пакетов ICMP Echo Request (ping requests), второе правило собирает информацию относительно пакетов ICMP Echo Reply (ping replies). Третье правило собирает информацию относительно фрагментированных пакетов ICMP. Этот прием подобен описанному для фрагментированных пакетов TCP и UDP.

Если Вы определяете источник и/или адресата в ваших правилах, Вы можете следить, откуда приходят пакеты, изнутри сети или снаружи.

Учет по протоколам

Допустим, нам интересно, какие протоколы используются нашим трафиком: TCP, UDP или ICMP. Тут нам поможет правило:

# ipfwadm -A both -a -W ppp0 -P tcp -D 0/0
# ipfwadm -A both -a -W ppp0 -P udp -D 0/0
# ipfwadm -A both -a -W ppp0 -P icmp -D 0/0
или:
# ipchains -A forward -i ppp0 -p tcp -d 0/0
# ipchains -A forward -i ppp0 -p udp -d 0/0
# ipchains -A forward -i ppp0 -p icmp -d 0/0
или:
# iptables -A FORWARD -i ppp0 -m tcp -p tcp
# iptables -A FORWARD -o ppp0 -m tcp -p tcp
# iptables -A FORWARD -i ppp0 -m udp -p udp
# iptables -A FORWARD -o ppp0 -m udp -p udp
# iptables -A FORWARD -i ppp0 -m icmp -p icmp
# iptables -A FORWARD -o ppp0 -m icmp -p icmp
С этими правилами трафик через интерфейс ppp0 будет проанализирован, чтобы определить тип протокола: TCP, UDP или IMCP, и соответствующие счетчики будут модифицированы для каждого пакета.