И так, подробный отчёт о тесте.
Из железа под рукой оказалось пара голосовых шлюзов, которые будут использоваться в роли конечных устройств (адреса 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 на бриджах и бридж-портах при фильтрации — вы увидите, что на один порт моста приходит трафик, но не пересылается в другой порт.