Мне нужно реализовать службу прозрачной локальной сети на основе VLAN в Linux. Это означает, что мне нужно взять настроенную VLAN и переслать ее прямо на указанный порт (все широковещательные / многоадресные и одноадресные пакеты).
Тривиальным решением будет определение моста 1 к 1 между интерфейсом VLAN и указанным портом. Обратной стороной этого решения является то, что я узнал обо всех MAC-адресах в этом туннеле. Я' m работает на встроенном устройстве с ограниченной таблицей Mac, и вы хотите избежать загрязнения таблицы Mac устройствами из сетей, которые я подключаю.
Я пытался найти способ использовать ebtables для этой задачи, но похоже, что -o параметры ebtables полезны только в цепочке FORWARD, которая возникает после обучения Mac. Цепочка BROUTING - это та, которая мне нужна, но похоже, что с этого момента я не могу заставить пакет выйти на конкретный интерфейс.
Итак, ebtables кажется тупиком. Есть другие варианты? В идеальном мире я бы предпочел иметь службу TLS на основе любого ключа, и не только VLAN, но и VLAN пока подойдут.
Спасибо,
Я пытался найти способ использовать ebtables для этой задачи, но похоже, что -o параметры ebtables полезны только в цепочке FORWARD, которая возникает после обучения Mac. Цепочка BROUTING - это та, которая мне нужна, но похоже, что с этого момента я не могу заставить пакет выйти на конкретный интерфейс.
Итак, ebtables кажется тупиком. Есть другие варианты? В идеальном мире я бы предпочел иметь службу TLS на основе любого ключа, и не только VLAN, но и VLAN пока подойдут.
Спасибо,
Я пытался найти способ использовать ebtables для этой задачи, но похоже, что -o параметры ebtables полезны только в цепочке FORWARD, которая возникает после обучения Mac. Цепочка BROUTING - это та, которая мне нужна, но похоже, что с этого момента я не могу заставить пакет выйти на конкретный интерфейс.
Итак, ebtables кажется тупиком. Есть другие варианты? В идеальном мире я бы предпочел иметь службу TLS на основе любого ключа, и не только VLAN, но и VLAN пока подойдут.
Спасибо, Я бы предпочел иметь службу TLS на основе любого ключа, и не только VLAN, но VLAN пока подойдет.
Спасибо, Я бы предпочел иметь службу TLS на основе любого ключа, и не только VLAN, но VLAN пока подойдет.
Спасибо, Илья.
UPDATE: Добавлено решение, все еще использующее мост. Возможно, для корпуса VLAN в любом случае, чтобы использовать мост Linux для своих возможностей фильтрации VLAN, и полностью отключить обучение MAC. tc
ниже может быть все еще полезен для его общего способа сравнения селекторов (вероятно, было бы проще использовать tc с достаточным количеством совпадений для чего-нибудь кроме VLAN в качестве селектора, чем использовать мост без кода для обработки).
Можно отключить обучение MAC-адресов. Это делается командой bridge link
. Тогда мост можно настроить на фильтрацию VLAN (используя также bridge vlan
): ему не нужен MAC-адрес, вся его переадресация будет осуществляться на основе настроенных параметров VLAN.
learning on or learning off
контролирует, будет ли данный порт запоминать MAC-адреса из полученного трафика или нет. Если обучение выключено, то мост будет в конечном итоге затопляет любой трафик, для которого нет входа в FDB. По умолчанию это Флаг включен.
learning_sync включен или learning_sync выключен
Контролирует, будет ли данный порт синхронизировать MAC-адреса, выученные на порту устройства, с мостом FDB.
Так, например, давайте посмотрим на систему с интерфейсом eth0 в виде ствола с тегированными фреймами, и eth1 eth2 eth3 или vlan ids 10, 20 и 30, не тегированные. Это было бы сделано с:
ip link add name br0 type bridge vlan_filtering 1
#remove implicit bridge's self port br0 from any interaction.
# Might have to not be done if using an IP on the bridge
# but more configuration might then be needed anyway.
bridge vlan del vid 1 dev br0 self
bridge link set dev br0 learning off learning_sync off self
for $nic in eth0 eth1 eth2 eth3; do
ip link set dev $nic master br0
bridge link set dev $nic learning off learning_sync off
bridge vlan del vid 1 dev $nic
done
ip link set br0 up
bridge vlan add 10 dev eth0
bridge vlan add 20 dev eth0
bridge vlan add 30 dev eth0
bridge vlan add vid 10 pvid 10 untagged dev eth1
bridge vlan add vid 20 pvid 20 untagged dev eth2
bridge vlan add vid 30 pvid 30 untagged dev eth3
Чтобы проверить, как ведет себя эта другая установка, просто замените следующие строки в скрипте установки в конце (которые используют метод tc, описанный в следующей части ответа):
ip netns exec fakebridge tc qdisc add dev trunk0 ingress
for vlan in 10 20 30; do
ip netns exec fakebridge tc qdisc add dev vlan$vlan ingress
ip netns exec fakebridge tc filter add dev vlan$vlan parent ffff: matchall action vlan push id $vlan action mirred egress redirect dev trunk0
ip netns exec fakebridge tc filter add dev trunk0 parent ffff: basic match "meta(vlan mask 0xfff eq $vlan)" action vlan pop action mirred egress redirect dev vlan$vlan
done
вместо них (это больше не фальшивый мост, но в любом случае. ...):
ip -n fakebridge link add name br0 type bridge vlan_filtering 1
ip netns exec fakebridge bridge vlan del vid 1 dev br0 self #remove implicit bridge's self port br0 from any interaction
ip -n fakebridge link set dev trunk0 master br0
ip netns exec fakebridge bridge vlan del vid 1 dev trunk0
ip netns exec fakebridge bridge link set dev trunk0 learning off learning_sync off
for vlan in 10 20 30; do
ip -n fakebridge link set dev vlan$vlan master br0
ip netns exec fakebridge bridge link set dev vlan$vlan learning off learning_sync off
ip netns exec fakebridge bridge vlan add vid $vlan dev trunk0
ip netns exec fakebridge bridge vlan del vid 1 dev vlan$vlan
ip netns exec fakebridge bridge vlan add vid $vlan pvid $vlan untagged dev vlan$vlan
done
ip -n fakebridge link set br0 up
Также возможно вообще не использовать мост, а работать с VLAN ID для операций, используя ...
tc способен манипулировать VLAN непосредственно используя tc vlan:
ОПИСАНИЕ
Действие vlan позволяет выполнить 802.1Q en- или декапсуляцию на a пакет, отражаемый режимами работы POP, PUSH и MODIFY. СОЗ режим прост, так как не требуется никакой дополнительной информации, чтобы просто бросить крайняя внешняя оболочка ВЛВС. Режимы PUSH и MODIFY требуют, чтобы на На ряду с другими функциями tc:
- matchall (может быть заменен на
u32 match u32 0 0
на старых ядрах) для безусловного соответствия пакетов,- basic+ematch для соответствия на мета-информации типа vlan id (этот SF Q/A помог): tc u32 - как сопоставить протоколы L2 в последних ядрах?),
- зеркально для фактического перемещения пакетов между интерфейсами без пересылки и маршрутизации.
и обычная сантехника (имеют qdisc, приложите фильтр с действием ), можно перемещать пакеты с одного интерфейса на другой, инкапсулируя или декапсулируя 802.1Q ID виртуальной локальной сети. Система не будет ни соединять, ни маршрутизировать эти пакеты. Системе не придется запоминать MAC-адрес или манипулировать IP-адресом, ее осведомленность о пакетах и протоколах будет ограничена тем, что делается с помощью
tc
.Обратите внимание, что это является доказательством концепции. Конечно, реальная система все равно должна будет взаимодействовать, используя IP, заботясь о том, чтобы не вмешиваться в эти настройки. Правильная реализация этого для производства, вероятно, сопряжена с непредвиденными дополнительными трудностями, учитывая, что tc является сложным инструментом. С помощью tc могут быть и другие лучшие способы более общей работы (думая о потоке tc для использования VLAN ID в качестве ключа для отображения в классе, который можно использовать более общим образом, или, возможно, использовать что-то другое в качестве ключа рядом с VLAN, при условии, что есть способ инкапсуляции/декапсуляции. )
Так что, например, давайте посмотрим на систему с интерфейсом eth0 в виде багажника с метками фреймов, и eth1 eth2 eth3 или vlan ids 10, 20 и 30, без метки. Позволить стороне с тегами общаться с правильной немаркированной стороной, а обратное будет сделано с:
tc qdisc add dev eth0 handle ffff: ingress tc qdisc add dev eth1 handle ffff: ingress tc qdisc add dev eth2 handle ffff: ingress tc qdisc add dev eth3 handle ffff: ingress tc filter add dev eth0 parent ffff: basic match "meta(vlan mask 0xfff eq 10)" action vlan pop action mirred egress redirect dev eth1 tc filter add dev eth0 parent ffff: basic match "meta(vlan mask 0xfff eq 20)" action vlan pop action mirred egress redirect dev eth2 tc filter add dev eth0 parent ffff: basic match "meta(vlan mask 0xfff eq 30)" action vlan pop action mirred egress redirect dev eth3 tc filter add dev eth1 parent ffff: matchall action vlan push id 10 action mirred egress redirect dev eth0 tc filter add dev eth2 parent ffff: matchall action vlan push id 20 action mirred egress redirect dev eth0 tc filter add dev eth3 parent ffff: matchall action vlan push id 30 action mirred egress redirect dev eth0
Может показаться логичным, что фактические интерфейсы должны быть переведены в беспорядочный режим для фактического перенаправления трафика, но в ядре 5.0 в этом не было необходимости. x и veth интерфейсов при тестировании в любом случае.
макет используя ip netns для сетевых пространств имён
Я провёл несколько экспериментов по реализации фальшивого моста с одним тегируемым магистральным интерфейсом и несколькими не тегируемыми vlan интерфейсами, использующими сетевые пространства имён. Каждый "хост" имеет своё собственное пространство имён и связан с другими хостами с помощью сетевых элементов, которые сами по себе реализованы с другими сетевыми пространствами имён, которые включают в себя мост. Настоящая система, имитирующая то, что может сделать ваше встроенное устройство, будет называться fakebridge, так как она может выглядеть как мост, знающий VLAN.
tagged untagged _______ .|host10b| +-------+ . ======= +------+ | |....vlan10....|host10| | |.......trunk......|fake | ====== |router|..................| |....vlan20....|host20| | | (vlans 10+20+30) |bridge | ====== +------+ | |....vlan30....|host30| +-------+ ------Таким образом, 1+1+4 = 6 хостов, 1 + 3 = 4 сети в общей сложности 10 пространств имён.
После выполнения скрипта ниже (от имени root), можно проверить и наблюдать с помощью команд типа:
term1:
ip netns exec fakebridge tcpdump -l -n -s0 -e -p -i trunk0
term2:
ip netns exec host10 ping -c1 198.51.100.20
Давая, например:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on trunk0, link-type EN10MB (Ethernet), capture size 262144 bytes 00:27:56.036743 c2:e8:f4:79:28:96 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 10, p 0, ethertype ARP, Request who-has 192.0.2.110 tell 192.0.2.10, length 28 00:27:56.036777 16:51:fa:18:21:b0 > c2:e8:f4:79:28:96, ethertype 802.1Q (0x8100), length 46: vlan 10, p 0, ethertype ARP, Reply 192.0.2.110 is-at 16:51:fa:18:21:b0, length 28 00:27:56.036794 c2:e8:f4:79:28:96 > 16:51:fa:18:21:b0, ethertype 802.1Q (0x8100), length 102: vlan 10, p 0, ethertype IPv4, 192.0.2.10 > 198.51.100.20: ICMP echo request, id 13483, seq 1, length 64 00:27:56.036807 16:51:fa:18:21:b0 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 20, p 0, ethertype ARP, Request who-has 198.51.100.20 tell 198.51.100.120, length 28 00:27:56.036832 b6:1d:bc:33:87:98 > 16:51:fa:18:21:b0, ethertype 802.1Q (0x8100), length 46: vlan 20, p 0, ethertype ARP, Reply 198.51.100.20 is-at b6:1d:bc:33:87:98, length 28 00:27:56.036841 16:51:fa:18:21:b0 > b6:1d:bc:33:87:98, ethertype 802.1Q (0x8100), length 102: vlan 20, p 0, ethertype IPv4, 192.0.2.10 > 198.51.100.20: ICMP echo request, id 13483, seq 1, length 64 00:27:56.036860 b6:1d:bc:33:87:98 > 16:51:fa:18:21:b0, ethertype 802.1Q (0x8100), length 102: vlan 20, p 0, ethertype IPv4, 198.51.100.20 > 192.0.2.10: ICMP echo reply, id 13483, seq 1, length 64 00:27:56.036867 16:51:fa:18:21:b0 > c2:e8:f4:79:28:96, ethertype 802.1Q (0x8100), length 102: vlan 10, p 0, ethertype IPv4, 198.51.100.20 > 192.0.2.10: ICMP echo reply, id 13483, seq 1, length 64 00:28:01.043203 16:51:fa:18:21:b0 > c2:e8:f4:79:28:96, ethertype 802.1Q (0x8100), length 46: vlan 10, p 0, ethertype ARP, Request who-has 192.0.2.10 tell 192.0.2.110, length 28 00:28:01.043246 b6:1d:bc:33:87:98 > 16:51:fa:18:21:b0, ethertype 802.1Q (0x8100), length 46: vlan 20, p 0, ethertype ARP, Request who-has 198.51.100.120 tell 198.51.100.20, length 28 00:28:01.043287 c2:e8:f4:79:28:96 > 16:51:fa:18:21:b0, ethertype 802.1Q (0x8100), length 46: vlan 10, p 0, ethertype ARP, Reply 192.0.2.10 is-at c2:e8:f4:79:28:96, length 28 00:28:01.043284 16:51:fa:18:21:b0 > b6:1d:bc:33:87:98, ethertype 802.1Q (0x8100), length 46: vlan 20, p 0, ethertype ARP, Reply 198.51.100.120 is-at 16:51:fa:18:21:b0, length 28
Сценарий установки для запуска от имени root. Он создает различные сетевые пространства имен, используя
ip netns
, заполняет необходимые сетевые соединения (мосты и veth), настраивает фильтры tc на fakebridge, и, наконец, настраивает IP-адреса различных хостов так, чтобы можно было поэкспериментировать. Фейкбридж tc остается без IP и без моста. Нет MAC-таблицы, которую можно было бы заполнить:ip neigh
илиbridge fdb
не покажет ничего, что связано с трафиком, так как нет ARP без обучения IP или MAC без моста.#!/bin/sh if ip netns id | grep -qv '^ *$' ; then printf 'ERROR: leave netns "%s" first\n' $(ip netns id) >&2 exit 1 fi hosts='router fakebridge host10 host10b host20 host30' nets='trunk vlan10 vlan20 vlan30' for ns in $hosts $nets; do ip netns del $ns 2>/dev/null || : ip netns add $ns ip netns exec $ns sysctl -q -w net.ipv6.conf.default.disable_ipv6=1 ip netns exec $ns sysctl -q -w net.ipv4.icmp_echo_ignore_broadcasts=0 done for ns in $hosts; do ip -n $ns link set lo up done bmac=1 for ns in $nets; do ip -n $ns link add bridge0 address 02:00:00:00:00:$(printf '%02d' $bmac) type bridge ip -n $ns link set bridge0 up bmac=$(($bmac+1)) done link_ns () { ip -n $1 link add name "$3" type veth peer netns $2 name "$4" ip -n $1 link set dev "$3" up ip -n $2 link set dev "$4" up if printf '%s\n' "$nets" | grep -q -w "$1"; then ip -n "$1" link set dev "$3" master bridge0 fi if printf '%s\n' "$nets" | grep -q -w "$2"; then ip -n "$2" link set dev "$4" master bridge0 fi } link_ns trunk fakebridge fakebridge trunk0 link_ns vlan10 fakebridge fakebridge vlan10 link_ns vlan20 fakebridge fakebridge vlan20 link_ns vlan30 fakebridge fakebridge vlan30 link_ns trunk router router trunk0 link_ns vlan10 host10 host10 eth0 link_ns vlan10 host10b host10b eth0 link_ns vlan20 host20 host20 eth0 link_ns vlan30 host30 host30 eth0 ip netns exec fakebridge tc qdisc add dev trunk0 ingress for vlan in 10 20 30; do ip netns exec fakebridge tc qdisc add dev vlan$vlan ingress ip netns exec fakebridge tc filter add dev vlan$vlan parent ffff: matchall action vlan push id $vlan action mirred egress redirect dev trunk0 ip netns exec fakebridge tc filter add dev trunk0 parent ffff: basic match "meta(vlan mask 0xfff eq $vlan)" action vlan pop action mirred egress redirect dev vlan$vlan done for vlan in 10 20 30; do ip -n router link add link trunk0 name trunk.$vlan type vlan id $vlan ip -n router link set dev trunk.$vlan up ip netns exec router sysctl -q -w net.ipv4.conf.trunk/$vlan.forwarding=1 done ip -n router address add 192.0.2.110/24 dev trunk.10 ip -n router address add 198.51.100.120/24 dev trunk.20 ip -n router address add 203.0.113.130/24 dev trunk.30 ip -n host10 address add 192.0.2.10/24 dev eth0 ip -n host10b address add 192.0.2.11/24 dev eth0 ip -n host20 address add 198.51.100.20/24 dev eth0 ip -n host30 address add 203.0.113.30/24 dev eth0 ip -n host10 route add default via 192.0.2.110 ip -n host10b route add default via 192.0.2.110 ip -n host20 route add default via 198.51.100.120 ip -n host30 route add default via 203.0.113.130