Фильтрация пакетов в bridge (iptables,ebtables)

Вопрос в первую очередь адресован системным администраторам Linux.
Имеется некая плата маршрутизатора на базе процессора PowerPC, которая работает, под управлением операционной системы OpenWRT (Linux). На этой плате установлено всего два сетевых интерфейса eth0 и eth1, объединённых в сетевой мост.

root@OpenWrt:/# brctl show
bridge name     bridge id               STP enabled     interfaces
br-br0          8000.7e0410820000       no              eth0
                                                        eth1


Стоит задача сделать фильтрацию пакетов по IP-адрессу (именно только по IP-адрессу!). Чтобы только некоторые компьютеры одной сети видели компьютеры другой. Задача с одной стороны тривиальная (использовать iptables), но на поверку оказалась нетривиальной…

Для проверки корректности настройки, к одному сетевому интерфейсу подключён компьютер с IP-адрессом 192.168.1.10 (положим к eth0), а к другому с адрессом 192.168.1.11 (положим eth1). Для удобства, у самого роутера присвоен айпишник 192.168.1.2.

Итак, в качестве проверки использую ping. Плюс, дополнительно в качестве «фона» использую локальную сеть предприятия, чтобы проверить фильтрацию пакетовПингую оба компьютра (друг-друга), маршрутизатор, с маршрутизатора компьютеры — пинги идут. Смотрим tcpdump на роутере и компьютерах — по сети гуляют пакеты. Теперь давайте закрываться, и тут начинается самое интересное!

root@OpenWrt:/# iptables -F
root@OpenWrt:/# iptables -P INPUT DROP
root@OpenWrt:/# iptables -P OUTPUT DROP
root@OpenWrt:/# iptables -P FORWARD DROP
root@OpenWrt:/#


Казалось бы, после этого в сети должна наступить тишина и никто никого видеть и слышать не должен, кроме компьютера, который находится в одной сети с предприятием. Ан нет! Внимание:
1. Роутер не пингуется и не пингует компьютеры, т.е. правила INPUT, OUTPUT DROP сработали!
2. Компьютеры видят друг-друга, пингуются и по сети свободно гуляют пакеты. Это видно tcpdump на всех компьютерах, кроме маршрутизатора. Это говорит о том, что правило для сквозного трафика FORWARD DROP — не работает!
Почему так, я не знаю!

Едем дальше. Существует фаервол, специально для моста, именуемый ebtables. Основной его недостаток, что он более низкоуровневый, и стоит на канальном уровне. Основная фильтрация идёт по МАС-адресам. Синтаксис работы похож на iptables. Итак попробуем:

root@OpenWrt:/# ebtables -F
root@OpenWrt:/# ebtables -P FORWARD DROP


И всё, передача заткнулась. Можно открывать шапанское, и праздновать победу. Но теперь нам нужно разрешить передачу от компьютера с адрессом 192.168.1.10 к компьютеру 192.168.1.11 и наоборот. При этом не привязываясь к МАС-адресам. Я попробовал сделать вот такое правило:
ebtables -A FORWARD -p ipv4 --ip-dst 192.168.1.11 --ip-source 192.168.1.10 -j ACCEPT
ebtables -A FORWARD -p ipv4 --ip-dst 192.168.1.10 --ip-source 192.168.1.11 -j ACCEPT


Но чуда не произошло… Компьютеры как не слышали, так и не слышат друг-друга. Щипаю на себе волосы, читаю маны, но что и как делать не знаю. Вопрос в общем-то простой, но решение неочевидно.

Теперь вопросы:
1. Почему мне не удалось фильтровать проходящий трафик с помощью iptables?
2. Можно ли настроить фильтрацию пакетов с помощью ebtables по IP-адрессу, без привязки к МАС? Если можно, то как?
3. Есть ли возможность сделать так, чтобы ebtables передавала правила фильтрации трафика iptables?

Меня не сильно бить ногами, я только начинаю сталкиватся с этим. Я не системный администратор, но железка которая делается будет использоваться для маршрутизации и фильтрации, по сему приходится разбираться и курить.
  • Вопрос задан
  • 23902 просмотра
Решения вопроса 1
EvilMan
@EvilMan
1. Для того, чтобы можно было с помощью iptables фильтровать трафик, проходящий транзитом через мост необходимо выставить следующие системные переменные sysctl:
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1

2. После того как установите переменные sysctl, можно использовать для этого iptables, используя сопоставление (match) -m physdev --physdev-in / --physdev-out
3. См. предыдущий ответ.
Как-то так.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
EvilMan
@EvilMan
И так, подробный отчёт о тесте.
Из железа под рукой оказалось пара голосовых шлюзов, которые будут использоваться в роли конечных устройств (адреса 192.168.253.1 и 192.168.253.2), и управляемый свитч. Запихиваем каждый из аддпаков в отдельный влан, настраиваем привязку портов к вланам на коммутаторе и начинаем эксперимент.

1. На машинке создаём бридж-интерфейс и два влана, запихиваем вланы в бридж, поднимаем всё, прописываем адрес на бридж-интерфейсе:
brctl addbr br0
ip l add l eth2 name eth2.10 type vlan id 10
ip l add l eth2 name eth2.11 type vlan id 11
ip l s up dev br0
ip l s up dev eth2.10
ip l s up dev eth2.11
ip a add 192.168.253.3/29 dev br0


2. Устанавливаем переменные sysctl, при этом не будет никакой фильтрации:
sysctl -w net.bridge.bridge-nf-call-iptables=0
sysctl -w net.bridge.bridge-nf-filter-vlan-tagged=0


3. Проверяем связность между устройствами в разных портах моста и хостовой машиной (пингуем остальные адреса с аддпака 192.168.253.1/29):
test-addpac-1# ping 192.168.253.2
PING 192.168.253.2 (192.168.253.2): 56 data bytes
64 bytes from 192.168.253.2: icmp_seq=0 ttl=64 time=10 ms
64 bytes from 192.168.253.2: icmp_seq=1 ttl=64 time=10 ms
64 bytes from 192.168.253.2: icmp_seq=2 ttl=64 time=10 ms
64 bytes from 192.168.253.2: icmp_seq=3 ttl=64 time=10 ms

--- 192.168.253.2 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss'
round-trip min/avg/max = 10/10/10 ms
test-addpac-1# ping 192.168.253.3
PING 192.168.253.3 (192.168.253.3): 56 data bytes
64 bytes from 192.168.253.3: icmp_seq=0 ttl=64 time=15 ms
64 bytes from 192.168.253.3: icmp_seq=1 ttl=64 time=5 ms
64 bytes from 192.168.253.3: icmp_seq=2 ttl=64 time=5 ms
64 bytes from 192.168.253.3: icmp_seq=3 ttl=64 time=5 ms
64 bytes from 192.168.253.3: icmp_seq=4 ttl=64 time=5 ms
64 bytes from 192.168.253.3: icmp_seq=5 ttl=64 time=5 ms

--- 192.168.253.3 ping statistics ---
6 packets transmitted, 6 packets received, 0% packet loss'
round-trip min/avg/max = 5/6/15 ms

Как видно, всё работает.

4. Устанавливаем переменную для того, чтобы трафик между портами попадал в iptables, и добавляем правило в файерволл для блокировки трафика между двумя устройствами с заданными адресами:
sysctl -w net.bridge.bridge-nf-call-iptables=1
iptables -A FORWARD \
  --src 192.168.253.1 --dst 192.168.253.2 \
  -j DROP

И проверяем так же с помощью пинга:
test-addpac-1# ping 192.168.253.2 
PING 192.168.253.2 (192.168.253.2): 56 data bytes

--- 192.168.253.2 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss'
test-addpac-1# ping 192.168.253.3
PING 192.168.253.3 (192.168.253.3): 56 data bytes
64 bytes from 192.168.253.3: icmp_seq=0 ttl=64 time=5 ms
64 bytes from 192.168.253.3: icmp_seq=1 ttl=64 time=5 ms
64 bytes from 192.168.253.3: icmp_seq=2 ttl=64 time=5 ms
64 bytes from 192.168.253.3: icmp_seq=3 ttl=64 time=5 ms
64 bytes from 192.168.253.3: icmp_seq=4 ttl=64 time=5 ms

--- 192.168.253.3 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss'
round-trip min/avg/max = 5/5/5 ms

И проверяем счётчики в iptables (в динамике вы увидите, как они инкрементируются):
anton@insider:~$ sudo iptables -L FORWARD 8 -n -v
  455 38220 DROP  all  --  *  *   192.168.253.1  192.168.253.2 


Итого: вот примерно так можно фильтровать трафик между портами моста, обходясь совершенно без ebtables. Чтобы фильтровать трафик между портами с учётом интерфейса, то необходимо использовать расширение physdev примерно так:
iptables -A FORWARD -m physdev \
  --physdev-in eth2.10 --physdev-out eth2.11 \
  --src 192.168.253.1 --dst 192.168.253.2 \
  -j DROP


Так же следует учесть, что ebtables так же умеет фильтрацию по полям заголовков L3, если соответствующие модули загружены.

Можно сделать тоже самое с помощью ebtables:
ebtables -A FORWARD -p ip \
--ip-source 192.168.253.1 --ip-destination 192.168.253.2 \
-j DROP


Как видите, для фильтрации вовсе не нужно указывать мак-адреса. Подробные сведения о модулях ebtables вы сможете найти в мане. Так же будет полезно поиграться с tcpdump на бриджах и бридж-портах при фильтрации — вы увидите, что на один порт моста приходит трафик, но не пересылается в другой порт.
Ответ написан
shadowalone
@shadowalone
Вы должны понять уровни, на которых работает iptables и ebtables — это раз.
в бридже (L2) — работать надо с MAC-адресами.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы