Этот раздел описывает все, что вы действительно должны знать для построения
пакетного фильтра, удовлетворяющего вашим потребностям.
Ядро стартует с тремя списками правил; эти списки называются firewall-цепочками
или просто цепочками. Три цепочки называются input, output и forward. Когда
приходит пакет (скажем, через плату ethernet) ядро использует цепочку input,
чтобы решить судьбу пакета. Если пакет фильтр пропустит пакет, то ядро решает,
куда послать пакет дальше (это называется маршрутизацией). Если пакет
предназначен для другой машины, ядро консультируется с цепочкой forward.
И наконец, прежде, чем пакет выйдет через сетевой интерфейс, ядро
консультируется с цепочкой output.
Цепочка - контрольный список правил. Каждое правило говорит "если заголовок
пакета походит на это, то с пакетом поступить так-то'. Если правило не
применимо к пакету, то рассматривается следующе правило в цепочке. Наконец,
если никакие правил не подошли, то ядро обращается к стратегии цепочек, чтобы
решить, что делать. В системе с повышенными требованиями к безопасности, эта
стратегия обычно заставляет ядро отклонить или отвергнуть пакет.
Для любителей ASCII-картинок, нарисован полный путь пакета, входящего в машину.
----------------------------------------------------------------
| ACCEPT/ интерфейс lo |
v REDIRECT _______ |
--> C --> S --> ______ --> D -> ~~~~~~~~~~ ->|forward|----> _______ -->
h a |input | e {Решение о } |цепоч- | |output |ACCEPT
e n |цепоч-| m {маршр-ции } |__ка___| --->|цепоч- |
c i |__ка__| a ~~~~~~~~~~~ | | ->|__ка___|
k t | s | | | | |
s y | q | v | | |
u | v e v DENY/ | | v
m | DENY/ r Местный процесс REJECT | | DENY/
| v REJECT a | | | REJECT
| DENY d --------------------- |
v e -----------------------------
DENY
Вот методическое описание каждой стадии:
- Контрольная сумма(Checksum):
Проверка целостности пакета. Если контрольная сумма не совпадает, то пакет
отбрасывается(DENY).
- Здравомыслие(Sanity):
На самом деле проверка на правильность формата пакета проводится перед
каждой цепочкой, но цепочка input наиболее важна. Некоторые пакеты
неправильного формата могли бы запутать код, обеспечивающий проверку
правила, вот такие пакеты здесь и отбрасываются (DENY) (если такое
случилось, то в syslog помещается сообщение).
- Цепочка input:
Это - первая firewall цепочка, проверяющая пакет. Если цепочки на приняла
решение об отбрасывании(DENY) или отклонении(REJECT) пакета, пакет идет
дальше.
- Демаскарадинг(Demasquerade):
Если пакет является ответом на замаскараденный пакет, он демаскарадируется, и
перебрасывается прямо на цепочку output. Если вы не используете IP
маскарадинг, то можете мысленно стереть это место в диаграмме.
- Решение о маршрутизации:
Поле адреса назначения исследуется кодом маршрутизации, чтобы решить, не
направлен ли этот пакет локальному процессу (см. "Локальный процесс"
ниже) или послан удаленной машине (см. "цепочку forward" ниже).
- Локальный процесс:
процесс, выполняющийся на машине может получать пакеты после шага "Решение
о маршрутизации", и может отправлять пакеты (которые проходят шаг "Решения
о маршрутизации" и затем пересекают цепочку output).
- Интерфейс lo:
Если пакеты из локального процесса предназначены локальному процессу,
они пройдут цепочку output с интерфейсом, установленным в "lo", и возвратятся
через входную цепочку с интерфейсом тоже "lo". Интерфейс lo обычно
называется петлевым интерфейсом (loopback).
- Локальный(local):
Если пакет не был создан локальным процессом, то цепочка forward проверяет
его, иначе пакет идет на цепочку output.
- Цепочка forward:
Эту цепочку проходят любые пакеты, которые пытаются уйти на другую машину.
- Цепочка output:
Эта цепочка проверяет все пакеты прежде, чем выпустить их наружу.
Использование ipchains
Сначала убедитесь, что ваша версия ipchains соответствует той версии, о
которой рассказывается в этом документе:
$ ipchains --version
ipchains 1.3.9, 17-Mar-1999
Обратите внимание, что я рекомендую 1.3.4 (у которого нет никаких длинных
опций, типа `--sport'), или 1.3.8 или выше; они очень устойчивы.
Ipchains имеет довольно подробный man (man ipchains
), а если вам нужны
подробности, вы можете проверить программный интерфейс (man 4 ipfw
), или файл
net/ipv4/ip_fw.c
в исходных текстах ядра 2.1.x, который является (очевидно)
авторитарным.
Имеется также превосходный краткий справочник Скотта Бронсона в пакете с
исходными текстами в форматах A4 и US Letter Postscript(TM).
С ipchains можно делать множество вещей. Во-первых, управлять целыми цепочками.
Изначально у вас есть три встроенных цепочки: input, forward и output, которые
вы не можете удалять.
- Создать новую цепочку (-N).
- Удалить пустую цепочку (-X).
- Изменить стратегию для встроенной цепочки (-P).
- Выдать список правил цепочки (-L).
- Удалить правила из цепочки (-F).
- Обнулить счетчики пакетов и байтов во всех правилах цепочки (-Z).
Имеется несколько способов управлять правилами внутри цепочки:
- Добавить новое правило к цепочке (-A)
- Вставить новое правило в определенную позицию цепочки (-I)
- Заменить правило в определенной позиции цепочки (-R)
- Удалить правило в определенной позиции цепочки (-D)
- Удалить первое правило в цепочке, удовлетворяющее условию (-D)
Есть несколько операций для маскарадинга, которые находятся в ipchains из-за
отсутствия более подходящего места для их размещения:
- Вывести текущие параметры маскарадинга (-M -L)
- Установить значения таймаутов для маскарадинга (-M -S)
(Но см. ``Я не могу установить таймауты маскарадинга!").
Последняя (и, возможно, наиболее полезная) функция позволяет вам проверить,
что случилось бы с данным пакетом, если бы он должен был пересечь
данную цепочку.
Обработка одним правилом
Это - "бутерброд" ipchains; правила управления. Наиболее часто вы вероятно
используете команды добавления (-A) и удаления (-D). Другие (-I для вставки и
-R для замены) - простые расширения этих концепций.
Каждое правило определяет набор условий отбора (например по полю "адрес
назначения") и обработки пакетов. Например, вы можете захотеть отвергать все
ICMP пакеты, исходящие с IP адреса 127.0.0.1. В этом случае наши условия
заключаются в том, что протокол должен быть ICMP и исходный адрес 127.0.0.1.
Наше действие - "DENY"(отбросить).
127.0.0.1 - это "петлевой" интерфейс, который у вас будет существовать, даже
если у вас отсутствует реальное сетевое соединение. Вы можете использовать
программу "ping", чтобы сгенерировать такие пакеты (она просто посылает тип
ICMP 8 (запрос ECHO), на которые все кооперативные хосты должны из вежливости
ответить пакетами с типом ICMP 0 (ответ ECHO)). Это полезно для тестирования.
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.2/0.2/0.2 ms
# ipchains -A input -s 127.0.0.1 -p icmp -j DENY
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
#
Вы видите, что первый ping проходит нормально (опция "-c 1' означает, что
надо послать один пакет).
Затем мы прибавляем (-A) к цепочке "input" правило, определяющее, что
пакеты от 127.0.0.1 ("-s 127.0.0.1') протокола ICMP ("-p ICMP') мы
должны отбросить(DENY) ("-j DENY').
Затем мы проверяем наше правило, вторично запустив ping. Программа попытается
дождаться ответа, который так и не придет.
Мы можем удалить правило одним из двух способов. Во-первых, так как мы знаем,
что это - единственое правило во входной цепочке, то мы можем использовать
удаление по номеру. Удаляем правило 1 в цепочке:
# ipchains -D input 1
#
Второй способ состоит в применении зеркальную команде -A команду -D.
Это полезно, когда у вас сложная цепочка правил, и вы не хотите выяснять
номер правила. В этом случае, мы действовали бы так:
# ipchains -D input -s 127.0.0.1 -p icmp -j DENY
#
Синтаксис -D должен иметь такие же опции, что и -A (или -I или -R).
Если в той же самой цепочке имеются несколько идентичных правил,
то будет удалено только первое из них.
Указание правил фильтрации
Мы видели, что "-p" применяется для определения протокола, а " -s' для
определения исходного адреса, но имеются и другие опции, которые мы можем
использовать для определения характеристик пакета. Ниже такие опции
поясняются очень подробно.
Определение адресов назначения и источника
IP адреса источника (-s) и назначения (-d) могут быть определены четырьмя
способами. Наиболее общий способ состоит в том, чтобы использовать полное имя,
типа "localhost" или "www.linuxhq.com". Второй способ состоит в том, чтобы
указать IP адрес типа "127.0.0.1".
Третий и четвертый способ позволяют указать группы адресов IP, типа
"199.95.207.0/24" или "199.95.207.0/255.255.255.0".
Они оба определяют любой адрес IP от 192.95.207.0 до 192.95.207.255
включительно; цифры после "/" сообщают, какая часть IP адреса является
значительной. "/32" или "/255.255.255.255" - значение по умолчанию
(соответствует всем IP адресам). Чтобы указать любой адрес, можно
использовать маску "/0":
# ipchains -A input -s 0/0 -j DENY
#
Однако, такая запись используется крайне редко, потому что тот же эффект
достигается, если в правиле совсем не указывать адрес.
Указание инверсии
Многие флажки, включая "-s' и "-d' могут иметь параметры, которым предшествует
"!' (произносится "не') для выделения адресов, НЕ равных этим данным. Например,
"-s! localhost' соответствует любому пакету, не исходящему из localhost.
Указание протокола
Протокол может быть определен флажком "-p". Протокол может быть числом (если вы
знаете числовые значения протокола для IP) или именем типа "TCP", "UDP" или
"ICMP". Регистр букв не имеет значения, так что "tcp"понимается эквивалентно
"TCP".
Имени протокола может предшествовать "!" для инверсии заданных параметров,
напр., "-p! TCP'.
Указание портов UDP и TCP
В специальных случаях, когда определен протокол TCP или UDP, может
указываться дополнительный параметр, указывающий порт TCP или UDP, или
(включительно) диапазон портов (но см. ``Обработка фрагментов" ниже).
Диапазон определяется с помощью символа ":', типа "6000:6010', что означает
11 портов с номерами от 6000 до 6010. Если нижняя граница не указана, то
значение по умолчанию 0. Если верхний предел опущен, это значение по умолчанию
65535. Напр., для указания TCP соединений, исходящих из первых 1024 портов,
пишем так: "-p TCP -s 0.0.0.0/0:1023'. Номера порта могут быть определены
именами, напр. "www'.
Обратите внимание, что спецификации порта можно предшествовать "!", который
инвертирует это условие. Вот так можно определить любой TCP пакет, кроме www:
-p TCP -d 0.0.0.0/0 ! www
Важно понять что спецификация
-p TCP -d ! 192.168.1.1 www
очень отличается от
-p TCP -d 192.168.1.1 ! www
Первое определяет любой TCP пакет на WWW порту любой машины, кроме
192.168.1.1. Второй определяет любое TCP соединение на любом порту на
192.168.1.1, кроме WWW порта.
В заключение, случай для не WWW порта и не 192.168.1.1:
-p TCP -d ! 192.168.1.1 ! www
Указание типа и кода ICMP
ICMP также может принять необязательный параметр, но поскольку ICMP не
имеет портов, (ICMP имеет тип и код) они имеют другое значение.
Вы можете указать их как ICMP имена (используйте ipchains -h icmp
для вывода
списка имен) после опции "-s', или как числовой тип и код ICMP, где тип
следует за опцией "-s', а код следуют за опцией "-d".
ICMP имена довольно длинны: вам только нужно использовать достаточно
символов, чтобы сделать имя, отличное от других имени.
Вот маленькая таблица некоторых из наиболее общих ICMP пакетов:
Номер Имя Требуется для
0 echo-reply ping
3 destination-unreachable любого TCP/UDP трафика
5 redirect маршрутизации, если не запущен демон маршрутизации
8 echo-request ping
11 time-exceeded traceroute
Обратите внимание, что именам ICMP в настоящее время не могут
предшествовать "!".
ВНИМАНИЕ!
Ни в коем случае не запрещайте передачу ICMP-пакетов типа 3 !
(См. `` ICMP пакеты " ниже).
Указание интерфейса
Опция "-i" определяет имя интерфейса. Интерфейс - физическое устройство, на(из)
который(ого) приходит(уходит) пакет . Вы можете использовать команду ifconfig
,
чтобы посмотреть какие интерфейсы в системе "подняты" (то есть работают в
настоящий момент).
Интерфейс для входящих пакетов (то есть пакетов, проходящих цепочку input)
является интерфейсом, на который они пришли. Логически следует, что интерфейс
для исходящих пакетов (пакеты, проходящие цепочку output) - интерфейс, через
который они выйдут. Интерфейс для пакетов, проходящих цепочку forward -
тоже интерфейс, через который они выйдут; довольно спорное решение, как
мне кажется.
Совершенно допустимо определить интерфейс, который в настоящее время
не существует; правило ничему не будет соответствовать до тех пор, пока
не появится интерфейс.
Это чрезвычайно полезно для коммутируемой PPP связи (обычно интерфейс
ppp0) и т.п..
Как специальный случай, имя интерфейса, оканчивающееся на "+" будет
соответствовать всем интерфейсам (существуют ли они в настоящее время или нет),
которые начинаются с той же последовательности символов. Например, чтобы
определить правило, которое соответствует всем интерфейсам PPP, использовалось
бы опция "-i ppp+'.
Имени интерфейса может предшествовать "!" для соответствия пакету,
который не соответствует определенному интерфейсу(ам).
Указание только пакетов TCP SYN
Иногда полезно разрешить TCP соединения в одном направлении. Например, вы
могли бы захотеть позволить соединение с внешним WWW сервером, но не
соединения от этого сервера.
Наивно было бы блокировать пакеты TCP, исходящие от сервера. К
сожалению, TCP соединения для своей работы требуют, чтобы пакеты ходили в
обоих направлениях.
Решение состоит в блокировании только пакетов, используемых для запроса
соединения. Эти пакеты называются SYN пакетами (ok, технически это пакеты с
установленным флажком SYN, и опущенными флажками ACK и FIN, но мы называем их
SYN пакетами). Отвергая только эти пакеты, мы можем прервать попытки
инициировать соединение.
Для этого используется флажок "-y": он допустим только для правил, которые
относятся к TCP протоколу. Например, вот как указываются попытки TCP соединения
от 192.168.1.1:
-p TCP -s 192.168.1.1 -y
Аналогично, этот флажок может быть инвертирован, с помощью "!", что
означает все пакеты, кроме пакетов инициирования соединения.
Обработка фрагментов
Иногда пакет слишком большой, чтобы пересылаться одним куском. Когда это
случается, пакет делится на фрагменты, и посылается как несколько пакетов.
Другой конец собирает несколько фрагментов в один целый пакет.
Проблема с фрагментами состоит в том, что некоторые из спецификаций,
перечисленных выше (в частности порта источника, порта назначения, тип ICMP,
код ICMP, или SYN флажок TCP) требуют, чтобы ядро анализировало начало пакета,
которое содержится только в первом фрагменте.
Если ваша машина - единственое соединение со внешней сетью, то вы можете
сообщить Linux ядру, что надо собирать все фрагменты, которые
проходят через него, компилируя ядро с установкой IP: always defragment "Y"
.
Это аккуратное решение проблемы.
В любом случае, важно понять, как фрагменты обрабатываются правилами фильтрации.
Любое правило фильтрации, которое запрашивает информацию, не будет срабатывать,
если не будет соответствия. Это означает, что первый фрагмент обработается
подобно любому другому пакету. Второй и далее фрагментя не будут обрабатываться.
Таким образом правило "-p TCP -s 192.168.1.1 www'
(указание исходного порта
"www") никогда не будет соответствовать фрагменту (не первому фрагменту).
Обратное правило "-p TCP -s 192.168.1.1 ! www'
тоже не сработает.
Однако, вы можете определить правило специально для второго и далее
фрагментов, используя флажок "-f". Ясно-понятно, что его нельзя применять
при указании TCP или UDP порта, типа ICMP, кода ICMP или TCP SYN, так как
эта информация во вторых и последующих фрагментах отсутствует.
Можно также указать, что правило не применяется ко второму и последующим
фрагментам, указав '!' перед '-f'.
Обычно это считается безопасным для получения второго и дальнейших фрагментов,
так как фильтр отбросит при необходимости первый фрагмент, и таким
образом все остальные фрагменты, однако, сейчас стало известно об ошибках,
которые могут повесить машину простой посылкой фрагментов. Учтите это.
Обратите внимание: пакеты некорректного формата (TCP, UDP и ICMP пакеты,
слишком короткие для обработки firewalling кодом, настолько короткие, что из
них нельзя получить информацию о портах или коде и типе ICMP) тоже
обрабатываются как фрагменты. Только TCP фрагменты, начинающиеся с позиции 8
явно отбрасываются firewall кодом (в syslog отправляется соответствующее
сообщение).
Например, следующее правило отбросит любые фрагменты, приходящие на
192.168.1.1:
# ipchains -A output -f -d 192.168.1.1 -j DENY
#
Фильтрация побочных эффектов
Отлично, теперь мы знаем все способы, которыми мы можем
определять соответствия, используемые в правилах, для пакетов.
Если пакет соответствует правилу, происходят следующие вещи:
- Счетчик байтов для того правила увеличивается на размер пакета (заголовок и
все остальное).
- Счетчик пакетов для того правила увеличивается.
- Если правило предусматривает это, то пакет рагистрируется в журнале.
- Если правило предусматривает это, изменяется поле Type Of Service.
- Если правило предусматривает это, пакет помечается (не для ядер 2.0)
- Анализируется, какое действие над пакетом указывается в правиле,
чтобы решить дальнейшую судьбу пакета.
Для разнообразия, я буду описывать их в порядке важности.
Указание действия
Описание действия сообщает ядру, что делать с пакетом, который соответствует
правилу. Ipchains для определения действия использует флаг "-j" (наверное
"jump-to"). Выходное имя должно быть менее 8 символов длиной. Имена
регистрозависимы, варианты "RETURN" и "return" совершенно различны.
Самый простой случай - когда действие не определено. Этот тип правила (часто
называемый правилом "учета") полезен для просто подсчета пакетов некотороых
типов. Соответствуют ли эти правила или нет, ядро просто переходит к следующему
правилу в цепочке. Например, чтобы подсчитать число пакетов от 192.168.1.1,
мы могли бы сделать так:
# ipchains -A input -s 192.168.1.1
#
(Используя "ipchains -L -v' мы можем увидеть счетчики байтов и пакетов,
связанные с каждым правилом).
Есть шесть специальных действий. Первые три, ACCEPT, REJECT и DENY довольно
просты. ACCEPT позволяет пропустить пакет. DENY отбрасывает пакет, как будто
он никогда не приходил. REJECT тоже отбрасывает пакет, но (если это не ICMP
пакет) генерирует ICMP-ответ источнику, сообщая, что адресат недостижим.
Следующий, MASQ, говорит ядру, что надо подменить пакет. Для этого нужно,
чтобы ваше ядро скомпилировалось с разрешенным IP маскарадингом. Подробности
см. в Masquerading-HOWTO и приложении ``Различия между ipchains и ipfwadm".
Это действие допустимо только для пакетов, проходящих через цепочку forward.
Еще одно важное действие - REDIRECT, которое сообщает, что пакет надо
переадресовать на локальный порт машины вместо того места, куда он
действительно направляется.
Это может быть определено только для правил, с указанными TCP или UDP
протоколами. Необязательно можно определить порт (имя или номер) после
"-j REDIRECT", что заставит ядро перенаправить пакет на этот порт, даже если
пакет был адресован другому порту.
Это действие допустимо только для пакетов, проходящих через цепочку forward.
Последнее действие - RETURN приводит к немедленному прекращению дальнейших
проверок в цепочке. (См. ниже ``Установка политики'').
Любое другое действие определяет пользовательскую цепочку (как описано в
``Обработка всей цепочки" ниже). Пакет начнет просматриваться правилами в этой
цепочке. Если эта цепочка не решает судьбу пакета, то, как только обход этой
цепочке закончится, продолжится проверка правил со следующего правила
текущей цепочки.
Подошло время для еще одной ASCII-картинки. Рассмотрите две (глупых) цепочки:
input (встроенная цепочка) и Test (пользовательская цепочка).
`input' `Test'
------------------------------- -------------------------------
| Правило1: -p ICMP -j REJECT | | Правило1: -s 192.168.1.1 |
|-----------------------------| |-----------------------------|
| Правило2: -p TCP -j Test | | Правило2: -d 192.168.1.1 |
|-----------------------------| -------------------------------
| Правило3: -p UDP -j DENY |
-------------------------------
Рассмотрим TCP пакет идущий из 192.168.1.1 на 1.2.3.4. Он поступает на цепочку
input и не соответствует правилу Правило1.
Правило2 подходит, и его действие - Test, так что проверка следующего
правило начнется с первого правила Test. Правило1 в Test соответствует, но
действие в ней не указано, поэтому осуществляется переход к Правило2. Оно не
соответствует, так что мы достигли конца цепочки. Мы возвращаемся к цепочке
input, где мы дошли только до Правило2, так что мы теперь проверяем Правило3,
который тоже не соответствует.
Так что путь пакета:
v __________________________
`input' | / `Test' v
------------------------|--/ -----------------------|----
| Правило1 | /| | Правило1 | |
|-----------------------|/-| |----------------------|---|
| Правило2 / | | Правило2 | |
|--------------------------| -----------------------v----
| Правило3 /--+___________________________/
------------------------|---
v
В разделе ``Как организовать ваши Firewall правила" описано как сохдавать ваши
собственные пользовательские цепочки.
Регистрация пакетов
Это полезный побочный эффект; вы можете отметить в журнале соответствующий
условию правила пакет, используя флажок "-l". Для стандартных пакетов это
обычно не нужн, но это весьма полезная возможность в тех случаях, когда вы
хотите отловить какие-то особые события.
Ядро записывает в журнал записи типа:
Packet log: input DENY eth0 PROTO=17 192.168.2.1:53 192.168.1.1:1025
L=34 S=0x00 I=18 F=0x0000 T=254
Эта журнальная запись создается с таким расчетом, чтобы быть краткой, но и
содержать техническую информацию, полезную только для гуру-сетевиков, но она
может быть полезной и для остальной части пользователей. Журнальная запись
расшифровывается так:
- `input' - цепочка, которая содержала правило, чье соответствие пакету
вызывает запись сообщения в журнал.
- `DENY' - то, что правило будет делать с пакетом. Если это - "-", то правило
не воздействует на пакет (учетное правило).
- "eth0" - имя интерфейса. Поскольку это была цепочка input, то значит
пакет пришел на "eth0".
- `PROTO=17' означает, что это пакет протокола номер 17. Список номеров
протоколов задан в
"/etc/protocols'
. Наиболее часто используемые протоколы
1 (ICMP), 6 (TCP) и 17 (UDP).
- "192.168.2.1" - это IP адрес, с которого пришел пакет
- ":53" означает, что порт источника имеет номер 53. В "/etc/services' это
описано как порт `domain' (то есть это - вероятно ответ DNS). Для UDP и TCP,
этот номер порта источника. Для ICMP, это - тип ICMP. Для других он будет
65535.
- "192.168.1.1" - IP адрес назначения.
- ":1025" означает, что порт назначения имеет номер 1025. Для UDP и TCP
этот номер - порт назначения. Для ICMP это - код ICMP. Для других он будет
65535.
- "L=34' означает, что пакет был общей длиной 34 байта.
- "S=0x00' означает поле Type of Service (делится 4, чтобы получить Type of
Service как используется ipchains).
- `I=18' идентификатор IP.
- "F=0x0000' является 16-разрядным смещением фрагмента плюс флажки. Значение,
начинающееся с "0x4" или "0x5", означает, что установлен бит Don't
Fragment. "0x2" или "0x3" означает установку бита `More Fragments'; после
этого ожидается прибытие следующих фрагментов. Остальная часть числа -
смещение этого фрагмента, деленное на 8.
- "T=254' является временем жизни (Time To Live) пакета. При каждом переходе
от маршрутизатора к маршрутизатору это значение уменьшается, и оно обычно
начинается с 15 или 255.
- `(#5)' может вставляться на более современных ядрах (возможно после 2.2.9).
Это - номер правила, которое зарегистрировало пакет в журнале.
На стандартной Linux системе, этот вывод ядра фиксируется klogd (kernel
logging daemon) который поручает это syslogd (system logging daemon).
"/etc/syslog.conf'
управляет поведением syslogd, определяя адресата
для каждого "facility" (в нашем случае, facility - "ядро") и "уровень" (для
ipchains, используемый уровень - "info").
Например, мой (Debian) /etc/syslog.conf
содержит две строки, которые
соответствуют "kern.info":
kern.* -/var/log/kern.log
*.=info;*.=notice;*.=warn;\
auth,authpriv.none;\
cron,daemon.none;\
mail,news.none -/var/log/messages
Этот означает, что сообщения дублируются в "/var/log/kern.log'
и
"/var/log/messages'
. Подробности см. в "man syslog.conf'
.
Управление Type Of Service
В IP заголовке имеются четыре редко-используемых бита, называемых Type of
Service (TOS) битами. Они управляют обработкой пакетов; четыре бита -
"Минимальная задержка", "Максимальная производительность", "Максимальная
надежность" и "Минимальная стоимость". Установлен может быть только один из
этих битов. Rob van Nieuwkerk, автор TOS-кода, разъясняет их смысл
следующим образом:
"Минимальная задержка" кажется мне наиболее важной установкой. Я
включаю ее для "интерактивных" пакетов на моем upstream маршрутизаторе
(Linux). Передо мною находится 33kб модемная связь. Linux располагает по
приоритетам пакеты из 3 очередей. Таким образом я получаю приемлемую
интерактивную эффективность при одновременном выполнении объемных
загрузок (Если бы не было такой большой очереди в драйвере
последовательной линии, то результат был бы даже лучше, но и сейчас
время ожидания составляет менее 1.5 секунды).
Обратите внимание: вы в явном виде не имеете никакого контроля над входящими
пакетами; вы можете только управлять приоритетами пакетов, уходящих с вашей
машины. Чтобы договориться о приоритетах с другим концом линии, должен
использоваться протокол типа RSVP (о котором я не знаю ничего, так что меня
не спрашивайте).
В наиболее общем случае надо установить для управляющих соединений telnet и
ftp "Минимальную задержку", а для данных FTP - "Максимальную
производительность". Это можно выполнить следующим образом:
ipchains -A output -p tcp -d 0.0.0.0/0 telnet -t 0x01 0x10
ipchains -A output -p tcp -d 0.0.0.0/0 ftp -t 0x01 0x10
ipchains -A output -p tcp -s 0.0.0.0/0 ftp-data -t 0x01 0x08
Флажок "-t" берет два дополнительных параметра в hex-виде. С их помощью можно
производить сложные установки битов TOS: первая маска - операция AND над
текущим значением TOS пакета, а вторая маска - XOR над тем же самым значением.
Если вам это все равно не понятно, используйте следующую таблицу:
TOS имя Значение Типичное применение
Минимальная задержка 0x01 0x10 ftp, telnet
Максимальная производительность 0x01 0x08 ftp-data
Максимальная надежность 0x01 0x04 snmp
Минимальная стоимость 0x01 0x02 nntp
Andi Kleen указывает на следующее (немного подредактировано):
Возможно было бы полезно добавить ссылку на txqueuelen параметр ifconfig
для обсуждения битов TOS. Заданная по умолчанию длина очереди устройства
настроена для ethernet-карточек, для модемов она является слишком длинной и
в результате 3-полосный планировщик (на котором основаны очереди TOS)
работает неоптимально. Было бы лучше установить это значение между 4-10
для модема или одного B-канала ISDN связи: на коммутируемых устройствах
необходима более длинная очередь.
Это проблема в ядрах 2.0 и 2.1, но в 2.1 есть флажок ifconfig (в недавних
nettools), в то время как ядро 2.0 требуется патчить.
Итак, чтобы увидеть максимальную пользу от манипулирования TOS для модемной
PPP связи, внесите строку "ifconfig $1 txqueuelen' в ваш сценарий
/etc/ppp/ip-up. Числовой параметр зависит от скорости модема и объема буфера
модема; далее опять говорит Andi:
Наилучшее значение для данной конфигурации требуется подобрать
экспериментально. Если очереди на маршрутизаторе слишком короткие, то
пакеты станут пропадать. Также конечно польза будет даже без перезаписи
TOS, перезапись TOS может вам помочь для некооперативнях программ.
(Но все стандартные программы linux кооперативные).
Маркировка пакета
Это позволяет осуществлять сложные и мощные взаимодействия с новой реализацией
Качества Сервиса (Quality of Service) Алексея Кузнецова, для основанного на
метках форвардинга в ядрах серии 2.1. Более пока ничего не известно. В ядрах
2.0 эта опция игнорируется.
Обработка всей цепочки
Очень полезная возможность ipchains - способность группировать связанные
правила в цепочки. Вы можете нызывать цепочки как вам хочется при условии, что
имена не совпадают с именами встроенных цепочек (input, output и forward) или
действий (MASQ, REDIRECT, ACCEPT, DENY, REJECT или RETURN).
Я предлагаю вам избегать полностью использования верхнего регистра меток,
так как я могу использовать их в будущих расширениях. Имя цепочки может быть
длиной до 8 символов.
Создание новой цепочки
Давайте создадим новую цепочку. Я назову ее test -- вот такое у меня богатое
воображение!
# ipchains -N test
#
Это просто пример. Теперь вы можете помещать правила в нее как было описано
выше.
Удаление цепочки
Удаление цепочки также просто.
# ipchains -X test
#
Почему "-X"? Ну, это тоже хорошая буква.
Есть пара ограничений на удаление цепочки: они должны быть пустыми (см.
``Очистка цепочки" ниже) и они не должны быть действием любого правила. Вы не
можете удалить ни одну из трех встроенных цепочек.
Очистка цепочки
Есть простой способ освобождения всех правил в цепочке использованием команды
"-F".
# ipchains -F forward
#
Если вы не указали цепочку, то будут очищены все цепочки.
Просмотр цепочки
Вы можете просмотреть все правила в цепочке, используя команду "-L".
# ipchains -L input
Chain input (refcnt = 1): (policy ACCEPT)
target prot opt source destination ports
ACCEPT icmp ----- anywhere anywhere any
# ipchains -L test
Chain test (refcnt = 0):
target prot opt source destination ports
DENY icmp ----- localnet/24 anywhere any
#
"refcnt" в test - это число правил, в которых test назначен как действие.
Это значение должно быть нулем (а цепочка пустой) перед удалением цепочки.
Если имя цепочки опущено, распечатываются все цепочки, даже пустые.
Есть три опции, которые могут сопровождать опцию "-L". "-n" (numeric) опция
очень полезна, поскольку не дает ipchains пытаться переводить адреса IP в
доменные имена, что (если вы, как и многие, используете DNS) приведет к
большим задержкам, если ваш DNS неправильно установлен, или вы фильтруете
наружние DNS запросы. Также эта опция указывает, что порты должны быть
распечатаны как числа, а не как имена.
Опция "-v" показывают вам все подробности правил, такие как пакетные и байтовые
счетчики, маски TOS, интерфейс и метку пакета. Иначе эти значения будут
опущены. Например:
# ipchains -v -L input
Chain input (refcnt = 1): (policy ACCEPT)
pkts bytes target prot opt tosa tosx ifname mark source destination ports
10 840 ACCEPT icmp ----- 0xFF 0x00 lo anywhere anywhere any
Обратите внимание, что пакетные и байтовые счетчики распечатаны, с
использованием суффиксов "K", "М" или "G" для 1000, 1,000,000 и 1,000,000,000
соответственно. Использование флажка "-x" (expand numbers) также распечатывает
числа полностью, независимо от их значений.
Сброс (обнуление) счетчиков
Полезно иметь возможность сбросить счетчики. Это делается опцией "-Z".
Например:
# ipchains -v -L input
Chain input (refcnt = 1): (policy ACCEPT)
pkts bytes target prot opt tosa tosx ifname mark source destination ports
10 840 ACCEPT icmp ----- 0xFF 0x00 lo anywhere anywhere any
# ipchains -Z input
# ipchains -v -L input
Chain input (refcnt = 1): (policy ACCEPT)
pkts bytes target prot opt tosa tosx ifname mark source destination ports
0 0 ACCEPT icmp ----- 0xFF 0x00 lo anywhere anywhere any
#
Проблема с этим подходом в том, что иногда вы должны знать значения счетчика
до того, как они сброшены. В вышеупомянутом примере, некоторые пакеты могли бы
пройти во время выполнения команд "-L" и "-Z". По этой причине вы можете
использовать "-L" и "-Z" вместе, сбрасывать счетчики при их просмотре. К
сожалению, если вы делаете это, вы не можете обрабатывать одну цепочку: вы
просматриваете и обнуляете все цепочки сразу.
# ipchains -L -v -Z
Chain input (policy ACCEPT):
pkts bytes target prot opt tosa tosx ifname mark source destination ports
10 840 ACCEPT icmp ----- 0xFF 0x00 lo anywhere anywhere any
Chain forward (refcnt = 1): (policy ACCEPT)
Chain output (refcnt = 1): (policy ACCEPT)
Chain test (refcnt = 0):
0 0 DENY icmp ----- 0xFF 0x00 ppp0 localnet/24 anywhere any
# ipchains -L -v
Chain input (policy ACCEPT):
pkts bytes target prot opt tosa tosx ifname mark source destination ports
10 840 ACCEPT icmp ----- 0xFF 0x00 lo anywhere anywhere any
Chain forward (refcnt = 1): (policy ACCEPT)
Chain output (refcnt = 1): (policy ACCEPT)
Chain test (refcnt = 0):
0 0 DENY icmp ----- 0xFF 0x00 ppp0 localnet/24 anywhere any
#
Установка политики
Мы упоминали о том, что случается, когда пакет доходит до конца встроенной
цепочки, когда обсуждали, как пакет идет по цепочкам в ``Указание действия"
выше. В этом случае, судьбу пакета определяет политика цепочки. Только
встроенные цепочки (input, output и forward) имеют политику, потому что, если
пакет достигает конца пользовательской цепочки, обход возвращается к предыдущей
цепочке.
Политика может быть любой из первых четырех специальных действий: ACCEPT, DENY,
REJECT или MASQ. MASQ допустим только для цепочки "forward".
Также важно обратить внимание, что действие RETURN в правиле в одной из
встроенных цепочек полезно для явного назначения политики цепочки, когда пакет
соответствует правилу.
Операции по маскарадингу
Есть несколько параметров, которые вы можете применить для IP Маскарадинга.
Они связаны с ipchains, потому что отдельный инструмента для них не написан
(хотя это изменится в будущем).
Команда IP Masquerading - "-M", и она может быть объединена с "-L", чтобы
отобразить текущие masqueraded соединения, или с " -S', чтобы установить
параметры маскарадинга.
Команда "-L" может сопровождаться "-n" (чтобы показать числа вместо имен
хостов и портов) или "-v" (показывать deltas в порядковых числах для
masqueraded соединений, если вас это заботит).
Команда "-S' должна сопровождаться тремя значениями таймаутов, в секундах:
для TCP сеансов, для TCP сеансов после пакета FIN и для UDP пакетов. Если вы
не хотите изменять одно из этих значений, просто дайте значение "0'.
Значения по умолчанию перечислены в "/usr/src/linux/include/net/ip_masq.h'
, в
настоящее время это 15 минут, 2 минуты и 5 минут соответственно.
Наиболее общее значение для изменения - первое, для FTP (см. ``Кошмары FTP"
ниже).
Обратите внимание на проблемы с установкой таймаутов, перечисленные
в ``Я не могу установить таймауты для маскарадинга!".
Проверка пакета
Иногда вы хотите знать, что происходит, когда некоторый пакет входит на вашу
машину, напр., для отладки ваших firewall цепочек. В ipchains есть команда
"-C", которая использует те же самые подпрограммы, которые ядро использует для
диагностики реальных пакетов.
Вы указываете, какой цепочке проверить пакет, указывая имя после параметра
"-C". В то время как ядро всегда начинает с цепочек input, output или forward,
вы можете начать тестирование с любой цепочки.
Подробности "пакета" определяются по тому же самому синтаксису, который
используется для определения правил firewall. В частности протокол ("-p"),
исходный адрес ("-s'), адрес назначения ("-d') и интерфейс ("-i') обязательны.
Если протокол - TCP или UDP, то должны быть указаны одиночные порты источника и
адресата, а для ICMP протокола должны быть определены тип и код ICMP (если
не определен флажок "-f' для указания правил фрагментов, в этом случае
опции запрещены).
Если протокол - TCP (и флажок "-f" не определен), можно определять флажок
"-y", чтобы указать, что тестовый пакет должен иметь установленным бит SYN.
Вот пример тестировочного TCP SYN пакета с хоста 192.168.1.1 порт
60000 к хосту 192.168.1.2 порт www, приходящий на интерфейс eth0 в цепочку
"input". (Это - классическая иницциация входящего WWW соединения):
# ipchains -C input -p tcp -y -i eth0 -s 192.168.1.1 60000 -d 192.168.1.2 www
packet accepted
#
Несколько правил одновременно и наблюдение за происходящим
Иногда одна командная строка может воздействовать на несколько правил сразу.
Это происходит по двум причинам. Во-первых, если вы определяете имя хоста,
которое преобразуется (используя DNS) в несколько IP адресов, ipchains будет
действовать так, как будто вы ввели несколько команд для каждой комбинации
адресов.
Так, если имя хоста "www.foo.com" указывает на три IP адреса, а имя хоста
"www.bar.com" - на два IP адреса, то команда "ipchains -A input -j REJECT -s www.bar.com -d www.foo.com'
добавила бы 6 правил ко цепочке input.
Другая причина, заставляющая ipchains выполнить несколько действий, состоит
в использовании флажка ("-b" -- bidirectional). Этот флажок заставляет
ipchains вести себя так, словно вы ввели команду дважды, поменяв во второй
команде местами значения параметров "-s' и "-d'. Так, чтобы запретить обмен
с хостом 192.168.1.1, вы могли бы напечатать следующее:
# ipchains -b -A forward -j REJECT -s 192.168.1.1
#
Лично мне опция "-b" не слишком нравится; если вам хочется удобства, см.
``Использование ipchains-save" ниже.
Опция "-b" может использоваться с командами вставки ("-I"), удаления ("-D")
(но без использования номера правила), добавления ("-A") и проверки ("-C").
Другой полезный флажок "-v" (verbose), который выводит информацию о том, что
ipchains делает с вашими командами. Это полезно, если вы имеете дело с
командами, которые могут производить множественные правила. Например, здесь мы
проверяем поведение фрагментов между 192.168.1.1 и 192.168.1.2.
# ipchains -v -b -C input -p tcp -f -s 192.168.1.1 -d 192.168.1.2 -i lo
tcp opt ---f- tos 0xFF 0x00 via lo 192.168.1.1 -> 192.168.1.2 * -> *
packet accepted
tcp opt ---f- tos 0xFF 0x00 via lo 192.168.1.2 -> 192.168.1.1 * -> *
packet accepted
#
У меня есть коммутируемое PPP соединение (-i ppp0)
. При каждой PPP-сессии
я скачиваю новости
(-p TCP -s news.virtual.net.au nntp)
и почту
(-p TCP -s mail.virtual.net.au pop-3)
. Для обновления
пакетов Debian я регулярно использую FTP-метод
(-p TCP -y -s ftp.debian.org.au ftp-data)
. По web я брожу через прокси моего
ISP (-p TCP -d proxy.virtual.net.au 8080)
, но ненавижу doubleclick.net
на
Dilbert Archive (-p TCP -y -d 199.95.207.0/24
и -p TCP -y -d 199.95.208.0/24)
.
Меня не беспокоят люди, заходящие на мой ftp пока я в Сети
(-p TCP -d $LOCALIP ftp)
, но мне не нравится, когда кто-то притворяется, что он
из моей внутренней сети (-s 192.168.1.0/24)
. Это обычно называется IP spoofing (спуфингом),
и для защиты от него в ядрах 2.1.х и выше существуют лучшие способы: см.
``Как мне установить защиту от IP спуфинга?''.
Эта установка довольно проста, потому что в моей внутренней сети
в настоящее время нет никаких других машин.
Я не хочу, чтобы любой локальный процесс (то есть Netscape, lynx и т.д.)
подсоединялся к doubleclick.net
:
# ipchains -A output -d 199.95.207.0/24 -j REJECT
# ipchains -A output -d 199.95.208.0/24 -j REJECT
#
Теперь я хочу установить приоритеты для различных исходящих пакетах (для
входящих пакетов это делать бессмысленно). Так как этих правил много, то имеет
смысл поместить их всех в одну цепочку по имени ppp-out.
# ipchains -N ppp-out
# ipchains -A output -i ppp0 -j ppp-out
#
Минимальная задержка для web и telnet.
# ipchains -A ppp-out -p TCP -d proxy.virtual.net.au 8080 -t 0x01 0x10
# ipchains -A ppp-out -p TCP -d 0.0.0.0 telnet -t 0x01 0x10
#
Низкая цена для ftp-data, nntp, pop-3:
# ipchains -A ppp-out -p TCP -d 0.0.0.0/0 ftp-data -t 0x01 0x02
# ipchains -A ppp-out -p TCP -d 0.0.0.0/0 nntp -t 0x01 0x02
# ipchains -A ppp-out -p TCP -d 0.0.0.0/0 pop-3 -t 0x01 0x02
#
Имеется несколько ограничений на пакеты, приходящие на интерфейс ppp0: давайте
создадим цепочку "ppp-in":
# ipchains -N ppp-in
# ipchains -A input -i ppp0 -j ppp-in
#
Теперь, никакие пакеты, приходящие на ppp0 не должны быть из сети
192.168.1.*, так что мы регистрируем их и отбрасываем:
# ipchains -A ppp-in -s 192.168.1.0/24 -l -j DENY
#
Я разрешаю входящие UDP пакеты для DNS (у меня стоит кэширующий сервер имен,
который пересылает все запросы к 203.29.16.1, так что я ожидаю ответы DNS
только от них), входящие пакеты ftp, и только ответные пакеты ftp-data
(которые должны идти только на порту с номером больше 1023, и не на портах X11
в районе примерно 6000).
# ipchains -A ppp-in -p UDP -s 203.29.16.1 -d $LOCALIP dns -j ACCEPT
# ipchains -A ppp-in -p TCP -s 0.0.0.0/0 ftp-data -d $LOCALIP 1024:5999 -j ACCEPT
# ipchains -A ppp-in -p TCP -s 0.0.0.0/0 ftp-data -d $LOCALIP 6010: -j ACCEPT
# ipchains -A ppp-in -p TCP -d $LOCALIP ftp -j ACCEPT
#
В заключение, даем добро для передачи от локального хоста к локальному хосту:
# ipchains -A input -i lo -j ACCEPT
#
Теперь, моя заданная по умолчанию сполитика на цепочке input - DENY, так что
все неподошедшее под условия правил цепочки выбрасывается:
# ipchains -P input DENY
#
ОБРАТИТЕ ВНИМАНИЕ: я не располагаю мои цепочки в этом порядке, поскольку
в то время, пока я их настраиваю, могли прийти пакеты. Самая надежная
политика - сперва назначить DENY, а затем вставлять правила. Конечно, если ваши
правила требуют поиска DNS для преобразования имен, то вы можете столкнуться с
проблемами.
Использование ipchains-save
После настройки firewall цепочек вам надо где-то сохранить их, чтобы эта
настройка не потерялась при перезагрузке машины.
Итак, ipchains-save - скрипт, который читает вашу текущую настройку цепочек и
сохраняет ее в файле. Я немного расскажу, что делает этот скрипт.
ipchains-save может сохранять одну или все цепочки (если имя цепочки не
определено). В настоящее время единственая опция скрипта - "-v", которая
печатает правила (на stderr) в том виде, как они записаны.
поскольку они сохранены. Также сохраняется политика цепочек input,
output и forward
# ipchains-save > my_firewall
Saving `input'.
Saving `output'.
Saving `forward'.
Saving `ppp-in'.
Saving `ppp-out'.
#
Использование ipchains-restore
ipchains-restore восстанавливает цепочки, сохраненные ipchains-save. У скрипта
две опции: "-v", которая описывает каждое добавленное правило, и "-f" которая,
вынуждает очистить пользовательские цепочки, если они существуют, как описано
ниже.
Если пользовательская цепочка найдена в input, ipchains-restore проверяет, не
существует ли уже цепочка. Если да, то вас спросят, нужно ли цепочки очистить
(от всех правил) или не восстанавливать эту цепочку. Если вы определили "-f"
в командной строке, то запроса не будет; цепочка будет очищена.
Например:
# ipchains-restore < my_firewall
Restoring `input'.
Restoring `output'.
Restoring `forward'.
Restoring `ppp-in'.
Chain `ppp-in' already exists. Skip or flush? [S/f]? s Skipping `ppp-in'.
Restoring `ppp-out'.
Chain `ppp-out' already exists. Skip or flush? [S/f]? f Flushing `ppp-out'.
#
Вперед
Назад
Содержание