ebtables/iptables interaction on a Linux-based bridge

Содержание

  1. Введение
  2. Как фреймы проходят цепочки ebtables.
  3. Машина используется как коммутатор и как маршрутизатор (не brouter).
  4. DNAT-трансляция коммутируемых пакетов.
  5. Цепь прохождения для коммутируемых IP-пакетов.
  6. Цепь прохождения для коммутируемых IP-пакетов.
  7. Два возможных пути прохождения фреймами/пакетами цепочек iptables PREROUTING, FORWARD и POSTROUTING.
  8. IP DNAT в цепочке iptables PREROUTING на фреймах/пакетах, входящих в порты коммутатора.
  9. Использование модуля MAC для iptables.
  10. Использование модуля iptables для ядра 2.6
  11. Детальное прохождение IP-пакетов.

0. Перевод

Некоторые термины вызвали сомнения в адекватности перевода, поэтому ниже предоставлен список таковых.

Оригинал текста.
Обсуждение.

1. Введение.

Этот документ описывает взаимодействие таблиц фильтрации iptables и ebtables внутри сетевого коммутатора Linux.
Для получения файрвола коммутатора в ядре 2.4.x, необходимо наложить патч на исходники ядра. Ядро 2.6 содержит код ebtables и br-nf, поэтому его не нужно патчить. Т.к. потребность в патчах для 2.4 была велика, они остаются доступны на домашней странице ebtables Код br-nf позволяет пропускать через цепочки iptables IP-пакеты, проходящие через коммутатор. Ebtables фильтрует на уровне Ethernet, тогда как iptables фильтрует только IP-пакеты.
В разъяснениях ниже использована сетевая модель TCP/IP. Необходимо заметить, что код br-nf иногда нарушает модель TCP/IP. Как будет видно позже, это позволяет, например, выполнять IP DNAT на канальном уровне.
Мы хотим заметить, что мы прекрасно знаем, что термин фрейм используется для канального уровня, тогда как пакет - для сетевого. Однако, когда мы говорим о пакетах IP на канальном уровне, мы будем ссылаться на них как на фреймы/пакеты или пакеты/фреймы.

2. Как фреймы проходят цепочки ebtables.

Данная секция рассматривает только ebtables, не iptables.

Первое, что нужно держать в голове - это то, что здесь мы говорим о уровне Ethernet, т.е. втором уровне OSI (Data link layer), или первом уровне (Link layer, Network Access layer) модели TCP/IP.

Пакет, предназначеный локальному компьютеру с точки зрения коммутатора (который работает на уровне Ethernet), необязательно предназначен ему же с точки зрения IP-уровня. Это то, как работает маршрутизация (MAC-цель (destination) - роутер, IP-цель - тот хост, с которым вы хотите взаимодействовать).

Рис. 2a. Общая схема прохождения фрейма.

В коде коммутатора Linux существуют 6 точек перехвата, из которых точка BROUTING была добавлена для ebtables.



Рис. 2b. Точки перехвата Ethernet-коммутатора.

Точки перехвата - специальные места в сетевом коде, в которых ПО может присоединиться к процессу прохождения пакетов/фреймов через эти места. Например, модуль ядра, отвечающий за цепочку FORWARD ebtables, присоединяется к точке перехвата коммутатора FORWARD. Это делается когда модуль загружается в ядро или при загрузке.

Заметьте, что цепочки ebtables BROUTING и PREROUTING проходятся перед решением о коммутации, поэтому эти цепочки увидят даже те фреймы, которые будут проигнорированы коммутатором. Учитывайте это, когда используете эти цепочки. Также следует иметь в виду, что эти цепочки не увидят фреймы, входящие на заблокированный порт коммутатора (прим. пер. - видимо, речь идет о STP).
Решение о коммутации фрейма (как видно на Рис. 2b) может быть одним из следующих:

Рис. 2c. Процесс прохождения таблиц коммутатора (ebtables).

Ebtables имеет 3 таблицы: filter, nat и broute, как видно на Рис. 2c.


Цепочки OUTPUT таблиц filter и nat разделены и используются по разному.

Рис. 2b и 2c дают ясное понимание того, где цепочки ebtables подключаются к точкам перехвата коммутатора.

Когда сетевая карта, подчиненная коммутатору, получает фрейм, он, первым делом, будет отправлен через цепочку BROUTING. В этой специальной цепочке вы можете выбрать между маршрутизацией и коммутацией фреймов, т.о. можно сделать brouter. Определения, найденные в Интернете, несколько различаются, следующее определение достаточно хорошо описывает функциональность brouting, используя цепочку BROUTING:

Brouter - устройство, коммутирующее некоторые фреймы/пакеты (т.е. пересылка на основе информации канального уровня) и маршрутизирующее остальные фреймы/пакеты (т.е. пересылка на основе информации сетевого уровня). Решение коммутации/маршрутизации основывается на конфигурационной информации.

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

Далее фрейм пересылается через цепочку PREROUTING, в которой вы можете изменить MAC-адрес назначения (DNAT). Если фрейм проходит эту цепочку, код коммутации будет решать, куда должен быть отправлен фрейм. Коммутатор делает это, смотря на MAC-адрес назначения,он не заботится о адресе сетевого уровня (IP-адресе).

Если решено, что фрейм предназначен локальному компьютеру, он будет отправлен через цепочку INPUT. В этой цепочке вы можете фильтровать фреймы, предназначенные компьютеру-коммутатору. После прохождения цепочки INPUT, фрейм будет передан коду сетевого уровня (т.е. IP-коду). Т.о. маршрутизируемый (через данный компьютер. Прим. пер.) IP-пакет пройдет через цепочку INPUT ebtables, а не через FORWARD, что логично.



Рис. 2d. Цепь прохождения входящего пакета.

Иначе будет, если фрейм, возможно, должен быть послан на другую сторону коммутатора. В таком случае, фрейм пройдет через цепочки FORWARD и POSTROUTING. Фреймы могут быть отфильтрованы в цепочке FORWARD. В цепочке POSTROUTING вы можете поменять MAC-адрес источника (SNAT).



Рис. 2e. Цепь прохождения пересылаемого пакета.

Локально порожденные фреймы после решения о коммутации пройдут через nat OUTPUT, filter OUTPUT и nat POSTROUTING. Цепочка nat OUTPUT позволяет изменить MAC-адрес назначения, цепочка filter OUTPUT позволяет фильтровать локально порожденные пакеты. Учтите, что цепочка nat OUTPUT проходится после решения о коммутации, т.е. чересчур поздно. Мы должны изменить это. Цепочка nat POSTROUTING такая же, как описано выше.



Рис. 2f. Цепь прохождения исходящих фреймов.

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


3. Машина используется как коммутатор и как маршрутизатор (не brouter).

Схема точек перехвата IP-кода:

Рис. 3a. Точки перехвата IP-кода.

Схема прохождения пакетом iptables.



Рис. 3b. Процесс прохождения таблиц маршрутизации (iptables)

Имейте в виду, что цепочка iptables nat OUTPUT расположенв после решения о маршрутизации. Как отмечено в предыдущей секции (в обсуждении ebtables nat), это слишком поздно для выполнения трансляции DNAT. Эта проблема решается перемаршрутизацией IP-пакета, если он подвергся трансляции DNAT, перед продолжением. Для ясности: это стандартное поведение ядра Linux, а не что-то вызванное нашим кодом.

Рис. 3a и 3b дает ясное представление где цепочки iptables подключены к точкам перехвата IP. Когда bridge-код и netfilter включены в ядре, цепочки iptables также подключены к точкам перехвата в коде коммутации. Однако, это не означает, что они больше не подключены к их стандартным точкам перехвата IP-кода. Для IP-пакетов, что входят в контакт с кодом коммутации, код br-nf решит, в каком месте сетевого кода будут пройдены цепочки iptables. Очевидно, это гарантирует, что некоторый пакет не пройдет ни одну цепочка дважды. Все пакеты, не входящие в контакт с кодом коммутации, проходят цепочки iptables по стандартному пути, как показано на рис. 3b.
Следующие секции пытаются, среди других вещей, объяснить что и зачем делает код br-nf.

Возможно увидеть ситуацию, когда один IP-пакет/фрейм проходит цепочки ebtables nat PREROUTING, filter INPUT, nat OUTPUT, filter OUTPUT и nat POSTROUTING.
Это случается, когда коммутатор используется и как маршрутизатор. Ethernet фрейм содержащий этот IP-пакет будут иметь MAC-адрес назначения, который назначен коммутатору, тогда как IP-адрес назначения не назначен коммутатору. Включая цепочки iptables, вот как IP-пакет бежит через коммутатор/маршрутизатор (фактически, там происходит больше, см. section 6):

Рис. 3c. Маршрутизирование пакета на интерфейс коммутатора (упрощенный вид).

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

Рис. 3d. Маршрутизирование пакета на интерфейс вне коммутатора (упрощенный вид).

Рис. 3c и 3d предполагают, что IP-пакет прибывает на порт коммутатора. Что очевидно "асимметрично" здесь - это то, что цепочка iptables PREROUTING проходится перед цепочкой ebtables INPUT, однако это не может быть устранено без ухудшения функциональности. См. следующую секцию.

4. DNAT-трансляция коммутируемых пакетов.

Возьмем IP-пакет, полученный коммутатором. Предположим, что мы хотим сделать некоторую DNAT-трансляцию. Изменение адреса назначения пакета (IP- или MAC-адрес) происходит перед принятием решения о том, что делать с фреймом/пакетом.

Т.о. в коде коммутатор DNAT-трансляция IP происходит очень рано, а именно, перед тем, как код коммутатора сделает что-либо. Это происходит в том же месте, где будет проходится цепочка nat PREROUTING ebtables (по тем же причинам). Это должно объяснить "асимметричность", впервые встреченную на рис. 3c и 3d.
Имейте в виду тот факт, что фрейм, для которого решением о коммутации будет игнорирование (см. список решений в секции 2. Прим. пер.), будет виден в цепочке PREROUTING ebtables и iptables.

5. Цепь прохождения для коммутируемых IP-пакетов.

Коммутируемый пакет никогда не входит в сетевой код выше первого уровня (Link layer). Т.о. коммутируемый IP-пакет/фрейм никогда не входит в IP-код. Поэтому все цепочки iptables будут пройдены в то время, когда IP-пкет находится в коде коммутатора. Цепь прохождения будет выглядеть похожей на это:

Рис. 5. Цепь прохождения для коммутируемых IP-пакетов.

6. Использование портов коммутатора в правилах iptables.

Вполне законно желание использовать физические устройства, принадлежащие коммутатору, в цепочках iptables. Осознание происходящего во входных портах коммутатора необходимо для предотвращения spoofing-атак. Предположим, br0 имеет порты eth0 и eth1. Если правила iptables используют только br0, то нет способа определить, когда хост со стороны eth0 изменит свой IP-адрес на адрес хоста на стороне eth1, кроме осмотра MAC-адреса источника. С модулем physdev iptables можно использовать eth0 и eth1 в правилах iptables и, соответственно, отлавливать такие попытки.

6.1. iptables желает использовать порты назначения коммутатора:

Для реализации этого, цепочки iptables проходятся после принятия решения о том, куда отправлять фрейм (eth0, eth1 или в оба). Тут имеются некоторые разногласия со схемой из секции 3 (здесь мы смотрим на маршрутизируемый трафик, входящий на хост с портов коммутатора), которая похожа на эту (в случае рис. 3c):

Рис. 6a. Цепь прохождения маршрутизируемого трафика, когда код bridge и netfilter вкомпилированы в ядро.

Все цепочки сейчас проходятся во время пребывания в коде коммутатора - это следствие работы кода br-nf. Понятно, это не означает, что маршрутизируемые IP-пакеты никогда не попадут в IP-код. Они просто не проходят никаких цепочек iptables пока они в IP-коде.

6.2. IP DNAT для локально сгенерированных пакетов (т.е. в цепочке nat OUTPUT iptables):

Обычный путь локально сгенерированных пакетов через цепочки примерно такой:

Рис. 6c. Обычный путь локально сгенерированных пакетов.

Из секции 6.1 мы знаем, что в действительности путь похож на следующий (вследствие кода br-nf):

Рис. 6d. Действительный путь локально сгенерированных пакетов.

Заметьте, что цепочка nat OUTPUT iptables проходится в IP-коде, цепочка filter OUTPUT iptables - после принятия решения о коммутации. Это делает возможным выполнять DNAT на другое устройство в цепочке nat OUTPUT и позволяет нам ссылаться на порты коммутатора в цепочке filter OUTPUT.

7. Два возможных пути прохождения фреймами/пакетами цепочек iptables PREROUTING, FORWARD и POSTROUTING.

Из-за кода br-nf существуют два пути прохождения фреймами/пакетами данных цепочек. Первый путь - коммутация фрейма, цепочки iptables вызываются кодом коммутатора. Второй путь - маршрутизация пакета. Т.о. требуются специальные меры для различения этих двух ситуаций, особенно в цепочке iptables FORWARD. Вот пример странных вещей.

Представим следующую ситацию:

Рис. 7a. Очень простая схема.

Шлюз для 172.16.1.2 и 172.16.1.4 - 172.16.1.1, это адрес интерфейса br0 коммутатора с портами eth1 и eth2.

Еще детали:

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

Рис. 7b. Потоки трафика в примере.

Ниже представлена возможная конфигурация для использования при загрузке коммутатора/маршрутизатора:

iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -d 172.16.1.0/24 -j ACCEPT
iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -j MASQUERADE

brctl addbr br0
brctl stp br0 off
brctl addif br0 eth1
brctl addif br0 eth2

ifconfig eth1 0 0.0.0.0
ifconfig eth2 0 0.0.0.0
ifconfig br0 172.16.1.1 netmask 255.255.255.0 up

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

Уловка - в первой строке. Т.к. код iptables исполняется и для коммутируемых, и для маршрутизируемых пакетов, мы должны различать те и другие. Мы не хотим, чтобы коммутируемые фреймы/пакеты были подвергнуты маскарадингу. Если убрать первую строку, все продолжит работать, но некоторые вещи будут вести себя по-другому. Представим, что 172.16.1.2 пингует 172.16.1.4. Коммутатор получает пинг-запрос и пересылает через порт eth1 после первого маскарадинга IP-адреса. Т.о. IP-адрес источника будет 172.16.1.1, а 172.16.1.4 станет отвечать коммутатору. Маскарадинг изменит IP-адрес назначения пинг-ответа с 172.16.1.1 на 172.16.1.4. Все работает прекрасно. Но лучше избегать такого поведения, что позволяет сделать первая строка. Заметим, что если мы захотим фильтровать соединения в и из Интернета, мы определенно должны оставить первую строку для того, чтобы не фильтровать локальные соединения.

8. IP DNAT в цепочке iptables PREROUTING на фреймах/пакетах, входящих в порты коммутатора.

В течение несколько рутинной игры убеждаешься, что (см. /net/bridge/br_netfilter.c) DNAT-транслированные пакеты, которые после трансляции уйдут через тоже самое устройство, через которое они пришли (логическое устройство коммутатора, которое мы зовем br0), пойдут через цепочку ebtables FORWARD chain, а не через ebtables INPUT/OUTPUT. Все остальные DNAT-транислированные пакеты будут верно маршрутизированы, т.е. не будут проходить через цепочку ebtables FORWARD, но пойдут через ebtables INPUT и могут пройти через ebtables OUTPUT.

9. Использование модуля MAC для iptables

Побочный эффект, описываемый здесь, случается когда код netfilter разрешен в ядре, IP-пакет маршрутизируется и выходное устройство для пакета - логическое устройство коммутатора. Побочный эффект возникает при фильтрации по MAC-адресу источника в цепочке iptables FORWARD. Как должно быть ясно из предыдущих секций, прохождение цепочки iptables FORWARD откладывается пока пакет в коде коммутатора. Так сделано для того, чтобы мы могли фильтровать на выходном порту коммутатора. Это имеет побочный эффект, касающийся MAC-адреса источника, потому что IP-код поменяет его на MAC-адрес коммутатора (уже после маршрутизации? Прим. пер.). Поэтому невозможно в цепочке iptables FORWARD фильтровать по MAC-адресу компьютера, посылающего рассматриваемый пакет коммутатор/маршрутизатору. Если вам действительно нужна такая фильтрация, вы должны делать ее в цепочке nat PREROUTING. Да, очень безобразно, но реализация фильтрования по реальному MAC-адресу источника в цепочке FORWARD вынудит использовать очень грязный хак и, возможно, не стоит того. Это, конечно, делает замечание о антиспуфинге в секции 6 смешным.

10. Использование модуля iptables для ядра 2.6

Стандартное ядро 2.6 содержит модуль iptables, называемый physdev. Этот модуль может использоваться для привязки к физическим портам коммутатора. Использовать модуль просто (подробности в руководстве по iptables):

iptables -m physdev --physdev-in <bridge-port>

и

iptables -m physdev --physdev-out <bridge-port>

11. Детальное прохождение IP-пакетов.

Joshua Snyder (<josh_at_imagestream.com>) подготовил детальную картину о том, как пакеты IP проходят через файрвол коммутатора Linux.


Выпущено под GNU Free Documentation License.
Copyright (c) 2002-2003 Bart De Schuymer <bdschuym@pandora.be>,
                        Nick Fedchik <nick@fedchik.org.ua>.



Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation, with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. For a copy of the license, see "GNU Free Documentation License".

Последнее обновление: 9 ноября 2003г. Перевод: 25 ноября 2007г.