Фильтрация пакетов, firewall и маскарадинг в Линуксе
Кто не спрятался, я не виноват!

© Александр Дилевский 06-15.06.1999.

О чем это вообще?

Это о пересылке (forwarding), маскарадинге (masquerading) и фильтрации IP-пакетов на Линуксе с ядрами 2.1.* и выше и, в частности, о программе ipchains. Ссылки на более подробные материалы смотри внизу. В этой статье не рассматриваются вопросы маршрутизации, подробности работы протоколов семейства TCP/IP и проксирования, а также подробности настройки и конфигурирования ядер, сетевых интерфейсов и комплексной защиты от хакеров ;-)

Как известно, все коммуникации, использующие протокол IP, передают данные в виде пакетов. В начале каждого пакета есть заголовок, в котором написано, от кого и кому этот пакет (в виде IP-адресов), к какому протоколу более высокого уровня он относится (ICMP, TCP, UDP и т.п.), в некоторых случаях (для протоколов UDP и TCP) - номера портов отправителя и получателя, а также другая специфическая информация.

На пути от отправителя к получателю пакет может проходить через промежуточные узлы. В зависимости от информации, которая содержится в заголовке IP-пакета, они могут этот пакет переслать на следующий узел (forward), передать локальной программе для обработки, уничтожить (deny), отвергнуть, т.е. уничтожить и отправить об этом уведомление отправителю (reject). Выбор и осуществление одного из этих действий и называется фильтрацией пакетов.

Возможность фильтрации встроена в ядро Линукса, но для установки конкретных правил используются отдельные программы. В ядрах 2.0.x использовалась программа ipfwadm, в ядрах 2.1.x и выше используется более мощная программа ipchains. ipfwadm в ядрах 2.1.x не работает в принципе, а ipchains может работать в ядрах 2.0.x после небольшого патча ядра.

Firewall (или "по-русски" - брандмауэр, хотя у меня язык не поворачивается его так называть) - это программа или специализированная железка, которая, основываясь на некоторых правилах, разрешает или запрещает передачу информации, проходящей через нее, с целью ограждения некоторой подсети от внешнего доступа или наоборот, для недопущения выхода наружу. Firewall может определять правомерность передачи информации на основе только заголовков IP-пакетов, а может анализировать и их содержимое, т.е. использовать данные протоколов более высокого уровня.

Маскарадинг - это подмена некоторых параметров в заголовках IP-пакетов, позволяющая машинам, не имеющим реальных IP-адресов, практически полноценно работать в интернете.

Прозрачное проксирование (transparent proxying) - это переадресация пакетов на другой порт машины. Обычно используется для того, чтобы заставить пользователей из локальной сети пользоваться местным proxy-сервером без дополнительного конфигурирования их клиентских программ.

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

А зачем оно нужно?

Зачем нужен firewall - и так понятно. Вы же не хотите, чтобы ваш компьютер, или вся сеть, подключенная к интернету, были доступны всем желающим. Доступ должен разрешаться только туда, куда вы решите. А одним из простых вариантов firewall'а как раз и является фильтр пакетов.

Маскарадинг - вещь менее очевидная. Если у вас один компьютер с dial-up подключением, то он вам и не нужен. А как быть, если у вас в организации локальная сеть, и все хотят в интернет, а провайдер дал вам один-единственный IP-адрес? Или того хуже, вы организовали сеть дома с соседями, а dial-up у вас один, да еще с динамическим адресом? Ну или просто ваша жена скучает, когда вы бродите по интернету, и вы купили ей отдельный компьютер, и даже соединили его со своим, а телефонная линия у вас все равно одна и dial-up account тоже?

Можно, конечно, поставить прокси-сервер. Но это требует времени и некоторых усилий по настройке самого сервера, и клиентских программ. Вдобавок, он обеспечивает работу только ограниченного набора протоколов. Маскарадинг позволяет избежать этих трудностей.

В некоторых организациях маскарадинг применяется даже если у машин есть реальные IP-адреса, чтобы скрыть внутреннюю структуру сети. Снаружи это выглядит так, как будто все запросы исходят от единственной машины-шлюза.

Замечу, что "локальная сеть" может состоять из двух или более компьютеров (или даже виртуальных компьютеров на одном физическом), и совершенно неважно, как именно они соединены между собой (Ethernet, последовательный, параллельный или инфракрасный порт, USB или еще как-нибудь). Не играет особой роли и протокол, по которому эти компьютеры общаются между собой, подойдет и SLIP, и PLIP, и PPP, и IP-туннель над другим протоколом.. Единственное, что действительно требуется - чтобы этот протокол поддерживал передачу IP-пакетов.

Как выбрать адреса для машин в локальной сети? Если ваш интернет-провайдер выделил вам пул адресов, то адреса надо брать из него. Если же вам выделяется только один адрес (в том числе, и динамический) то в локальной сети настоятельно рекомендуется выбирать адреса из специально выделенных диапазонов 192.168.0.*, 172.16.0.0 - 172.31.255.255 или 10.*.*.* (так называемые fake-адреса, не маршрутизирующиеся глобально). (См. RFC 1597). Сконфигурированный для маскарадинга шлюз может менять заголовки IP-пакетов, пришедших из вашей локальной сети и отправлять их получателю уже со своего реального IP-адреса. В полученных снаружи ответных пакетах он меняет адрес получателя обратно на fake-адрес и пересылает пакет по назначению.

Вы, конечно, можете назначить своим компьютерам и чужие реальные адреса, но это чревато некоторыми неприятностями. При использовании маскарадинга вы не сможете связаться с удаленными хостами, которым эти адреса принадлежат по праву (поскольку ваш шлюз будет думать, что они находятся в вашей локальной сети). При отсутствии маскарадинга у вас просто не установится ни одно соединение, поскольку никто, кроме вашего шлюза, не будет маршрутизировать пакеты для чужих адресов в вашу сеть.

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

Пример 1: локальная сеть и единственный реальный IP-адрес

У вас есть локальная сеть, единственный выход в интернет (например, dial-up по ppp, хотя это не существенно) и шлюзовой компьютер с реальным выделенным IP-адресом (например, 1.2.3.4). На интерфейсе локальной сети этот компьютер имеет адрес 192.168.1.1. В локальной сети находится компьютер myhost с адресом 192.168.1.100, с которого вы хотите пользоваться интернет-браузером. Как это реализовать?

Вариант 1 (прозрачное проксирование): на компьютере firewall устанавливается proxy-сервер, все пакеты из локальной сети, адресованные на внешние http-серверы заворачиваются в этот proxy-сервер, который посылает запросы вовне со своего реального адреса 1.2.3.4, а полученные ответы пересылает обратно в локальную сеть. При этом браузер на машине myhost конфигурируется как для прямого соединения с интернетом, потому такое проксирование и называется прозрачным. С точки зрения удаленного http-сервера соединение устанавливается с вашего шлюза. С точки зрения браузера соединение устанавливается с удаленным сервером.

Вариант 2 (маскарадинг): у всех пакетов из локальной сети, адресованных вовне, адрес отправителя меняется на 1.2.3.4, а у приходящих в ответ пакетов адрес получателя заменяется на 192.168.1.100 и они пересылаются на машину myhost. С точки зрения удаленного сервера соединение устанавливается с вашим шлюзом. С точки зрения браузера соединение устанавливается с удаленным сервером.

Пример 2: локальная сеть с реальными IP-адресами

У вас есть локальная сеть с постоянным подключением к интернету. Все машины в локальной сети имеют реальные IP-адреса из пула 1.2.3.x. Шлюзовой компьютер имеет IP-адрес 1.2.3.4. Внутри сети установлен компьютер с адресом 1.2.3.10, который вы хотите сделать доступным для всего интернета, но только в качестве http-сервера.

В такой конфигурации фильтр пакетов может использоваться для ограничения доступа, в частности, внутрь вашей сети из остального интернета.

Вариант 1 (редиректор): пересылка пакетов из интернета внутрь вашей сети и обратно запрещена. На шлюзе на определенном порту ожидает входящих соединений программа, называемая редиректором. При установке соединения извне она также устанавливает соединение с сервером внутри вашей сети и производит прозрачную пересылку данных в обе стороны. С точки зрения вашего сервера соединение устанавливается с вашего же шлюза. С точки зрения удаленного клиента в интернете соединение устанавливается со шлюзом. Преимущество в том, что никакие другие соединения с вашим сервером из интернета не могут быть установлены, что сильно повышает безопасность. Недостаток в том, что сервер не может определить, с каким клиентом он реально работает.

Вариант 2 (требуется ядро 2.1.x или выше, либо патченное на предмет ipportfw 2.0.x): идея примерно та же, что и при редиректе, но реализуется другим способом. Ядро меняет адрес получателя для определенных пакетов и пересылает их в локальную сеть. С точки зрения сервера соединение устанавливается с удаленным клиентом, с точки зрения клиента соединение устанавливается со шлюзом. Недостаток предыдущего варианта устраняется: сервер видит реального клиента.

Как его настроить

Ядро

Первым делом надо настроить ядро. Проверьте, есть ли у вас файл /proc/net/ip_fwchains. Если да, то ядро уже готово к работе с ipchains.

Если нет, то установите опции ядра

CONFIG_FIREWALL=y
CONFIG_IP_FIREWALL=y

Возможно, вам понадобятся и другие опции:

CONFIG_IP_FIREWALL_NETLINK=y
- позволяет направлять копии пакетов программам мониторинга для протоколирования, извещения администратора о попытках атак и т.п.
CONFIG_IP_ALWAYS_DEFRAG=y
- всегда дефрагментировать транзитные пакеты. Эта опция требуется для маскарадинга.
CONFIG_IP_TRANSPARENT_PROXY=y
- позволяет включить прозрачное проксирование
CONFIG_IP_MASQUERADE=y
- позволяет включить маскарадинг
CONFIG_IP_MASQUERADE_ICMP=y
- позволяет маскарадить ICMP-пакеты (т.е. у вас будут работать, например, ping и traceroute с машин с fake-адресами).

Затем перекомпилируйте ядро и запустите его. Если вы не знаете, как это делать, почитайте Kernel-HOWTO.

Если вы поменяли ядро с 2.0.x на 2.1.x или более новое и не хотите изучать ipchains, существует скрипт ipfwadm-wrapper, который позволяет использовать с ipchains параметры от ipfwadm. Он входит в набор ipchains-scripts: ftp://ftp.rustcorp.com/ipchains/ipchains-scripts-1.1.2.tar.gz или более свежий. Кроме того, в этот набор входят скрипты, позволяющие записать текущие настройки фильтра пакетов в файл, и наоборот, загрузить их из файла (ipchains-save и ipchains-restore).

Включение фильтрации пакетов

Чтобы фильтр пакетов начал работать, надо записать '1' в файл /proc/sys/net/ipv4/ip_forward:

echo 1 > /proc/sys/net/ipv4/ip_forward

Соответственно, если туда записать 0, то он работать перестанет. Эту строку рекомендуется вписать в какой-нибудь скрипт, автоматически запускаемый при загрузке системы.

Как работает фильтрация пакетов

Ядро запускается с тремя встроенными (built-in) цепочками (chains) правил (rules) фильтрации, которые называются входная (input), выходная (output) и пересылочная (forward). В дополнение к встроенным можно создавать новые цепочки правил.

Цепочки состоят из правил (rules). Каждое правило содержит условие и, возможно, действие (target), которое надо произвести с пакетом, если его заголовок соответствует условию. Если заголовок пакета не соответствует условию, то проверяется следующее правило в цепочке. Если заголовок пакета не удовлетворяет ни одному условию, используется политика (policy) самой цепочки. В защищенных системах эта политика обычно требует уничтожить или отвергнуть пакет.

При появлении пакета на внешнем интерфейсе проверяется его контрольная сумма. Если она неправильная, то пакет считается испорченным и убивается на месте. Если контрольная сумма правильная, то пакет проверяется на корректность некоторых полей в заголовке, которые могут вызвать нарушения в работе фильтров. Если пакет оказывается дефектным, то он уничтожается, а в системный журнал помещается запись о нем. Затем пакет проверяется по входной цепочке правил. Если на этом этапе пакет не уничтожен и не отвергнут, то проверяется, не является ли он ответом на ранее отправленный маскарадный пакет. Если это так, то производится демаскарадинг (demasquerading) и пакет отправляется на выходную цепочку. Если пакет не является ответом на маскарадный, то ядро определяет, куда он должен быть отправлен (это называется маршрутизацией (routing)). Если он должен отправиться на другую машину, то пакет проверяется по пересылочной цепочке. Если при этом он не уничтожается, то он проверяется по выходной цепочке. Если и при этом пакет не уничтожается, то он наконец благополучно пересылается на следующую машину.

Если в процессе маршрутизации обнаружено, что пакет адресован на эту машину, то после маршрутизации он передается соответствующему локальному процессу.

Пакеты, сгенерированные локальными процессами, проходят этап маршрутизации и выходную цепочку.

Пакеты, сгенерированные локальными процессами и адресованные на локальный интерфейс (loopback, lo), проверяются по выходной цепочке с интерфейсом lo, а затем по входной цепочке также с интерфейсом lo. (Интерфейс, через который проходит пакет, может влиять на обработку его фильтром пакетов).

Таким образом, встроенные цепочки используются в следующих случаях:

Побочные эффекты работы фильтра пакетов. Если пакет соответствует условию, то производятся следующие действия:

  1. Счетчик байт для данного правила увеличивается на размер пакета (включая заголовок).
  2. Счетчик пакетов для данного правила увеличивается на 1.
  3. Если правило того требует, то пакет записывается в журнал.
  4. Если правило того требует, то у пакета изменяется поле Тип Обслуживания (TOS, Type Of Service).
  5. Если правило того требует, то пакет маркируется (кроме ядер 2.0.x). Сие есть вещь сильно загадочная. Если она вас заинтересовала, читайте оригинальную документацию.
  6. Если в правиле указано действие (target), то оно производится.
  7. ipchains: команды, параметры, флаги

    Команды операций с правилами в цепочке:

    1. добавить новое правило к цепочке ('-A', add)
    2. вставить новое правило в определенную позицию цепочки ('-I', insert)
    3. заменить правило в определенной позиции цепочки ('-R', replace)
    4. удалить правило в определенной позиции цепочки ('-D', delete)
    5. удалить первое правило в цепочке, удовлетворяющее условию ('-D', delete)

    Условия проверки пакетов, которые можно задавать в правилах:

    1. адрес отправителя ('-s', source)
    2. адрес получателя ('-d', destination)
    3. инверсия условия ('!', not)
    4. протокол ('-p', protocol)
    5. номера портов для протоколов TCP и UDP
    6. тип (type) и код (code) для протокола ICMP
    7. интерфейс ('-i', interface)
    8. флаг - только TCP SYN-пакеты ('-y')
    9. флаг - только фрагменты пакетов ('-f', fragment)

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

    1. основное действие ('-j', jump to)
    2. регистрация пакета в журнале ('-l', log)
    3. изменение Типа Обслуживания ('-t', TOS)

    Команды операций с целыми цепочками:

    1. создать новую цепочку ('-N', new)
    2. удалить пустую цепочку ('-X')
    3. удалить все правила из цепочки ('-F', flush)
    4. распечатать правила цепочки ('-L', list)
    5. обнулить счетчики байт и пакетов для всех правил в цепочке ('-Z', zero)
    6. изменить политику для встроенной цепочки ('-P', policy)

    Команды маскарадинга:

    1. вывести текущие параметры маскарадинга ('-M -L', masquerade list)
    2. установить значения таймаутов для маскарадинга ('-M -S', masquerade set)

    Ручная проверка работы фильтра

    Изменение нескольких правил одной командой:

    А теперь подробно обо всех командах, параметрах и флагах:

    Команды операций с правилами в цепочках

    Добавление нового правила к цепочке производится командой '-A' (add), за которой следует имя цепочки и все другие необходимые параметры и флаги, например:

    ipchains -A input -s 127.0.0.1 -p icmp -j DENY

    будет уничтожать ICMP-пакеты с адреса 127.0.0.1 при проверке по входной цепочке. Правила, добавляемые командой -A, приписываются в конец цепочки.

    Новое правило можно вставить в определенную позицию цепочки командой '-I' (insert), после которой должен быть указано имя цепочки и номер, а также другие необходимые параметры. Остальные правила в цепочке (если они есть) будут сдвинуты на следующие позиции. Первое правило в цепочке имеет номер 1. Например:

    ipchains -I forward 1 -p tcp -d 0/0 www -j DENY
    запрещает пересылку tcp-пакетов на www-порт.

    Заменить правило в определенной позиции цепочки можно командой '-R' (replace), после которой должен быть указано имя цепочки и номер, а также другие необходимые параметры. Синтаксис полностью совпадает с командой '-I'.

    Удалить правило в определенной позиции цепочки можно командой '-D' (delete), например:

    ipchains -D forward 1

    Остальные правила в цепочке (если они есть) сдвигаются на 1 позицию.

    Если вы не знаете номера правила в цепочке и не хотите его определять, то можно применить команду удаления по условию. Для этого после команды -D и названия цепочки надо указать абсолютно тот же набор параметров, который использовался при создании правила командами '-A', '-I' или '-R', например:

    ipchains -D input -s 127.0.0.1 -p icmp -j DENY

    Однако, если в цепочке было несколько одинаковых правил, будет удалено только первое из них.

    Условия проверки пакетов, которые можно задавать в правилах:

    Адреса отправителя и получателя могут быть заданы, соответственно, после параметров '-s' и '-d', в следующих формах:

    ipchains -A input -s 0/0 -j DENY

    Однако, это используется крайне редко, потому что тот же эффект будет достигнут, если в правиле вовсе не указывать адрес. Практически единственный случай, когда применяется адрес 0/0 - это когда надо указать номер порта или тип и код ICMP-пакетов, поскольку их невозможно указать без адреса.

    Инверсия условия: многие условия (в частности, -s и -d) допускают инвертирование путем указания '!' перед параметром. Например, чтобы указать все пакеты, кроме пришедших с localhost, надо использовать параметр

    '-s ! localhost'

    Протокол ('-p') может указываться в виде названия (большими или маленькими буквами) - TCP, UDP, ICMP, или в виде номера (см. /etc/protocols). К протоколам также может применяться инверсия:

    '-p ! TCP'

    означает любой протокол, кроме TCP.

    Для протоколов TCP и UDP в параметрах '-s' и '-d' после адреса могут указываться номера портов. Порты могут указываться в виде символического имени, например, www (см. /etc/services), в виде десятичного номера (например, 80) и в виде диапазона (80:82 включает порты 80, 81, 82). Если в диапазоне пропущена нижняя граница, то подразумевается 0 (например, :19 означает все порты с 0 по 19 включительно), если верхняя, то подразумевается 65535. Если порт не указан вовсе, то подразумеваются все. К портам также может применяться инверсия:

    '-p TCP -d 0.0.0.0/0 ! www'

    означает все пакеты протокола TCP, кроме адресованных на 80 порт.

    Внимание! Условие

    '-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.

    А запись

    '-p TCP -d ! 192.168.1.1 ! www'

    означает любой TCP-пакет, кроме адресованных на любой порт машины 192.168.1.1 и кроме адресованных на www-порт любой машины.

    Для протокола ICMP могут указываться тип (type) и код (code) ICMP-пакетов. Тип может указываться после адреса в параметре '-s', а код - в параметре '-d'. Они могут указываться в виде чисел, а тип - и в виде символического имени. Чтобы получить список символических имен типов, наберите команду

    ipchains -h icmp

    Вот небольшая таблица наиболее распространенных типов ICMP-пакетов:

    Номер типа: Название:               Кем используется:
    0           echo-reply              ping
    3           destination-unreachable любой TCP/UDP-трафик
    5           redirect                маршрутизация в отсутствие демона маршрутизации
    8           echo-request            ping
    11          time-exceeded           traceroute

    В текущей версии ipchains имена типов не могут инвертироваться с помощью '!'.

    Внимание! Ни в коем случае не запрещайте передачу ICMP-пакетов типа 3! Это может сильно замедлить или вообще заблокировать передачу данных.

    Интерфейсом называется физическое или логическое устройство, через которое могут приниматься или передаваться пакеты. Чтобы узнать, какие интерфейсы присутствуют в вашей машине и активны (up), воспользуйтесь командой ifconfig. Параметр '-i' позволяет задать проверку интерфейса в правиле.

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

    Вполне допустимо при задании правил указывать неактивный (down) или вообще отсутствующий в данный момент интерфейс. Такое правило просто не будет соответствовать ни одному пакету, пока интерфейс не активизируется.

    Можно указать сразу некоторую группу интерфейсов, написав '+' после имени. Так, '-i ppp+' означает все интерфейсы, имена которых начинаются с 'ppp' (в том числе, и не существующие на момент задания правила).

    К интерфейсам также применима инверсия: '-i ! eth0' означает все интерфейсы, кроме eth0.

    Иногда бывает полезно разрешить создание TCP-соединений только в одну сторону (например, из локальной сети в остальной интернет, но не наоборот). Фильтрация пакетов только по адресам здесь не поможет, потому что TCP-соединение требует передачи пакетов в обе стороны. Решение состоит в том, чтобы уничтожать пакеты с запросом на установку соединения, идущие в нежелательную сторону.

    Пакеты с запросом на установку TCP-соединения отличаются тем, что у них установлен флаг SYN, а флаги FIN и ACK сброшены, и по традиции называются SYN-пакетами. Проверка этого условия включается флагом '-y'. Он допустим только в правилах с указанным протоколом TCP, например:

    -p TCP -s 192.168.1.1 -y

    означает пакеты на установку соединения, отправленные с машины 192.168.1.1. В документации написано, что флаг -y может инвертироваться с помощью '!' для указания всех пакетов, кроме SYN, но я не представляю себе, как это пишется. Сами проверяйте.

    Иногда случается так, что пакет превышает максимально возможный размер для передачи по некоторому каналу (MTU - maximum transfer unit). В этом случае он разбивается на несколько пакетов (фрагментов), которые посылаются по отдельности. Это называется фрагментацией (fragmentation). На принимающей стороне фрагменты собираются обратно (дефрагментация - defragmentation).

    Проблема состоит в том, что некоторые данные, необходимые для проверки условий фильтрации, содержатся только в первом фрагменте (в частности, порт отправителя, порт получателя, тип ICMP, код ICMP, TCP флаг SYN). Если ваша машина является единственным шлюзом, соединяющим локальную сеть с остальным интернетом, вы можете указать ей дефрагментировать все проходящие через нее пакеты (надо собрать ядро с параметром CONFIG_IP_ALWAYS_DEFRAG).

    Если ваша машине не дефрагментирует транзитные пакеты, то фильтрация будет работать так: если правило содержит проверки информации, которая отсутствует во фрагменте, то условие считается не выполненным, и правило не срабатывает. Таким образом, первый фрагмент обработается как любой нефрагментированный пакет, а все остальные фрагменты - нет. Например, условие

    '-p TCP -s 192.168.1.1 www'

    не сработает на втором и последующих фрагментах пакета. Но также не сработает и обратное условие:

    '-p TCP -s 192.168.1.1 ! www'

    поскольку во втором и последующих фрагментах вообще нет информации о номере порта.

    Вы можете указывать правила для второго и последующих фрагментов с помощью флага '-f'. Очевидно, его нельзя применять вместе с номерами портов TCP/UDP, типом и кодом ICMP, и TCP SYN флагом, поскольку эта информация во втором и последующих фрагментах отсутствует. Можно также указать, что правило не применяется ко второму и последующим фрагментам, указав '!' перед '-f'.

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

    Некорректно сформированные пакеты (TCP, UDP, ICMP до того короткие, что из них нельзя извлечь информацию о номерах портов или коде и типе ICMP) также считаются фрагментами и обрабатываются по правилам для фрагментов.

    Следующий пример уничтожает фрагменты, адресованные на 192.168.1.1:

    ipchains -A input -f -d 192.168.1.1 -j DENY

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

    Основное действие с пакетом, если он соответствует условию правила, задается с помощью параметра '-j' (jump to).

    Существует шесть специальных действий:

    1. ACCEPT: принять пакет
    2. DENY: уничтожить
    3. REJECT: отвергнуть, т.е. уничтожить и послать квитанцию отправителю в виде ICMP-пакета, если, конечно, отвергаемый пакет сам не был ICMP.
    4. MASQ: замаскарадить пакет - допустимо только в пересылочной цепочке и только если ядро было скомпилировано с поддержкой маскарадинга
    5. REDIRECT: переадресовать пакет на определенный порт локальной машины, независимо от того, куда он был отправлен (прозрачное проксирование). Допустимо только во входной цепочке. Номер порта указывается после ключевого слова REDIRECT.
    6. RETURN: вызывает прекращение дальнейших проверок в цепочке и применение к пакету политики цепочки.

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

    Если действие правила не указано, то даже при соответствии пакета его условиям продолжается проверка следующих правил в цепочке. Такие правила называются учетными (accounting) и используются для учета трафика. Например, чтобы считать трафик от 192.168.1.1, можно использовать правило:

    ipchains -A input -s 192.168.1.1

    и проверять трафик командой

    ipchains -L -v

    Флагом '-l' (log) можно указать, что пакет следует записать в системный журнал. Обычно это применяется для регистрации возможных атак или при отладке сетевых настроек. Не злоупотребляйте регистрацией в системном журнале, а то он начнет быстро распухать..

    Изменение Типа Обслуживания (TOS, Type Of Service) задается параметром '-t'. В заголовке IP-пакета есть 4 специальных редко используемых битовых флага, которые могут влиять (а могут и не..) на обслуживание пакета некоторыми маршрутизаторами:

    Может быть установлен только один из этих флагов. Наиболее часто они применяются так: для telnet'а и управляющего соединения ftp устанавливается флаг Minimum Delay, а для данных ftp - Maximum Throughput. Это делается следующими командами:

    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' имеет 2 шестнадцатиричных параметра, которые применяются так:
    новыйTOS = (старыйTOS AND первый параметр) XOR второй параметр
    Для простоты приводится таблица со значениями параметров:

    Название Типа Обслуживания:  Значения параметров: Типичное применение
    Minimum Delay                0x01 0x10            ftp, telnet
    Maximum Throughput           0x01 0x08            ftp-data
    Maximum Reliability          0x01 0x04            snmp
    Minimum Cost                 0x01 0x02            nntp

    Команды операций с целыми цепочками

    Вы можете создавать свои цепочки правил. Называть цепочки можно любыми именами, кроме имен встроенных цепочек и стандартных действий (т.е. input, output, forward, ACCEPT, DENY, REJECT, MASQ, REDIRECT, RETURN). Не рекомендуется использовать в именах большие буквы, поскольку они могут быть задействованы в следующих версиях ipchains. Имя цепочки может содержать до 8 символов.

    Создание новой цепочки производится командой '-N' (new), например:

    ipchains -N test

    Удаление цепочки производится командой '-X', например:

    ipchains -X test

    Почему '-X'? А потому, что все хорошие буквы уже задействованы. Существует ограничение: цепочку можно удалить только если она пустая (т.е. в ней нет ни одного правила), и если на нее не ссылаются никакие правила из других цепочек.

    Очистка (flushing) цепочки (т.е. удаление из нее всех правил) производится командой '-F' (flush), например:

    ipchains -F forward

    Если имя цепочки не указано, то будут очищены все цепочки.

    Просмотр одной цепочки или всех сразу производится командой '-L' (list), например:

    ipchains -L input

    Если имя цепочки не указано, то будут показаны все цепочки. В выводимой информации значение refcnt означает, сколько правил ссылаются на данную цепочку в своих действиях. Чтобы цепочку можно было удалить, ее refcnt должен быть равен 0. Вместе с командой '-L' можно указывать следующие флаги:

    Сброс (обнуление) счетчиков производится командой '-Z' (zero), например:

    ipchains -Z input

    Если имя цепочки не указано, то обнуляются счетчики всех цепочек. Иногда требуется узнать состояние счетчиков непосредственно перед обнулением. Применение последовательно команд 'ipchains -L -v' и 'ipchains -Z' не подходит, поскольку в промежутке между их выполнением счетчики могут изменить свое значение. В таком случае можно указать обе команды в одном вызове:

    ipchains -L -v -Z

    но при этом нельзя задать конкретную цепочку - статистика будет выведена и затем сброшена для всех цепочек сразу.

    Задание политики для цепочки производится командой '-P' (policy). Если пакет не удовлетворяет ни одному условию в цепочке, то к нему применяется политика цепочки. Политика может задаваться только для встроенных цепочек (input, output, forward). Политика может быть: ACCEPT, DENY, REJECT а для пересылочной цепочки еще и MASQ. Задание политики MASQ для пересылочной цепочки не рекомендуется по соображениям безопасности: злоумышленник может настроить маршрутизацию своих пакетов на ваш шлюз, и его пакеты, не соответствующие явно никаким правилам в пересылочной цепочке, будут по умолчанию маскарадиться. В результате он сможет работать в интернете с IP-адреса вашего шлюза, скрывая свой реальный адрес.

    Хинт: использование действия RETURN в правилах цепочки позволяет применить к подходящему пакету текущую политику цепочки вместо конкретного действия.

    Операции с маскарадингом:

    Для работы с маскарадингом используется команда '-M' (masquerade), которая может сочетаться с '-L' (list) для просмотра текущих установок маскарадинга, и с '-S' (set) для установки параметров.

    '-L' может использоваться со своими флагами '-n', '-v', '-x'.

    После '-S' должны следовать три параметра, задающие таймауты в секундах, соответственно, для TCP-сеансов, для TCP-сеансов после FIN-пакета, и для UDP-пакетов. Если вы не хотите менять значение какого-то параметра, укажите для него значение 0. Наиболее часто приходится менять первый из этих параметров для нормальной работы FTP.

    Ручная проверка работы фильтра пакетов

    Если вы хотите проверить, как будет работать фильтр на некотором пакете, используйте команду '-C' (check). Параметры этого фиктивного пакета задаются точно так же, как и в правилах: '-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, (типичный запрос на установку www-соединения):

    ipchains -C input -p tcp -y -i eth0 -s 192.168.1.1 60000 -d 192.168.1.2 www

    В ответ на эту команду ipchains сообщит судьбу пакета, например 'Packet accepted'.

    Изменение нескольких правил одной командой

    Иногда одна команда может воздействовать сразу на несколько правил. Это может происходить по двум причинам.

    Во-первых, если вы указываете символический адрес машины, а его разрешение через DNS дает несколько различных IP-адресов, то ipchains будет действовать так, как если бы вы ввели несколько команд со всеми возможными сочетаниями IP-адресов. Например, если www.foo.com разрешается в 3 адреса, а www.bar.com - в 2 адреса, и вы ввели команду

    ipchains -A input -j reject -S www.bar.com -d www.foo.com

    то ко входной цепочке добавится 6 правил.

    Во-вторых, ipchains может выполнить несколько действий, если вы указали флаг '-b' (bidirectional). При этом ipchains будет действовать так, как если бы вы ввели команду дважды, во втором случае поменяв местами параметры '-s' и '-d'. Например, чтобы запретить пересылку пакетов от и к 192.168.1.1, можно воспользоваться командой:

    ipchains -b -A forward -j REJECT -s 192.168.1.1

    Флаг '-b' может применяться в командах '-A', '-C', '-I', '-D' (кроме удаления по номеру правила).

    Еще один полезный флаг - '-v' (verbose), который позволяет точно узнать, что сделала ваша команда. Он особенно полезен, если ваша команда может воздействовать сразу на несколько правил. Например, можно проверить, как работает пересылка фрагментов сразу в обе стороны между 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

    Пример настройки маскарадинга

    ipchains -P forward DENY
    ipchains -A forward -s 192.168.1.0/24 -j MASQ
    echo 1 > /proc/sys/net/ipv4/ip_forward

    Сначала отключается вся пересылка пакетов, потом включается маскарадинг в предположении, что в локальной сети используются адреса из пула 192.168.1.x.

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

    ipchains -P forward DENY
    ipchains -A forward -s 192.168.1.2 -j MASQ
    ipchains -A forward -s 192.168.1.8 -j MASQ
    echo 1 > /proc/sys/net/ipv4/ip_forward

    Остальные машины, кроме 192.168.1.2 и 192.168.1.8 доступа в интернет не получат.

    Пример настройки фильтра пакетов

    Предположим, что у вас есть PPP-соединение ('-i ppp0'). Вы читаете конференции (-p TCP -s news.virtual.net nntp) и почту (-p TCP -s mail.virtual.net pop-3). Иногда скачиваете по ftp свежее ядро для своего линукса (-p TCP -y -s ftp.kernel.org ftp-data). Бродите по www через прокси-сервер своего провайдера (-p TCP -d proxy.virtual.net 8080), но не любите рекламу с www1.reklama.ru и rb2.design.ru (-p TCP -y -d 195.46.160.46, -p TCP -y -d 212.24.32.76). Вы не возражаете против пользования ftp-сервером на вашей машине (-p TCP -d $LOCALIP ftp), но не хотите, чтобы кто-то снаружи делал вид, что он из вашей локальной сети (-s 192.168.1.0/24) - это называется IP-спуфинг (spoofing), и в ядрах 2.1.x и выше есть более правильные средства для защиты от него.

    Итак:

    Вы не хотите, чтобы ваши локальные процессы (в т.ч. Netscape) соединялись с www1.reklama.ru и rb2.design.ru:

    ipchains -A output -d 195.46.160.46 -j REJECT
    ipchains -A output -d 212.24.32.76 -j REJECT

    Вы устанавливаете приоритеты для исходящих пакетов (для входящих этого делать нет смысла). Поскольку этих правил довольно много, можно выделить их в отдельную цепочку по имени ppp-out:

    ipchains -N ppp-out
    ipchains -A output -i ppp0 -j ppp-out

    Минимальная задержка для www-трафика и telnet'а:

    ipchains -A ppp-out -p TCP -d proxy.virtual.net 8080 -t 0x01 0x10
    ipchains -A ppp-out -p TCP -d 0.0.0.0/0 telnet -t 0x01 0x10

    Низкая стоимость для данных ftp, nntp, pop3:

    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.*, т.е. из локальной сети. Если же таковые появятся, то их надо занести в журнал ('-l') и уничтожить:

    ipchains -A ppp-in -s 192.168.1.0/24 -l -j DENY

    Разрешим UDP-пакеты для DNS (поскольку у вас работает кэширующий DNS-сервер, который пересылает все запросы на 203.29.16.1, то и ответов вы ожидаете только оттуда), а также входящие 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

    Политика по умолчанию для входной цепочки - DENY, то есть все остальное уничтожается:

    ipchains -P input DENY

    Примечание: правила не обязательно добавлять именно в таком порядке, поскольку пока вы их добавляете, некоторые нежелательные пакеты могут проскочить через фильтр. С точки зрения безопасности наиболее правильно сначала установить политику DENY для входной цепочки, а потом добавлять новые правила. Однако, если добавляемые правила потребуют разрешения символических имен с помощью DNS, у вас могут возникнуть неприятности. Я вас предупредил ;-).

    Полезные советы

    Меры безопасности во время изменения правил фильтрации

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

    # сначала вставляем во все цепочки правила, уничтожающие все пакеты
    ipchains -I input 1 -j DENY
    ipchains -I output 1 -j DENY
    ipchains -I forward 1 -j DENY
    ... делаем все необходимые изменения ...
    # убираем безусловное уничтожение пакетов
    ipchains -D input 1
    ipchains -D output 1
    ipchains -D forward 1

    Динамическое изменение правил фильтрации

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

    '-i ppp0 -j DENY'

    а после поднятия интерфейса, например, в скрипте ip-up, выполнить что-нибудь типа:

    # восстановить цепочку ppp-in
    ipchains-restore -f < ppp-in.firewall
    # заменить первое правило входной цепочки
    ipchains -R input 1 -I ppp0 -j ppp-in

    Соответственно, скрипт ip-down может выглядеть так:

    ipchains -R input 1 -i ppp0 -j DENY

    Сохранение и восстановление правил фильтрации

    С помощью скрипта ipchains-save, входящего в комплект ipchains-scripts ( ftp://ftp.rustcorp.com/ipchains/ipchains-scripts-1.1.2.tar.gz) можно записать текущие правила одной или всех цепочек в файл. Это делается так:

    ipchains-save > my-firewall

    В качестве параметра можно указать имя одной цепочки. Если имя не указано, то записываются правила всех цепочек. Кроме того, можно указать флаг '-v', который позволит посмотреть правила по мере их записи.

    Для восстановления правил из фала применяется скрипт ipchains-restore:

    ipchains-restore < my-firewall

    Во время работы ipchains-restore может запрашивать подтверждения на некоторые действия, например, если создаваемая цепочка уже существует, то можно очистить ее либо ничего не делать, тогда правила будут добавляться к уже существующим в цепочке правилам.

    Какие пакеты не надо уничтожать

    Прежде чем уничтожать все ненужные вам пакеты, учтите следующее:

    Защита от атак по IP

    Некоторые типы пакетов могут при определенных условиях вызывать нарушения в работе TCP/IP-стека протоколов, вплоть до полного зависания компьютеров. Ниже приводятся некоторые рекомендации по настройке фильтрации, если за вашим firewall'ом есть компьютеры, чувствительные к таким атакам. Свежие ядра Линукса нечувствительны к этим атакам, но другие системы могут нуждаться в защите.

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

    Защита от спуфинга

    IP-спуфингом (spoofing) называется посылка пакетов с обратным адресом другой машины. Поскольку фильтрация пакетов во многом основывается на адресе отправителя, спуфинг может использоваться, чтобы обмануть фильтр пакетов. Кроме того, он используется для маскировки атакующего при атаках типа SYN, Teardrop, Ping of Death, и других. Если вы не знаете, что это такое, это не важно ;-)

    Лучший способ защититься от IP-спуфинга называется Проверка Адреса Отправителя (Source Address Verification), и выполняется программами маршрутизации, а не фильтрации пакетов. Проверьте, существует ли у вас на машине файл /proc/sys/net/ipv4/conf/all/rp_filter. Если да, то верным решением будет включение Проверки Адреса Отправителя во время начальной загрузки машины. Для этого следует вставить следующие команды в один из ваших скриптов инициализации, до инициализации сетевых интерфейсов:

    # Включаем Проверку Адреса Отправителя и получаем
    # защиту от спуфинга на всех существующих и будущих интерфейсах
    if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ]; then
      echo -n "Setting up IP spoofing protection..."
      for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
          echo 1 > $f
      done
      echo "done."
    else
      echo PROBLEMS SETTING UP IP SPOOFING PROTECTION.  BE WORRIED.
      echo "CONTROL-D will exit from this shell and continue system startup."
      echo
      # Start a single user shell on the console
      /sbin/sulogin $CONSOLE
    fi

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

    К примеру, у вас на машине 3 интерфейса - eth0, eth1, ppp0. Вы можете использовать ifconfig, чтобы узнать какие адреса и маски сети используются на каждом из интерфейсов. Предположим, eth0 соединен с сетью 192.168.1.0/255.255.255.0, eth1 - с сетью 10.0.0.0/255.0.0.0, а ppp0 - с остальным интернетом (поэтому на этом интерфейсе возможны любые адреса, кроме локальных сетей). Тогда надо добавить следующие правила:

    ipchains -A input -i eth0 -s ! 192.168.1.0/24 -j DENY
    ipchains -A input -i ! eth0 -s 192.168.1.0/24 -j DENY
    ipchains -A input -i eth1 -s ! 10.0.0.0/8 -j DENY
    ipchains -A input -i ! eth1 -s 10.0.0.0/8 -j DENY

    Такое решение хуже, чем Проверка Адреса Отправителя, поскольку при изменении сетевой конфигурации вам придется переделывать правила фильтрации. Ядра 2.1.x и выше автоматически отвергают пакеты с адресом отправителя 127.*.*.*, если они приходят не с локального интерфейса. Если у вас ядро 2.0.x, вы можете таким же образом защитить интерфейс lo:

    ipchains -A input -I !lo -s 127.0.0.0/8 -j DENY

    Где взять

    На официальной странице ipchains: http://www.rustcorp.com/linux/ipchains.

    Скрипты для ipchains: ftp://ftp.rustcorp.com/ipchains/ipchains-scripts-1.1.2.tar.gz

    Ссылки

    © Александр Дилевский 06-15.06.1999.