IPA.CONF(5) IPA.CONF(5)
НАИМЕНОВАНИЕ
ipa.conf -- конфигурационный файл для ipa(8)
ОПИСАНИЕ
Файл ipa.conf это конфигурационный файл для ipa(8). Этот файл или
любой-другой файл, указанный в опции -f в командной строке ipa(8),
обрабатывается когда ipa(8) начинает работать или получает сигнал
SIGHUP.
ФОРМАТ ФАЙЛА
Файл ipa.conf может быть достаточно простым и довольно сложным. Глав-
ная идея заключается в том, чтобы разместить как можно больше установок
в одном конфигурационном файле(ах), вместо того чтобы использовать
внешние программы для решения задач связанных с обработкой статистики.
Эта страница документации содержит полное описание формата конфигураци-
онного файла и полную документацию о всех возможностях ipa(8).
Почти после каждого параграфа приведен пример. Так как IPA пакет не
содержит каких-либо модулей, то в примерах используются модули
ipa_ipfw, ipa_ip6fw, ipa_atest и ipa_db_sdb, только лишь потому, что
это были первые модули учёта и базы данных, разработанные для IPA.
Общий синтаксис.
Любая логическая строка в конфигурационном файле может быть записана в
несколько текстовых строках для улучшения читаемости конфигурации. Нет
никакого правила в какой строке размещать зарезервированные слова,
аргументы или специальные символы. Если формат позволяет использовать
один пробел символ (пробел или символ табуляции), то можно использовать
столько пробелов, сколько необходимо для улучшения форматирования кон-
фигурационного файла. Все элементы в конфигурационном файле регистроза-
висимые. Конфигурационный файл состоит из секций, параметров и коммен-
тариев.
Комментарии.
Существуют shell-подобные и C-подобные комментарии. Если вы используете
C-подобный комментарий в shell-подобном комментарии, то C-подобный ком-
ментарий игнорируется.
Пример:
# Shell-подобный комментарий.
/* C-подобный комментарий. */
/*
* Другой C-подобный комментарий.
*/
Секции и параметры.
Секция состоит из имени секции, опциональных аргументов и тела секции.
Тело секции должно быть заключено в фигурные скобки:
секция [[=] аргумент] {
/* Параметры и секции. */
}
Параметр состоит из имени и опциональных аргументов. Каждый параметр
должен заканчиваться символом `;' в конце списка своих аргументов:
параметр [[=] аргумент];
Символ `=' после имени секции и параметра опционален. Некоторые пара-
метры похоже на переменные (для таких параметров естественно использо-
вать символ `='), другие похожи на инструкции. В любом случае, в можете
выбрать синтаксис, который вам наиболее подходит.
Аргумент может содержать строки:
"строка"
Возможно использовать последовательности ``\t'', ``\n'', ``\\'' и
``\"'', чтобы представить символ табуляции, символ новой строки, обрат-
ный слэш и двойную кавычку внутри строки. Если необходимо разделить
строку на несколько линий (строк в файле), то используйте символ `\' в
конце текущей линии (не добавляйте лишних пробелов после обратного
слэша). Если строка записана в несколько линий без символов `\', то
каждый символ новой строки добавляется в строку.
Макропеременные.
Возможно определить макропеременные и использовать их почти где угодно
в конфигурационном файле:
${переменная} = "строка";
Имя любой макропеременной может состоять из букв, цифр и знака доллара.
Что является буквой определяется функцией isalpha(3), которая исполь-
зует локаль.
Значением любой макропеременной должно быть строка, когда макроперемен-
ная расширяется, то первый и последний символы двойной кавычки убира-
ются.
Макропеременные могут быть локальными или глобальными. Макропеременная
является глобальной, если она определена вне какой-либо секции, иначе
макропеременная является локальной для всех вложенных секций и для всех
внешних секции. Локальные макропеременные скрывают глобальные макропе-
ременные.
Есть несколько предопределённых макропеременных:
${$} - расширяется в символ `$';
${rule} - расширяется в имя текущей секции rule;
${limit} - расширяется в имя текущей секции limit;
${sublimit} - расширяется в имя текущей секции sublimit;
${threshold} - расширяется в имя текущей секции threshold;
${autorule} - расширяется в имя текущей секции autorule.
Любая макропеременная (включая предопределённые), за исключением ${$},
по необходимости может быть переопределена. Не рекомендуется переопре-
делять или уничтожать макропеременные в модулях.
Макропеременная ${$} не может быть использована для конструирования
имён макропеременных (см. пример).
Макропеременные расширяются в момент их использования, а не в момент их
определения. Макропеременные также расширяются в строках. Расширение
макропеременных это свойство внутреннего парсера конфигурационного
файла, поэтому макропеременная ${rule} не может быть использовано в
автоправилах и шаблонах правил (см. информацию о подстановках в команд-
ных строках).
Пример:
${a} = "${b}"; # Определение ${a}.
${b} = "1"; # Определение ${b}.
param = ${a}; # Расширяется в 1.
${b} = "2"; # Переопределение ${b}.
param = ${a}; # Расширяется в 2.
param = "${$}{b}"; # Расширяется в ${b} (последовательность
# символов внутри строки).
section {
${a} = "1"; # Определение локальной ${a}, которая
# скрывает глобальную ${a}.
${c} = "4"; # Определение локальной ${c}.
param = ${a}; # Расширяется в 1.
subsection {
${a} = "2";# Переопределение локальной ${a}.
${b} = "3";# Переопределение глобальной ${b}.
}
param = ${a}; # Расширяется в 2.
param = ${b}; # Расширяется в 3.
}
# param = ${c}; <-- Ошибка: ${c} не определена как глобальная.
Включение файлов.
Возможно хранить конфигурацию в нескольких файлах. Файлы могут быть
включены при помощи следующих параметров:
include "/путь/файл";
include_files "/директория/шаблон";
Параметр include включает один файл. Параметр include_files включает
несколько файлов из указанной директории, имена которых совпадают с
указанным шаблоном.
Эти параметры могут быть использованы где угодно, за исключением секций
модулей. Возможно включать файлы из включённых файлов и т.д. Каждый
включённый файл должен содержать корректно определённые параметры с
аргументами, комментарии и секции с аргументами, но он может содержать
незакрытые секции.
Возможно использовать регулярные выражения POSIX (расширенный формат) в
качестве шаблонов в параметрах include_files, для этого установите
параметр posix_re_pattern в ``yes'' перед параметрами, которые включают
файлы с регулярными выражениями POSIX в качестве шаблонов, по умолчанию
значение этого параметра равно ``no'':
posix_re_pattern = <boolean>;
Этот параметр не должен располагаться в какой-либо секции.
Включаемые файлы должны иметь того владельца, кто запустил ipa(8) и не
должны иметь прав на запись для группы и остальных пользователей. Если
файлы включаются с помощью параметра include_files, то и директория
указанная в этом параметре тоже должна иметь те же свойства.
Пример:
posix_re_pattern = yes;
include "/usr/local/etc/ipa.local.conf";
include_files "/usr/local/etc/ipa/LAN/.";
Первый параметр включает один файл, второй параметр включает каждый
файл в данной директории, регулярное выражение POSIX ``.'' означает
любой символ.
/* posix_re_pattern = no; */
include_files "/usr/local/etc/ipa/LAN/*";
Здесь используется шаблон shell. Первую строку необходимо раскомменти-
ровать, если перед этим использовались регулярные выражения POSIX.
Использование модулей учёта.
Существуют специальные модули учёта, которые используются для сбора
статистики. ipa(8) использует эти внешние модули учёта с помощью специ-
ального ipa_ac_mod API, описанного в странице документации ipa_mod(3).
Параметр ac_mod сообщает ipa(8), что необходимо загрузить заданный IPA
модуль учёта:
ac_mod "имя_файла";
Этот параметр не должен располагаться в какой-либо секции. Возможно
использовать несколько модулей учёта одновременно.
Пример:
ac_mod "ipa_ipfw.so";
ac_mod "ipa_ip6fw.so";
Эти параметры загружают два модуля учёта.
Использование модулей баз данных.
Существуют специальные модули баз данных, которые используются для
того, чтобы сохранить статистику в базах данных. ipa(8) использует эти
внешние модули баз данных с помощью специального ipa_db_mod API, опи-
санного в странице документации ipa_mod(3).
Параметр db_mod сообщает ipa(8), что необходимо загрузить заданный IPA
модуль базы данных:
db_mod "имя_файла";
Этот параметр не должен располагаться в какой-либо секции. Возможно
использовать несколько модулей баз данных одновременно.
Пример:
db_mod "ipa_db_sdb.so";
Этот параметр загружает один модуль базы данных.
Конфигурирование модулей.
Документация для IPA модуля должна давать всю информацию как конфигури-
ровать модуль, но обычно конфигурация IPA модуля интегрируется в конфи-
гурационный файл ipa.conf(5).
Каждый модуль имеет конфигурационный префикс, который используется для
того, чтобы отличать секции и параметры модуля. Если параметр записан в
форме:
префикс:параметр [[=] аргумент];
то ipa(8) попытается найти загруженный модуль с конфигурационным пре-
фиксом ``префикс'', затем передаст этот параметр для разбора найденному
модулю.
Секции также могут иметь префиксы:
префикс:секция [[=] аргумент] {
/* Параметры и секции модуля. */
}
В этом случае параметры и секции внутри такой секции должны быть запи-
саны без префикса и они будут переданы соответствующему модулю для
обработки.
Документация для модуля должна описывать сам модуль, конфигурационный
префикс модуля, имя базы данных или системы учёта и все секции и пара-
метры модуля.
Пример:
sdb: {
allow_symlinks = yes;
}
ipfw:debug_ipfw = 1;
Приведенное имя секции может показаться несколько странным, но здесь
всё правильно. Модуль может иметь нулевые имена секций и параметров.
Правила учёта статистики.
ipa(8) выполняет учёт статистика основываясь на правилах. Существуют
два типа правил: статические и динамические. Статическое правило опре-
деляется в секции rule. Динамическое правило не имеет описания в конфи-
гурационном файле, но любое динамическое правило генерируется на лету
из некоторого автоправила, определённого в секции autorule.
Несколько правил (статических, динамических) могут разделять одни и те
же установки. Существует несколько путей это сделать. Первый путь это
использование секции global. Второй путь это использование секций
rulepat (шаблоны правил). И третий путь это определение общих установок
для динамических правил в секциях autorule.
Если какое-то правило (статическое, динамическое) не содержит установок
для какой-то секции или параметра (динамические правила также наследуют
установки от своих автоправил), то наследуются установки из подходящей
секции rulepat, далее наследуются установки из секции global, если
некоторые секции или параметра всё ещё не определены, то используются
установки по умолчанию. Запустите ipa(8) с ключами -tt, чтобы увидеть
реальные значения всех параметров.
Следующие параметры могут быть использованы в секциях global, rulepat,
rule и autorule: ac_list, db_list, append_time, update_time, worktime,
ctl_rule_acl, debug_exec, debug_limit, debug_limit_init, debug_thresh-
old, debug_threshold_init.
Использование систем учёта.
Выше был определён параметр ac_mod, который сообщает, что необходимо
загрузить модуль и позволяет этому модулю обрабатывать свою конфигура-
цию. Параметр ac_list определяет список используемых систем учёта:
ac_list = <список>;
<Список> это набор имён, разделённых пробелами. Чтобы получить имена
систем учёта, прочтите документацию для модулей, которые вы указали в
параметрах ac_mod.
Если какое-то правило содержит параметр ac_list, то системы учёта,
перечисленные в его значении, будут опрашиваться для получения стати-
стики для этого правила. Этот параметр позволяет создавать список
систем учёта для каждого правила по отдельности.
Существует одна встроенная в ipa(8) система учёта null: эта система
учёта всегда возвращает в качестве статистики 0. Если параметр ac_list
не определён, то используется система учёта null.
Пример:
ac_mod "ipa_ipfw.so";
ac_mod "ipa_ip6fw.so";
global {
ac_list = ipfw ip6fw;
}
Здесь определены две системы учёта.
Использование баз данных.
Выше был определён параметр db_mod, который сообщает, что необходимо
загрузить модуль и позволяет этому модулю обрабатывать свою конфигура-
цию. Параметр db_list определяет список используемых баз данных:
db_list = <список>;
<Список> это набор имён, разделённых пробелами. Чтобы получить имена
баз данных, прочтите документацию для модулей, которые вы указали в
параметрах db_mod.
Если какое-то правило (лимит, порог) содержит параметр db_list, то базы
данных, перечисленные в его значении, будут использовать для сохранения
статистики для этого правила (лимита, порога). Этот параметр позволяет
создавать список баз данных для каждого правила (лимита, порога) по
отдельности.
Существует одна встроенная в ipa(8) база данных null: все данные,
посланные в эту базу данных, сразу же исчезаю. Если параметр db_list не
определён, то используется база данных null.
Пример:
db_mod "ipa_db_sdb.so";
global {
db_list = sdb;
}
Здесь определена одна база данных.
Учёт статистики по временным интервалам недели.
По умолчанию ipa(8) выполняет учёт статистики для всех дней недели, но
существует возможность выполнять учёт статистики только для некоторых
временных интервалов. Параметр worktime определяет временные интервалы,
когда ipa(8) должна выполнять учёт статистики:
worktime = <X> h1:m1-h2:m2 [h1:m1-h2:m2];
worktime = <X> *;
<X> обозначает день недели. Допустимые значения для <X> следующие: `S'
воскресенье, `M' понедельник, `T' вторник, `W' среда, `H' четверг, `F'
пятница, `A' суббота. Может быть только одна запись для каждого дня.
Временные интервалы не должны перекрываться или быть расположенными не
по порядку.
Временной интервал 00:00-24:00 или символ `*' обозначает целый день.
Когда worktime разрешает выполнять учёт статистики, то секция в которой
он располагается называется ``активной'', иначе она называется ``неак-
тивной''.
Что конкретно этот параметр определяет для автоправил, правил, лимитов
и порогов читайте в соответствующих параграфах.
Заметьте, что интервалы заданные в параметре worktime не гарантируют,
что точно такие же временные интервалы окажутся в базе данных, так как
запущеная копия ipa(8) может иметь низкий приоритет или система может
быть слишком нагруженной.
Конец одного временного интервала может быть началом следующего времен-
ного интервала, это свойство полезно только для правил (см. ниже).
Пример:
Выполнять учёт статистики только по понедельникам, вторникам и средам:
worktime = M * T * W *;
Выполнять учёт статистики в четверг с 8:00 до 14:30 и с 18:20 до 21:00,
в воскресенье с полуночи до 10:35 (значение записано в нескольких стро-
ках только для выравнивания):
worktime = H 08:00-14:30 18:20-21:00
S 00:00-10:35;
Временные интервалы базы данных.
Параметр update_time определяет временные интервалы, когда ipa(8)
должна обновлять статистику для правила:
update_time = <время>;
Если этот параметр не указан, то значение по умолчанию равно 1 минуте.
Параметр append_time определяет временные интервалы, когда ipa(8)
должна добавить новую запись в базы данных для правила:
append_time = <время>;
Этот параметр не имеет значения по умолчанию. Новая учётная запись для
каждого правила добавляется в базу данных в конце каждого дня в любом
случае.
Обычно значение параметра append_time больше чем значение параметра
update_time.
ipa(8) пытается скомбинировать несколько временных событий в одно чтобы
уменьшить использование ресурсов, это свойство имеет другой интересный
момент, например, если update_time равен 5 минутам, то ipa(8) всегда
планирует временные события для этого параметра в 00:00, 00:05, 00:10 и
т.д.
Существуют программы, тикие как date(1) или ntpdate(8), которые могут
изменять UTC или локальное время, также временная зона может быть изме-
нена сама по себе. Эти события могут вызвать не критические ошибки типа
``some time related problems occurred'' в ipa(8). Параметры update_time
и append_time могут вызвать больше подобных ошибок. Например, если вы
вызываете ntpdate(8) очень часто и значение параметра update_time почти
равно временному интервалу вызовов ntpdate(8), то вы можете получить
множество предупреждающих сообщений от ipa(8).
Возможно указать насколько временные события чувствительны к изменениям
времени в параметре:
sensitive_time = <время>;
По умолчанию значение этого параметра равно 30 секундам. Этот параметр
не должен располагаться в какой-либо секции.
Параметр wakeup_time определяет максимальное число секунд, которое
может спать ipa(8). Этот параметр сообщает ipa(8) когда необходимо про-
будиться и проверить всё ли в порядке с временем, временной зоной и
т.п.:
wakeup_time = <время>;
По умолчанию значение этого параметра равно 10 минутам. Этот параметр
не должен располагаться в какой-либо секции.
Пример:
global {
update_time = 30s;
append_time = 1h 30m;
}
Символ `s' обозначает секунды, `m' минуты, `h' часы (пробелы опцио-
нальны). Если <время> определено как составное значение, то часы
должны быть указаны перед минутами и секундами, а минуты перед секун-
дами.
Описание правил, лимитов и порогов.
Секции rule, limit и threshold могут иметь параметр info, который пере-
даётся базе данных и используется для описания секции:
info = "<строка>";
Значение этого параметра не должно содержать символов `\n' и `\t'.
Обычно это значение должно помочь вспомнить для чего используется то
или иное правило, лимит или порог. Например, это значение выводится
программой ipastat(8).
Динамические правила получают своё описание от модулей учёта, которые
их генерируют, поэтому вы не можете указать описания динамических пра-
вил в конфигурационном файле.
Пример:
rule 10.1.2.3-in {
info = "Мой трафик от ISP";
/* ... */
}
Иногда имя правила не очень информативно, поэтому описание правила это
хорошая идея.
Статические правила.
Статические правила называются ``статическими'' потому, что они суще-
ствуют в конфигурационном файле и ни один модуль учёта не может уничто-
жить их (динамические правила могут быть уничтожены).
Секция rule описывает установки для одного статического правила:
rule <имя-правила> {
/* Параметры и секции правила. */
}
Необходимо давать такие имена правилам, которые также являются коррект-
ными именами правил для используемой вами базы данных.
Секция rule не требует каких-либо обязательных установок. Если какое-то
правило не содержит ни одной секции и параметра, то оно называется
пустым правилом. Очевидно, что такие правила бессмысленны, поэтому
любое правило имеет несколько параметров (собственные или наследован-
ные).
Если правило содержит параметр worktime, то новая запись о статистике
добавляется в базу данных с началом каждого нового временного интер-
вала. Если правило неактивно, то все её лимиты и пороги также неак-
тивны.
Пример:
ac_mod "ipa_ipfw.so";
ac_mod "ipa_ip6fw.so";
db_mod "ipa_db_sdb.so";
rule local.traf {
ac_list = ipfw ip6fw;
db_list = sdb;
info = "Входящий трафик для моей LAN";
sdb:db_group = staff;
ipfw:rules = 100 200 300;
ip6fw:rules = 1.10;
}
Здесь правило использует две системы учёта и одну базу данных. Оно
также имеет описание и несколько настроек для модулей.
Запуск команд.
Существует несколько секций позволяющие определить список команд, кото-
рые должны быть запущены если произойдёт некоторое событие.
Параметр exec используется для запуска команд:
exec [<пользователь>] "/path/command";
Параметр exec без <пользователя> запускает команду с привилегиями поль-
зователя запустившего ipa(8), т.е. не предпринимаются никакие действия
по смене пользователя или группы пользователя для запускаемой команды.
Параметр exec с <пользователем> запускает команду с привилегиями задан-
ного пользователя. Пользователь может быть задан только по имени.
ipa(8) определит UID и GID (группы) пользователя в момент запуска
команды. Этот параметр может быть использован если ipa(8) запущена
супер-пользователем.
Возможно использовать макропеременные (включая предопределённые) в
командных строках (как и в любых строках). Если необходимо использовать
имя правила в какой-то команде в секции rulepat или autorule, то нужно
воспользоваться подстановками. Определены две подстановки:
%rule% Имя правила.
%% Символ `%'.
Эти подстановки не работают в командных строках, расположенных в сек-
циях rule, вместо этого используйте макропеременную ${rule}.
По умолчанию команды должны быть заданы с абсолютными путевыми именами,
но возможно задавать команды с относительными именами, установив пара-
метр only_abs_paths в ``no'', по умолчанию значение этого параметра
равно ``yes'':
only_abs_paths = <boolean>;
Все команды запускаются с помощью shell, поэтому могут быть указаны
любые конструкции командной строки:
<shell_path> <shell_arg1> /path/command
Заметьте, что стандартный ввод (stdint), стандартный вывод (stdout) и
стандартный поток ошибок (stderr) обрабатываются также как и в ipa(8).
<Shell_path> определяется когда IPA компилируется, обычно это /bin/sh
(см. реальный путь в выводе команды ``ipa -v''), но возможно точно ука-
зать путь к оболочке в конфигурационном файле с помощью параметра
shell_path:
shell_path = "/path/shell";
<Shell_arg1> по умолчанию равен ``-c'', но он может быть переопределён
в параметре shell_arg1:
shell_arg1 = "<arg1>";
Если нет достаточно ресурсов и ipa(8) не в состоянии, например, запу-
стить потомка (ошибка вызова fork(2)), то ipa(8) завершит свою работу с
кодом ошибки. Но если какая-то ошибка возникнет в потомке, который
запускает команды, то ipa(8) проигнорирует эти ошибки и потомок просто
отправит предупреждающие сообщения в лог.
Параметры only_abs_paths, shell_path и shell_arg1 не должены распола-
гаться в какой-либо секции.
Пример:
startup {
exec "/bin/echo \"ipa started\" | mail me";
exec nobody "/usr/local/bin/something";
}
only_abs_path = no;
shutdown {
exec "echo \"ipa stopped\" | mail me";
}
rulepat "^client" {
startup {
exec "command %rule%";
}
}
rule 1 {
shutdown {
exec "echo rule off >> /tmp/${rule}.log";
}
}
В первой секции команда ``mail'' задана без абсолютного путевого имени.
Это корректно, так как только первая команда проверяется на абсолютное
путевое имя, ipa(8) не интерпретирует конструкции командной строки обо-
лочки.
Для включения имени правила в командную строку в секции rulepat исполь-
зуется подстановка %rule%, в секции rule используется макропеременная
${rule}.
Запуск команд при старте и завершении работы.
В секции startup (shutdown) можно определить команды, которые должны
быть запущены, когда ipa(8) начинает (завершает) свою работу. Эти сек-
ции могут располагаться самостоятельно (глобальные команды) и в секциях
autorule, rulepat, rule, limit, sublimit и threshold.
Если эти секции располагаются самостоятельно (см. использование этих
секций в других секциях), то они могут содержать только параметры exec
и sync_exec.
Алгоритм запуска команд из секций startup (shutdown) следующий:
1 запустить глобальные команды;
2 запустить команды из секций rule;
2а в каждой секции rule запустить команды для лимитов и порогов;
2б в каждой секции limit запустить команды для подлимитов.
Когда ipa(8) перечитывает конфигурационный файл (когда она получает
сигнал SIGHUP), тогда команды в секциях startup игнорируются, но будут
использоваться новые команды для секций shutdown. Если необходимо
запустить некоторые команды из секций startup, то их можно запустить
при помощи опции ipa(8) -x.
Пример:
startup {
exec "command1";
}
rule 1 {
startup {
exec "command2";
}
limit 1 {
/* ... */
startup {
exec "command3";
}
}
}
rule 2 {
startup {
exec "command4";
}
}
Здесь команды запускаются в следующем порядке: command1, command2, com-
mand3 и command4.
Синхронный и асинхронный запуск команд.
Существует два режима запуска команд: синхронный и асинхронный. В син-
хронном режиме ipa(8) ждёт завершения запущенных команд. В асинхронном
режиме ipa(8) запустив команды, не ждёт завершения запущенных команд, а
продолжает свою работу.
По умолчанию команды во всех секциях startup и shutdown запускаются
синхронно, во всех остальных секциях команды запускаются асинхронно.
Параметр sync_exec позволяет определить асинхронный или синхронный
режим для любой секции:
sync_exec = <boolean>;
Этот параметр может использовать в любой секции, которая содержит пара-
метры exec.
Пример:
startup {
sync_exec = no;
exec "/path/something";
}
В этом примере синхронный режим, определённый по умолчанию для секции
startup, изменён на асинхронный.
О статистике.
ipa(8) интерпретирует данные статистики как 64-битные беззнаковые целые
числа, статистикой может быть что угодно (например, время или байты).
Предположим, что некоторое правило использует несколько систем учёта.
ipa(8) суммирует статистику от каждого модуля статистики и обновляет
статистику для правила в базе данных. Обычно модуль статистики возвра-
щает положительную статистику, но он может возвращать и отрицательную
статистику.
ipa(8) во время работы для правил представляет статистику двумя 64-бит-
ными счётчиками: один счётчик для положительной статистики и другой для
отрицательной статистики. В любой момент времени один из этих счётчиков
равен нулю. Если счётчик отрицательной статистики переполняется, то
ipa(8) сообщает о случившейся проблеме и завершает свою работу, так как
такое переполнение означает неправильную конфигурацию. Если счётчик
положительной статистики переполняется, то ipa(8) делает запрос базе
данных на добавление новой записи для правила со статистикой не поме-
стившейся во внутреннем счётчике.
Любой лимит или порог имеет такие же два счётчика, но если переполнится
счётчик положительной или отрицательной статистики для лимита или
порога, то ipa(8) сообщает о случившейся проблемы и завершает свою
работу, так как такое переполнение означает неправильную конфигурацию.
Также каждый порог имеет несколько счётчиков для временных интервалов
(отрицательный или положительный знак хранится в битовой карте).
Статистика передаётся в базу данных в виде 64-битных целых вместе с
текущим локальным временем.
Обычно положительная статистика больше чем отрицательная, но это не
является жёстким правилом. Только положительная статистика сохраняется
в базе данных, отрицательная статистика хранится в памяти и когда
ipa(8) завершает свою работу и некоторое правило имеет отрицательную
статистику, то эта статистика теряется (предупреждающее сообщение будет
послано в лог-файл). Другими словами, ipa(8) способна вычитать стати-
стику из текущего значения счётчика положительной статистики и нет воз-
можности вычитать статистику из старой статистики в базе данных.
Лимиты: введение.
Лимит должен рассматриваться в контексте некоторого правила. Иногда
лимиты в IPA называются триггерами. Если есть необходимость выполнять
какие-то действия, когда статистика для правила достигнет определённого
значения за некоторый период времени, тогда должна быть использована
секция limit. Эта секция может иметь несколько секций и должна содер-
жать по крайне мере один параметр по имени limit:
limit <имя-лимита> {
limit = <значение-лимита>;
/* Параметры и секции лимита. */
}
Необходимо давать такие имена лимитам, которые также являются коррект-
ными именами лимитов для используемой вами базы данных.
Любой лимит имеет 64-битный беззнаковый счётчик для положительной ста-
тистики, который изменяется ipa(8) и который сравнивается со значением
параметра limit. Если значение счётчика станет равным или большим чем
значение параметра limit, то лимит становится достигнутый и ipa(8)
больше не изменяет его счётчик. Счётчик лимита обновляется синхронно со
счётчиком правила.
Лимиты имеют имена, поэтому возможно использовать несколько лимитов в
одном правиле и они будут различаться по именам.
ipa(8) ничего не знает об единицах статистики, поэтому возможно исполь-
зовать различные форматы для <значения-лимита>: байты, время и 64-бит-
ное беззнаковое число (см. примеры ниже). <Значение-лимита> всегда пре-
образовывается в 64-битное беззнаковое число.
Лимит может проходить несколько состояний: лимит не достигнут, лимит
достигнут (плюс опциональный запуск команд), достигнутый лимит должен
быть перезапущен (плюс опциональный запуск команд) и псевдо состояние
когда не достигнутый лимит должен быть перезапущен. Секция limit может
иметь несколько параметров и секций, которые определяют состояния
лимита (описано ниже).
Если лимит не достигнут, то его статистика проверяется каждый раз,
когда обновляется статистика его правила (временной интервал не больше
чем значение параметра update_time).
Пример:
rule my-account {
/* Параметры и секции правила. */
limit 1 {
limit = 1M 500K;
info = "Байтовый лимит";
}
limit 2 {
limit = 2h 30m;
info = "Временной лимит";
}
limit 3 {
limit = 1234567890;
info = "Численный лимит";
}
}
В этом примере правило содержит три независимых лимита.
Если значение параметра limit задаётся в байтах, то символ `T' обозна-
чает Тбайты, `G' Гбайты, `M' Мбайты, `K' Кбайты, `B' байты (пробелы
опциональны). Если значение определяется как сложное значение, то
Тбайты должны быть указаны до Гбайтов и Мбайтов и так далее.
Активные и неактивные лимиты.
Если лимит не имеет собственного параметра worktime, то он активен
когда его правило активно, то есть, если параметр worktime правила раз-
решает ведение статистики, то лимит работает как обычно, если ведение
статистики не разрешено для правила, то ipa(8) игнорирует лимит и
начнёт с ним работу когда параметр worktime правила разрешит ведение
статистики снова.
Любой лимит может иметь собственный параметр worktime. В этом случае
если правило активно, то ipa(8) проверяет параметр worktime лимита.
Когда лимит неактивен, то времена, определённые в параметрах restart и
expire, не проверяются.
Таким образом, возможно иметь активное правило и неактивный лимит. Но
не возможно иметь неактивное правило и активный лимит. Все временные
интервалы в параметре worktime лимита должны быть подмножеством времен-
ных интервалов параметра worktime правила.
Пример:
rule my-account {
/* ... */
worktime = A * S *;
limit 1 {
limit = 10M;
worktime = A 08:00-21:00 S 08:00-21:00;
}
}
Здесь правило активно только по субботам и воскресеньям, а лимит акти-
вен с 08:00 до 21:00 по тем же дням. Так как временной интервал
08:00-21:00 является подмножеством временного интервала 00:00-24:00, то
в этих двух параметрах всё корректно.
Перезапуск не достигнутого лимита.
Время когда новый лимит был создан (или достигнутый лимит был перезапу-
щен снова) известно как ``время старта''. ipa(8) изменяет счётчик
лимита только когда лимит не достигнут. Возможно указать время, когда
не достигнутый лимит должен быть перезапущен с обнулённым счётчиком.
Секция restart позволяет определить время перезапуска не достигнутого
лимита:
limit <имя-лимита> {
/* Параметры и секции лимита. */
restart {
restart = <время-перезапуска>;
/* Команды. */
}
}
Секция restart должна иметь по крайней мере параметр restart. Суще-
ствует три метода определения этого времени. Рассмотрим их на последую-
щих примерах.
Возможно указать опциональные команды, которые будут запущены, когда не
достигнутый лимит будет перезапускаться.
ipa(8) также информирует системы учёта, используемые правилом лимита,
когда не достигнутый лимит перезапускается, поэтому если вы не указали
команды в секции restart, то некоторые действия всё ещё могу быть
выполнены системами учёта.
Если лимит не содержит секции restart, то этот лимит (если он не
достигнут) не может быть автоматически перезапущен, но он может быть
перезапущен утилитой ipactl(8).
Пример 1:
rule my.traf {
ac_list = ipfw;
ipfw:rules = 100 200;
limit 1 {
limit = 1G;
restart {
restart = 20h 30m;
}
}
}
Здесь значение параметра restart добавляется к времени старта лимита и
вычисленное время является временем перезапуска лимита. Здесь мы можем
рассматривать время перезапуска как число секунд со времени старта
лимита.
Символ `s' обозначает секунды, `m' минуты, `h' часы, `D' дни и `W'
недели.
Пример 2:
rule my.traf {
ac_list = ipfw;
ipfw:rules = 100 200;
limit 1 {
limit = 1G;
restart {
restart = +W;
}
}
}
Здесь лимит будет перезапущен в конце недели после времени старта
лимита. Символ после знака `+' означает: `m' минуту, `h' час, `D'
день, `W' неделю, `M' месяц.
Пример 3:
rule my.traf {
ac_list = ipfw;
ipfw:rules = 100 200;
limit 1 {
limit = 1G;
restart {
restart = +M 2D;
}
}
}
В этом примере лимит будет перезапущен на третий день следующего месяца
после времени старта лимита: сначала вычисляется время перезапуска для
``+'' (начало следующего месяца), затем ``2D'' (два дня) добавляется к
вычисленной дате.
Заметьте, что ``2D +M'' это не тоже самое: здесь ``2D'' добавляется ко
времени старта и затем вычисляется время перезапуска для ``+M'' (и
здесь мы всегда получим первый день некоторого следующего месяца).
Действия, когда лимит будет достигнут.
Когда лимит будет достигнут ipa(8) выполнит команды перечисленные в
секции reach:
limit <имя-лимита> {
/* Параметры и секции лимита. */
reach {
/* Команды. */
}
}
Секция reach может отсутствовать или быть пустой, в этом случае никакие
команды не будут запускаться по достижению лимита.
ipa(8) также информирует системы учёта, используемые правилом лимита,
когда лимит становится достигнутым, поэтому если вы даже не указали
команды в секции reach, то некоторые действия всё ещё могу быть выпол-
нены системами учёта.
Пример:
rule my.traf {
ac_list = ipfw;
ipfw:rules = 100;
limit 1 {
limit = 1G;
restart {
restart = +W;
}
reach {
exec "/somewhere/stop_traffic";
}
}
}
Здесь лимит в 1Гбайт, который перезапускается в конце недели если он не
достигнут, но когда он становится достигнутым, то запускается заданная
команда.
Перезапуск достигнутого лимита.
Возможно перезапустить достигнутый лимит. Для этого используйте секцию
expire:
limit <имя-лимита> {
/* Параметры и секции лимита. */
expire {
expire = <время-перезапуска>;
/* Команды. */
}
}
Секция expire должна иметь по крайней мере параметр expire.
Возможно указать опциональные команды, которые будут запущены, когда
достигнутый лимит будет перезапускаться.
ipa(8) также информирует системы учёта, используемые правилом лимита,
когда достигнутый лимит перезапускается, поэтому если вы не указали
команды в секции expire, то некоторые действия всё ещё могу быть выпол-
нены системами учёта.
Если лимит не содержит секции expire, то этот лимит (если он достигнут)
не может быть автоматически перезапущен, но он может быть перезапущен
утилитой ipactl(8).
Значение параметра expire может быть 0s, это означает, что достигнутый
лимит будет перезапущен мгновенно.
Пример:
rule my.traf {
ac_list = ipfw;
ipfw:rules = 100;
limit 1 {
limit = 1G;
restart {
restart = +W;
}
reach {
exec "/somewhere/stop_traffic";
}
expire {
expire = +W;
exec "/somewhere/start_traffic";
}
}
}
Здесь приведен лимит в 1Гбайт за неделю. Если лимит будет достигнут, то
он перезапустится в начале недели. Если этот лимит не будет достигнут,
то он всё равно будет перезапущен в начале недели.
Секции startup и shutdown для правила.
Выше были описаны две секции для запуска команд при старте и завершении
работы. Правило также может иметь эти секции, но секции startup и shut-
down расположенные в секции rule могут также содержать подсекции:
if_any_reached - если любой из лимитов правила достигнут;
if_any_not_reached - если любой из лимитов правила не достигнут;
if_all_reached - если все лимиты правила достигнуты;
if_all_not_reached - если все лимиты правила не достигнуты.
Эти секции определяют команды, которые должны быть запущены, если
лимиты попадают под условие подсекции.
Любое правило может иметь пустую секцию startup или shutdown, в этом
случае эта секция не наследуются из подходящей секции rulepat.
Пример:
rule my.traf {
ac_list = ipfw;
ipfw:rules = 100;
startup {
exec "/somewhere/count_traffic";
if_any_reached {
/* ... */
exec "/bin/echo \"Какой-то из лимитов в правиле \
${rule} был достигнут\" | mail admin";
}
}
limit 1 {
limit = 1G;
restart {
restart = +M;
}
info = "1G в месяц";
/* ... */
}
limit 2 {
limit = 500M;
restart {
restart = +W;
}
info = "500M в неделю";
/* ... */
}
}
Здесь приведены два лимита: 1 Гбайт в месяц и 500 Мбайт в неделю, сек-
ция if_any_reached будет использована если любой из этих лимитов будет
достигнут на момент старта ipa(8). Также startup секция правила содер-
жит одну команду, которая всегда запускается при старте. Здесь мы
использовали обратный слэш для разделения командной строки.
Секции startup и shutdown для лимита.
Лимит может иметь собственные секции startup и shutdown с следующими
дополнительными подсекциями:
if_reached - если лимит достигнут;
if_not_reached - если лимит не достигнут.
Эти секции определяют команды, которые необходимо запустить, если лимит
подпадает под условие подсекции.
ipa(8) также информирует используемые системы учёта правилом лимита при
старте и завершении работы достигнут ли лимит, поэтому, если вы не ука-
зали команды для старта и/или останова для лимита, то некоторые дей-
ствия всё ещё могу быть выполнены системами учёта.
Использование отдельных баз данных для лимитов.
Существует параметр db_list, который определяет список баз данных
используемых правилом. По умолчанию лимит использует тот же самый спи-
сок баз данных, что и его правило (он наследует этот список). Но воз-
можно использовать параметр db_list в секции limit:
rule <имя-правила> {
/* Параметры и секции правила. */
db_list <список1>;
limit <имя-лимита> {
/* Параметры и секции лимита. */
db_list <список2>;
}
}
<Список1> и <список2> могут содержать общие элементы, в любом случае
<список1> используется только для правила, а <список2> используется
только для лимита.
Зачем использовать раздельные базы данных для правила и его лимитов?
Не все базы данных работают с лимитами и даже если какая-то база данных
работает с лимитами, она может поддерживать не все функции (методы) для
лимитов. См. детали реализации в странице документации ipa_mod(3).
Допустим некоторый лимит использует несколько баз данных. Из какой базы
данных ipa(8) возьмёт текущее состояние лимита? Первая база данных,
которая в состоянии вернуть состояние лимита, будет опрошена о текущем
состоянии лимита, даже если какая-то другая база данных имеет другое
состояние лимита, она не будет опрошена и её состояние лимита будет
потеряно, затем ipa(8) обновит состояние лимита в каждой базе данных.
Заметьте, что порядок баз данных для лимита важен.
Прочтите в документации к базе данных, которую вы используйте, может ли
она работать с лимитами и что конкретно модуль поддерживает, когда
работает с лимитами.
Использование значения параметра limit из базы данных.
Иногда необходимо хранить значение параметра limit в базе данных и
изменять это значение в базе данных, поэтому должен быть способ сооб-
щить ipa(8) о том, что необходимо использовать значение параметра limit
из базы данных. Для этой цели был реализован параметр load_limit:
limit <имя-лимита> {
/* Параметры и секции лимита. */
load_limit = <boolean>;
}
Если вы хотите использовать значение параметра limit из базы данных, то
установите значение параметра load_limit в ``yes''. Если база данных не
имеет текущего состояния лимита (например если лимит новый), то будет
использоваться значение параметра limit из конфигурационного файла,
поэтому параметр limit всегда должен быть определён.
По умолчанию параметр load_limit имеет значение ``no''.
Один из случаев почему необходимо установить этот параметр в ``yes''
является использование утилиты ipactl(8) для изменения значение пара-
метра limit на лету.
Этот параметр может быть определён в секции global, если какая-то сек-
ция limit не будет содержать этот параметр, то его значение будет уста-
новлено из секции global.
Инициализация лимитов.
Когда ipa(8) стартует, перечитывает конфигурационный файл или выполняет
переинициализацию когда возникнут проблемы со временем, она выполняет
следующие шаги для произвольного лимита:
1. Текущее состояние лимита читается из базы данных, если база дан-
ных не имеет состояния лимита, то состояние лимита регистриру-
ется со значением параметра limit из конфигурационного файла и с
нулевым счётчиком и инициализация лимита завершена, иначе ipa(8)
выполняет второй шаг (2а или 2б);
2а. Если лимит не достигнут с текущим состоянием из базы данных, то
если значение параметра load_limit равно ``no'', то ipa(8)
обновляет значение параметра limit из конфигурационного файла;
если значение параметра load_limit равно ``yes'', то ipa(8)
игнорирует значение параметра limit из конфигурационного файла и
берёт это значение из базы данных. В любом случае лимит помеча-
ется как не достигнутый, даже если с новыми установками он ста-
новится достигнутым. Затем ipa(8) обновляет дату когда лимит
должен быть перезапущен согласно значению параметра restart из
конфигурационного файла, игнорируя эту дату из базы данных.
2б. Если лимит достигнут, то ipa(8) помечает этот лимит как достиг-
нутый и не обновляет значение параметра limit в базе данных
(т.е. временно не учитывается значение параметра load_limit и
это можно увидеть в выводе команды ipactl(8) status для этого
лимита). Затем ipa(8) обновляет дату когда лимит должен быть
перезапущен согласно значению параметра expire из конфигурацион-
ного файла, игнорируя это значение из базы данных.
Лимиты: ещё раз о событиях лимитов.
Для улучшения понимания работы лимитов ниже приведена временная диа-
грамма состояний произвольного лимита:
+--------------+--> Restart (Tstart)
| |
Trestart_exec Treach_exec Texpire_exec
--|------>------||------>------||------>------||------------->
Tstart Trestart Treach Texpire time
Подлимиты.
Подлимит это часть некоторого лимита. Главное назначение подлимита это
регистрация события, когда будет достигнута некоторая часть значения
параметра limit. Так как подлимит является частью секции limit, то его
значение должно быть задано в тех же единицах, что и значение параметра
limit. Для упрощения определения подлимита возможно задавать подлимит в
процентах, то есть некоторое число процентов от значение параметра
limit:
limit <имя-лимита> {
limit = <значение-лимита>;
/* Параметры и секции лимита. */
sublimit <значение-подлимита> {
/* Секции подлимита. */
}
}
Подлимиты могут содержать только секции reach, startup и shutdown. Все
эти секции имеют тот же самый формат, что и те же самые секции для
лимитов. ipa(8) не информирует системы учёта о событиях подлимитов, так
как подлимиты не видимы для модулей.
Лимит может иметь несколько не дублирующих (разные <значения-подлими-
тов>) подлимитов.
Так как состояния подлимитов не хранятся в базах данных, поэтому, если
возможно, то лучше использовать подлимиты, чем добавлять дополнительные
лимиты для правила.
Пример:
rule my.traf {
/* ... */
limit l1 {
limit = 1G;
load_limit = yes;
restart {
restart = +M;
}
info = "1G в месяц";
/* ... */
sublimit 50% {
reach {
exec "/bin/echo \"Достигнута половина лимита \
${limit} правила ${rule}\" | mail me";
}
}
}
}
Здесь подлимит посылает email, когда половина лимита t1 будет достиг-
нута. Даже если значение параметра limit будет изменено утилитой
ipactl(8), значение подлимита будет скорректировано, так как оно задано
в процентах.
Пороги: введение.
Порог позволяет наблюдать за статистикой правила за некоторый временной
промежуток до текущего момента времени и делать некоторые действия,
когда статистика за этот временной промежуток меньше, равна или больше
чем заданное значение. Этот временной интервал также может быть назван
``скользящим временным окном''. Порог описывается секцией threshold,
имеющей следующий формат:
threshold <имя-порога> {
threshold = <значение-порога>;
threshold_time_width = <время>;
threshold_time_slice = <время>;
/* Другие параметры и секции порога. */
}
Необходимо давать такие имена порогам, которые также являются коррект-
ными именами порогов для используемой вами базы данных.
Любой порог имеет 64-битный беззнаковый счётчик, который изменяется
ipa(8) и сравнивается со значением параметра threshold. Если значение
счётчика становится меньше, равно или больше чем значение параметра
threshold, то запускаются команды из опциональных секции below_thresh-
old, equal_threshold или above_threshold. Счётчик порога изменяется
синхронно со счётчиком правила каждый threshold_time_slice временной
интервал.
ipa(8) ничего не знает об единицах статистики, поэтому возможно зада-
вать <значение-порога> в различных форматах: байты, время и беззнаковое
64-битное целое. <Значение-порога> всегда конвертируется в беззнаковое
64-битное целое.
Возможно определить отклонение <значения-порога> при помощи параметра
threshold_deviation. Значение параметра threshold_deviation должно быть
задано в тех же единицах, что и значение параметра threshold. Чтобы
упростить определение значения отклонения порога, возможно задавать его
значение в процентах, то есть некоторое число процентов от значение
параметра threshold.
Значение параметра threshold_time_width определяет ширину скользящего
временного окна. Значение параметра threshold_time_slice определяет
временные интервалы движения скользящего временного окна. Значение
параметра threshold_time_width должно быть больше чем значение пара-
метра threshold_time_slice и должно быть делится нацело на это значе-
ние. Другими словами, счётчик порога представляет снимок статистики
правила за последние threshold_time_width секунд. В отличии от лими-
тов, пороги не имеют ``времени старта'', так как их статистика скользит
во времени дискретными временными интервалами равными thresh-
old_time_slice секундам. Эти два параметра могут быть определены в сек-
ции global и они будут использоваться, при их отсутствии в секции
threshold.
Пороги имеют имена, поэтому можно использовать несколько порогов в
одном правиле и они будут различаться по именам.
Системы учёта, используемые правилом порога, оповещаются о событиях
порога, поэтому системы учёта также могут выполнять некоторые действия,
когда значение счётчика порога меньше, равно или больше чем значение
параметра threshold.
Возможно ограничить число раз запуска команд или оповещения систем
учёта из секций below_threshold (X), equal_threshold (Y) и
above_threshold (Z) в параметре threshold_balance:
threshold_balance = X:Y:Z;
Этот параметр может быть определён в секции global и если какая-то сек-
ция threshold его не содержит, то его значение будет наследоваться из
секции global.
Есть три внутренних счётчика x, y и z, которые считают количество
последовательных запусков команд и количество сообщений модулям учёта
из секций below_threshold, equal_threshold и above_threshold. Эти
счётчики изначально равны X, Y и Z соответственно. Когда счётчик порога
меньше чем значение параметра threshold и x не равно нулю, то значение
x декрементируется, y устанавливается равным Y, z устанавливается рав-
ным Y, затем запускаются команды из секции below_threshold и системы
учёта информируются о событии порогоа. Аналогичные действия делаются
для счётчиков y и z.
Чтобы задать безграничные значения для X, Y или Z, установите их как
`-'. В реализации безграничное число равно UINT_MAX. По умолчанию зна-
чение этого параметра равно -:-:-.
Пример:
rule lan {
ac_list = ipfw;
ipfw:rules = 100 200 -300;
update_time = 1m;
limit l1 {
limit = 1G;
info = "Контроль каждого 1G трафика";
reach {
exec "/bin/echo \"1G правила ${rule} достигнут\" |
mail me";
}
expire {
expire = 0s;
}
}
threshold t1 {
threshold = 500M;
threshold_balance = 1:-:1;
threshold_deviation = 50M;
threshold_time_width = 24h;
threshold_time_slice = 15m;
info = "Порог в 500M плюс-минус 50M за 24h";
below_threshold {
exec "/somewhere/increase_bandwidth ${rule}";
}
above_threshold {
exec "/somewhere/decrease_bandwidth ${rule}";
}
}
}
Здесь правило имеет один порог и один лимит.
Порог позволяет контролировать трафик в 500 Мбайт плюс-минус 50 Мбайт
(мы увеличиваем скорость некоторой программой increase_bandwidth и
уменьшаем скорость некоторой программой decrease_bandwidth) за 24 часа
(это один день, но это не день недели, здесь 24 часа обозначают времен-
ной интервал). Время продвижения порога равно 15 минутам, заметьте, что
в этом примере порог не будет проверяться каждую минуту (значение пара-
метра update_time для правила).
Статистика для правил и лимита будет обновляться каждую минуту. Лимит
позволяет отправлять email, когда будет использован очередной 1 Гбайт
трафика.
Активные и неактивные пороги.
Пороги подобно лимитам могут быть активными и неактивными и иметь соб-
ственные параметры worktime. Поэтому, для большей информации прочтите
соответствующий параграф для лимитов.
Чему будет равно значение счётчика порога, когда порог был неактивным и
становится активным из-за значения параметра worktime? Первое решение
это позволить временному окну порога перемещаться в временном интервале
неактивности, второе решение это ``переместить'' временное окно порога
через временной интервал неактивности. В первом решении статистика для
счётчика порога в временном интервале неактивности равна 0 и значение
счётчика порога уменьшается. Во втором решении статистика в временном
интервале неактивности игнорируется (она пропускается) и значение счёт-
чика порога не изменятся.
Чему будет равно значение счётчика порога когда ipa(8) начинает свою
работу и в базе данных уже есть состояние порога? Существует также два
решения этой ситуации, как и в предыдущем вопросе.
Возможно выбирать решения для выше описанных ситуаций с помощью пара-
метра threshold_type, его значение равно битам объединённых по ИЛИ
(даны в шестнадцатиричной системе счисления):
0x1 переместится через временной интервал, когда ipa(8) не работала
(была остановлена);
0x2 переместится через временной интервал, когда порог был неактив-
ным.
По умолчанию значение параметра threshold_type равно 0. Возможные зна-
чения этого параметра следующие: 0, 1, 2 и 3 (0x1|0x2). Нормальные зна-
чения для этого параметра 0 и 3, значения с установленным только одним
битом должны использоваться с осторожностью, так как когда порог иници-
ализируется, он рассматривается как активный (прочтите параграф об ини-
циализации порогов).
Этот параметр может быть определён в секции global и он будет использо-
ван, если какая-то секция threshold не имеет этого параметра, то его
значение будет унаследовано из секции global.
Пример:
rule client {
ac_list = ipfw;
ipfw:rules = 100 200 300;
update_time = 1m;
threshold t {
threshold = 100M;
threshold_deviation = 10%;
threshold_time_width = 5h;
threshold_time_slice = 15m;
threshold_type = 3;
worktime = M 08:00-21:00 T 08:00-21:00 W 08:00-21:00
H 08:00-21:00 F 08:00-21:00;
info = "Порог в 100M плюс-минус 10% за 5h (тип 3)";
below_threshold {
exec "/somewhere/increase_bandwidth ${rule}";
}
above_threshold {
exec "/somewhere/decrease_bandwidth ${rule}";
}
}
}
Предположим, что данное правило это правило для клиента, который имеет
доступ в Internet каждый рабочий день с 08:00 до 21:00. Мы разрешаем
ему использовать скорость в 100 Мбайт плюс-минус 10% за каждые 5 часов
(мы увеличиваем скорость некоторой программой increase_bandwidth и
уменьшаем скорость некоторой программой decrease_bandwidth).
Предположим, что текущее значение счётчика порога равно 90 Мбайт в
21:00. Когда наступит 08:00 следующего дня по умолчанию текущее значе-
ние счётчика порога станет 0 Мбайт, так как в интервале между 21:00 и
08:00 следующего дня содержится по крайней мере один интервал в 5
часов. Здесь мы используем тип порога 3 и временное окно ``переин-
стится'' с 21:00 в 08:00 и текущее значение счётчика порога останется
неизменённым, то есть 90 Мбайт в 08:00 следующего дня. Мы также можем
остановить ipa(8) в 21:00 и запустить её снова в 08:00 и временное окно
порога также ``переместится'' с 21:00 в 08:00.
Если есть несколько клиентов с такими же установками, то в 08:00 ни
один из них не сможет интенсивно начать использовать собственную часть
общего трафика.
Секции startup и shutdown для порога.
Порог может иметь собственные секции startup и shutdown, которые они
могут содержать только списки команд.
Использование значение параметра threshold из базы данных.
Порог подобно лимиту может иметь параметр load_threshold, который озна-
чает тоже самое и используется для той же самой цели. Поэтому, про-
чтите соответствующий параграф для лимитов для большей информации.
Использование отдельных баз данных для порогов.
Подобно лимитам возможно использовать параметр db_list в секции thresh-
old и указывать различные списки баз данных для правила и его порога.
Инициализация порогов.
В отличии от лимитов инициализация порогов очень проста, так как пороги
не могут быть достигнутыми или не достигнутыми: ipa(8) получает состоя-
ние порога из первой базы данных, которая в состоянии вернуть состояние
порога, если база данных не имеет состояния порога, то регистрируется
новое состояние со значением параметра threshold из конфигурационного
файла, иначе ipa(8) учитывая значения параметров load_threshold и
threshold_type обновляет состояние порога. Заметьте, что когда порог
инициализируется предполагается что он активен, даже если его параметр
worktime отмечает этот порог неактивным. Так как статистика порога для
временных интервалов не хранится в базе данных, то статистика для вре-
менных интервалов инициализируется приблизительно в соответствии с
текущим локальным временем, временными отметками порога и значения его
счётчика.
Пороги: ещё раз о порогах.
Для улучшения понимания работы порогов ниже приведена временная диа-
грамма:
<-------------- time_width ------------->
(t1) |---c1--|---c2--|---c3--|---c4--|---c5--| --> скольжение
(t2) |---c2--|---c3--|---c4--|---c5--|---c6--| --> скольжение
<-slice->
-----|-------|-------|-------|-------|-------|-------|-------|-->
t1 t2 время
На этой диаграмме видна статистика порога для временных отметок t1 и
t2. Вся статистика представляется как сумма ci, каждая ci равна стати-
стике правила в течении одного интервала времени t2 - t1. Порог сколь-
зит во времени дискретно и его статистика это снимок статистики правила
за time_width секунд.
Динамические правила и автоправила.
Динамические правила генерируются на лету из автоправил специально раз-
работанными модулями учёта. Внутри ipa(8) статические и динамические
правила почти неразличимы и любой параметр (кроме параметров
ac_gather_*) и секция (включая секции limit и threshold) в статических
правилах могут быть использованы в динамических правилах.
Автоправило определяется секцией autorule:
autorule <имя-автоправила> {
/* Параметры и секции. */
}
<Имя-автоправила> не хранится в базе данных, но модуль учёта может
использовать это имя для генерирования имён динамических правил,
поэтому используйте те же ограничение что и для <имени-правила> для
используемой вами базы данных.
Динамическое правило похоже на статическое правило. Существует всего
два ограничения для автоправил (таким образом и для динамических правил
тоже): автоправило может иметь только одну систему учёта в значении
параметра ac_list и автоправило не может иметь параметров ac_gather_*.
Конфигурационный файл может иметь несколько автоправил одновременно.
Любое автоправило должно иметь по крайней мере параметр ac_list с одним
элементом в его значении. (Возможно реализовать поддержку нескольких
систем учёта для одного автоправила, но это бессмысленно.) Этот эле-
мент в значении параметра ac_list определяет систему учёта, которая
может создавать и уничтожать динамические правила. Каждый раз когда
эта система учёта опрашивает для получения новой статистики (функция
ac_get_stat в ipa_mod(3)), она имеет шанс создать и/или уничтожить
(ранее созданные) динамические правила. Значение параметра update_time
определяет временной интервал вызовов функции ac_get_stat (эта функция
может вызываться чаще).
Если вы хотите использовать некоторую базу данных для динамических пра-
вил, то эта база данных должна поддерживать динамические правила.
Если автоправило имеет параметр worktime, то этот параметр используется
автоправилом. Динамические правила сгенерированные от этого автоправила
наследуют параметр worktime_rule из автоправила как свой параметр work-
time. Если в автоправиле нет параметра worktime, то он наследуется из
секции global.
Так как автоправило и его динамические правила могут иметь разные пара-
метры worktime, то возможно неактивное автоправило и активные динамиче-
ские правила и наоборот.
Динамическое правило наследует установки от своего автоправила, если
какие-то параметры и секции всё ещё не определены, то они наследуются
от подходящей секции rulepat, затем из секции global и затем использу-
ются установки по умолчанию.
Если автоправило имеет секции startup и shutdown, то эти секции для
динамических правил, а не для самого автоправила. Если вам необходимо
использовать имя динамического правила в командной строке, то не
используйте макропеременную ${rule}, так как она расширяется внутренним
парсером конфигурационного файла, вместо этого используйте подстановки
командной строке (см. выше).
Любое автоправило может иметь пустую секцию startup или shutdown, в
этом случае эта секция не наследуются из подходящей секции rulepat для
его динамических правил.
Если необходимо использовать различные лимиты и пороги для динамических
правил, то определите эти лимиты и пороги в различных секциях rulepat.
Пример:
ac_mod "ipa_atest.so";
db_mod "ipa_db_sdb.so";
global {
db_list = sdb;
append_time = 1h;
}
autorule a {
ac_list = atest;
update_time = 1m;
limit 1 {
limit = 100M;
restart {
restart = +W;
}
reach {
exec "/somewhere/stop_traffic.sh %rule%";
exec "/bin/echo \"%rule%'s limit ${limit} reached\" |
mail admin";
}
expire {
expire = +M;
exec "/somewhere/start_traffic.sh %rule%";
}
}
}
Здесь каждое динамическое правило сгенерированное из автоправила насле-
дует параметр автоправила update_time и подобно статическим правилам
каждое динамическое правило наследует параметры db_list и append_time
из секции global. Каждое динамическое правило будет иметь один лимит,
так как мы не можем использовать макропеременную ${rule} в динамические
правилам (на самом деле в автоправилах), то используется подстановка
%rule%. Использование макропеременной ${limit} является корректным, так
как имя лимита известно для парсера конфигурационного файла.
Шаблоны правил.
Использование шаблонов правил это эффективный метод для разделения
общих установок для нескольких правил. Как было сказано раньше, секция
global позволяет определить общие установки для любых правил, динамиче-
ские правила могут наследовать установки от своих автоправил. Шаблоны
правил позволяют определить общие установки для классов статических и
динамических правил.
Если какое-то статическое или динамическое правило не имеет какого-то
параметра или секции, то оно может наследовать этот параметр или секцию
из подходящего шаблона правила. Шаблоны правил определяются в секциях
rulepat:
rulepat "<regexp>" {
/* Параметры и секции. */
}
Каждый шаблон правила поименован регулярным выражением POSIX (расширен-
ный формат). ipa(8), разобрав конфигурационный файл, находит подходящий
шаблон правила для каждого статического правила и добавляет неопре-
делённые установки для статического правила из шаблона правила. Анало-
гично, создав динамическое правило, ipa(8) находит подходящий шаблон
правила и добавляет неопределённые установки для динамического правила
из шаблона правила. По умолчанию, когда подходящий шаблон правила най-
ден, поиск следующего шаблона правила прекращается. Чтобы продолжить
поиск следующих шаблонов правил, установите значение параметра
check_next_rulepat в ``yes'':
check_next_rulepat = <boolean>;
Этот параметр может быть указан только в секции rulepat и его значение
по умолчанию равно ``no''.
Любой параметр (кроме параметров ac_gather_*) и любая секция (включая
секции limit и threshold), которая может быть использована в секции
rule может быть использована в секции rulepat.
Шаблоны правил могут быть указаны в любом месте в конфигурационном
файле, важен их порядок, так как их регулярные выражение проверяются в
том же самом порядке, в котором расположены шаблоны правил в конфигура-
ционном файле.
Модули также могут ожидать параметры и секции в секциях rulepat.
Пример:
ac_mod "ipa_ipfw.so";
db_mod "ipa_db_sdb.so";
global {
ac_list = ipfw;
db_list = sdb;
update_time = 1m;
load_limit = yes;
sdb:db_group = staff;
}
rulepat "0${$}" {
update_time = 30s;
threshold 1 {
threshold = 1G;
threshold_deviation = 10%;
threshold_time_width = 10h;
threshold_time_slice = 5m;
below_threshold {
exec "/somewhere/increase-bandwidth.sh %rule%";
}
above_threshold {
exec "/somewhere/decrease-bandwidth.sh %rule%";
}
}
}
rulepat "^client" {
worktime = M 08:00-20:00 T 08:00-20:00 W 08:00-20:00
H 08:00-20:00 F 08:00-20:00 A 08:00-17:00;
}
Здесь первая секция rulepat ``ловит'' все правила с нулём в конце их
имени (макропеременная ${$} расширяется в одиночный символ `$', а `$' в
конце регулярного выражения POSIX обозначает конец строки). Вторая
секция rulepat ``ловит'' все правила с подстрокой ``client'' в начале
их имён.
Сбор статистики из нескольких правил.
Обычно каждое правило получает статистику от модулей учёта, но иногда
необходимо суммировать статистику из нескольких правил и невозможно или
слишком трудоёмко дать эту задачу модулям учёта.
Параметры ac_gather_add и ac_gather_sub позволяют получать статистику
для одного правила из нескольких правил и добавлять или вычитать эту
статистику:
rule <имя-правила> {
/* Параметры и секции правила. */
ac_gather_add = "<regexp>";
ac_gather_sub = "<regexp>";
}
Здесь <regexp> это регулярное выражение POSIX (расширенный формат), ес-
ли имя какого-то правила соответствует этому регулярному выражению, то
его статистика добавляется к статистике правила в котором указаны пара-
метры ac_gather_*. Заметьте, что этот параметр также работает с динами-
ческими правилами. Также возможно строить сложные зависимости в этом
параметре (см. пример).
Этот параметр может быть указан только в секции rule, т.е. он может
быть использован только со статическими правилами, но может собирать
статистику со статических и динамических правил.
Параметр ac_list является синхронным по отношению к секции rule: когда
некоторое правило обновляется, статистика забирается из каждого модуля
учёта, используемого правилом. Параметр ac_gather является асинхронным
по отношению к секции rule: текущее правило получает статистику из пра-
вила соответствующего регулярному выражению параметров ac_gather_*
только тогда, когда это совпадающее правило само обновляется.
Правило, которое имеет параметры ac_gather_*, также может иметь пара-
метр ac_list.
Пример:
ac_mod "ipa_ipfw.so";
global {
ac_list = ipfw;
}
rule client1 {
ipfw:rules = 100 102 104;
info = "Статистика для первого клиента";
}
rule client2 {
ipfw:rules = 200 202 204;
info = "Статистика для второго клиента";
/* ac_gather_add = "^clients${$}"; <-- ОШИБКА! */
}
rule clients {
ac_gather_add = "^client[[:digit:]]+${$}";
info = "Статистика для всех клиентов";
}
rule server {
ipfw:rules = 1000 1002;
info = "Статистика для сервера";
}
rule all_stat {
ac_gather_add = "(server|clients)${$}";
info = "Статистика для всех в моей LAN";
}
rule all_except_client2_stat {
ac_gather_add = "^all_stat${$}";
ac_gather_sub = "^client2${$}";
info = "Статистика для всей в моей LAN, кроме client2";
}
Здесь у нас шесть правил: client1, client2, clients, server, all_stat и
all_except_client2_stat. Правило clients получает статистику из правил
client1 и client2. Правило all_stat получает статистику из правил
clients и server. И правило all_except_client2_stat получает статистику
из правил clients и server исключая статистику от client2.
Правило client2 имеет неправильный параметр ac_gather_add в коммента-
рии, если бы этот параметр существовал в этом правиле, то мы бы полу-
чили зацикливание в зависимости правил: client2->clients->client2...
ipa(8) не проверяет зацикливания в зависимостях правил.
Использование программы ipactl(8).
Программа ipactl(8) позволяет посылать ipa(8) управляющие команды через
Unix domain сокет. Перед тем как использовать эту программу необходимо
разрешить её использование установкой значения параметра ctl_enable в
``yes'', по умолчанию значение этого параметра равно ``no'':
ctl_enable = <boolean>;
Если значение этого параметра равно ``yes'', то ipa(8) создаст Unix
domain сокет и будет готова для приёма управляющих команд на этом
сокете. Созданный Unix domain сокет будет иметь владельца, равному
пользователю, запустившего ipa(8), права доступа к сокету определяются
значением параметра ctl_socket_perm.
Существует путь к этому Unix domain сокету, заданный по умолчанию (см.
вывод команды ``ipactl -h''), но возможно определить путь к Unix domain
сокет в параметре ctl_socket_path:
ctl_socket_path = "/path/to/socket";
По умолчанию ipa(8) ожидает данные из сокета в течение 10 секунд, воз-
можно изменить этот таймаут в параметре ctl_timeout:
ctl_timeout = <время>;
Можно определить права доступа к сокету в параметре ctl_socket_perm:
ctl_socket_perm = <права>;
<Права> это последовательность букв: `u', `g' и `o'. Эти символы опре-
деляют кому (пользователю, группе или остальным пользователям) разре-
шено посылать данные в сокет. Вы можете разрешить посылать данные в
сокет остальным пользователям только если ipa(8) понимает следующие
параметры. Если этот параметр не задан, то значение по умолчанию этого
параметра равно ``u''.
ipa(8), запущенная на FreeBSD, способна проверять отправителя сообщений
от ipactl(8) (проверьте это в выводе команды ``ipa -v''), поэтому на
этой системе необходимо также определять параметры ctl_acl_class,
ctl_dump_acl, ctl_freeze_acl, ctl_stat_acl и ctl_rule_acl.
Параметр ctl_acl_class определяет класс ACL (список управления досту-
пом): имя ACL с последующим определением ACL. Этот параметр не должен
располагаться в какой-либо секции:
ctl_acl_class <класс> [<ACL>];
ACL состоит из элементов, разделённых пробелами, каждый элемент имеет
имеет следующий формат:
[!]<пользователь>|%<группа>
Символ `!' обозначает, что доступ запрещён. Символ `%' обозначает, что
последующее имя это имя группы. <Пользователь> и <группа> должны быть
заданы символьными именами (UID и GID здесь не работают). Элементы в
ACL проверяются слева на право. Здесь под ``доступ запрещён'' понима-
ется, что пользователю не разрешено использовать некоторую управляющую
команду. Когда прибывает управляющее сообщение, ipa(8) переводит имя
пользователя или группы каждого элемента ACL в UID или GID и сравнивает
с идентификаторами отправителя сообщения.
Параметр ctl_dump_acl применяет указанный ACL к команде dump утилиты
ipactl(8):
ctl_dump_acl <класс>;
Параметр ctl_freeze_acl применяет указанный ACL к команде freeze ути-
литы ipactl(8):
ctl_freeze_acl <класс>;
Параметр ctl_stat_acl применяет ACL для команд status и memory утилиты
ipactl(8):
ctl_stat_acl <класс>;
Параметр ctl_rule_acl применяет указанный ACL к правилу для команд
restart, expire, set и status утилиты ipactl(8):
ctl_rule_acl <класс>;
Если ACL не определён и не наследуется, то он воспринимается как пустой
ACL, и обозначает, что доступ запрещён для всех.
Давайте рассмотрим как использовать все эти параметры на примерах.
Пример 1:
ctl_enable = yes;
ctl_socket_perm = ug;
В этом примере ipa(8) не знает как получить информацию об отправителе
управляющих сообщений программы ipactl(8). Мы разрешили пользователю и
группе посылать команды в сокет (это контролируется правами доступа
сокета). Из соображений безопасности невозможно разрешить другим поль-
зователям выполнять запись в сокет.
Пример 2:
ctl_enable = yes;
ctl_socket_path = "/var/tmp/ipactl.sock";
ctl_timeout = 10s;
Здесь мы изменили путь к Unix domain сокету и таймаут. Параметр
ctl_socket_perm не задан, поэтому используется значение, заданное по
умолчанию, равное ``u''.
Пример 3:
ctl_enable = yes;
ctl_socket_perm = ugo;
ctl_acl_class empty;
ctl_acl_class root root;
ctl_acl_class admins root !john %wheel;
ctl_dump_acl root;
global {
ctl_rule_acl admins;
/* ... */
}
rulepat "^vip" {
ctl_rule_acl root;
/* ... */
}
rulepat "^staff" {
ctl_rule_acl admins;
/* ... */
}
rule lan-all {
ctl_rule_acl empty;
/* ... */
}
В этом примере ipa(8) знает как получить информацию об отправителе
управляющих сообщений программы ipactl(8), поэтому необходимо восполь-
зоваться параметрами ctl_acl_class, ctl_dump_acl и ctl_acl, также мы в
состоянии разрешить в параметре ctl_socket_perm остальным пользователям
посылать управляющие команды в сокет. Определены три ACL класса: empty,
root и admins.
Замораживание работы ipa(8).
Иногда необходимо быть уверенным, что ipa(8) ничего не выполняет в
течении некоторого промежутка времени. Существуют два параметра, кото-
рые позволяют заморозить работу ipa(8).
Первый параметр sleep_after_dump позволяет определить период времени, в
течении которого ipa(8) должна приостановить свою работу и игнорировать
все сигналы после выполнения команды dump от ipactl(8).
Второй параметр freeze_time позволяет определить период времени, в
течении которого ipa(8) должна приостановить свою работу и игнорировать
все сигналы после получения команды freeze от ipactl(8).
freeze_time = <время>;
sleep_after_dump = <время>;
Значения этих параметров не должны быть относительно большими, так как
существует вероятность того, что какое-то из временных событий будет
проверено слишком поздно.
Праметры sleep_after_dump и freeze_time не имеют значений по умолчанию.
Эти параметры не должны располагаться в какой-либо секции.
Пример:
freeze_time = 30s
sleep_after_dump = 5s;
Здесь мы сообщаем ipa(8), что необходимо приостановить свою работу на 5
секунд после получения команды dump, и приостановить свою работу на 30
секунд после получения команды freeze. Это общий случай: мы отправляем
команду dump, например, если мы хотим получить текущую статистику
позже, и мы отправляем команду freeze, чтобы заморозить работу ipa(8) и
произвести некоторые изменения в системе. Здесь предполагается, что 30
секунд будет достаточно, чтобы сделать все необходимые изменения в
системе.
Порядок активных правил.
ipa(8) проверяет правила начиная с головы очереди активных правил. Ес-
ли все правила независимы, то вы не должны беспокоится о их порядке, но
если, например, правило r1 должно быть проверено перед правилом r2, то
прочтите следующие несколько параграфов.
Если нет параметров ac_gather_* и нет параметров worktime, то порядок
активных правил такой же как и порядок правил в конфигурационном файле.
Если есть по крайней мере один ac_gather_* параметр, то порядок актив-
ных правил изменяется, чтобы последовать зависимостям определённых в
параметрах ac_gather_*, но если какие-то правила не соответствуют регу-
лярным выражениям определённым в параметрах ac_gather_*, то их относи-
тельный порядок такой же как и их относительный порядок в конфигураци-
онном файле.
Если нет параметров ac_gather_* и если есть правила с параметрами work-
time, то порядок этих правил может быть изменён.
Динамические правила всегда добавляются в начало очереди активных пра-
вил, так как динамические правила не могут иметь параметров
ac_gather_*, но некоторые статические правила могут получать статистику
из динамических правил.
Если вам необходимо сохранять порядок активных правил таким же как и
порядок правил в конфигурационном файле, то установите параметр
keep_rules_order в ``yes'', по умолчанию значение этого параметра равно
``no'':
keep_rules_order = <boolean>;
Будьте осторожны с порядком правил в конфигурационном файле, если у вас
есть по крайне мере один параметр ac_gather_* и параметр
keep_rules_order установлен в ``yes'': располагайте правила, которые
отдают статистику, перед правилами, которые принимают статистику.
Лимиты и пороги в одном правиле проверяются в том же самом порядке, в
котором они записаны в конфигурационном файле и этот порядок не меня-
ется.
Заметьте, что некоторые модули чувствительны к порядку активных правил.
Этот параметр не должен располагаться в какой-либо секции.
Пример:
keep_rules_order = yes;
Теперь ipa(8) не будет менять порядок активных правил.
Отладка.
Иногда необходимо определить почему что-то идёт не так как должно было
быть. Существует несколько параметров, которые могут быть использованы
для отладки ipa(8):
debug_ac_null - сообщать об использовании системы учёта null
(отдельно, 1);
debug_db_null - сообщать об использовании базы данных null
(отдельно, 1);
debug_time - отладка различных временных событий (отдельно, 2);
debug_worktime - отладка параметров worktime (отдельно, 1);
debug_exec - отладка параметров exec (правило, 1);
debug_autorule - отладка автоправил (отдельно, 1);
debug_limit - отладка событий лимитов (правило, 1);
debug_limit_init - давать больше информации о инициализации лимитов
(правило, 1);
debug_threshold - отладка событий порогов (правило, 1);
debug_threshold_init - давать больше информации о инициализации порогов
(правило, 1).
Каждый параметр отладки принимает уровень отладки как аргумент, макси-
мальный уровень отладки для каждого параметра определён как номер в
скобках. Если в скобках есть слово ``отдельно'', то этот параметр дол-
жен располагаться отдельно, если в скобках есть слово ``правило'', то
этот параметр может быть указан в секциях global, rule, rulepat и
autorule.
По умолчанию отладка отключена.
Пример:
debug_worktime = 1;
debug {
debug_limit_init = 1;
}
В этом примере в лог-файл будет посылаться детальная информация о
интервалах параметров worktime и об инициализации лимитов для всех пра-
вил.
ФАЙЛЫ
ipa.conf
(запустите ipa с ключём -h, чтобы увидеть путевое имя конфигурационного
файла, используемое по умолчанию)
ДРУГИЕ ИСТОЧНИКИ
ipa(8), ipactl(8), ipastat(8), ipastat.conf(5), ipa_mod(3)
АВТОР
Andrey Simonenko <simon@comsys.ntu-kpi.kiev.ua>
НЕДОРАБОТКИ
Если вы обнаружите какие-либо ошибки, то, пожалуйста, сообщите мне по
email.
16 апреля 2005 г. IPA.CONF(5)