Объединение двух интерфейсов касания

Объединение двух интерфейсов касания

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

$ brctl showstp br0
br0
bridge id      8000.46846e0c0ff9
designated root    8000.46846e0c0ff9
root port         0            path cost          0
max age          20.00         bridge max age        20.00
hello time        2.00         bridge hello time      2.00
forward delay        15.00         bridge forward delay      15.00
ageing time         300.00
hello timer           1.98         tcn timer          0.00
topology change timer     0.00         gc timer         115.04
flags          


tap1 (1)
port id        8001            state            forwarding
designated root    8000.46846e0c0ff9   path cost        100
designated bridge  8000.46846e0c0ff9   message age timer      0.00
designated port    8001            forward delay timer   10.34
designated cost       0            hold timer         0.98
flags          

tap2 (2)
port id        8002            state            forwarding
designated root    8000.46846e0c0ff9   path cost        100
designated bridge  8000.46846e0c0ff9   message age timer      0.00
designated port    8002            forward delay timer    0.00
designated cost       0            hold timer         0.98
flags          

Я создал мост br0, добавил tap1и tap2. У меня есть программа, внедряющая пакеты ARP в , tap1используя libpcap. Wireshark правильно отображает пакеты, входящие в tap1. Однако пакеты не отображаются в tap2. Я попробовал добавить следующее правило в ebtables:

sudo ebtables -I INPUT --log --log-level debug

В журналах не отображается ни одного пакета. Буду признателен за любые комментарии.

EDIT: Добавляю больше информации. Вставка поддельных пакетов — это действительно приложение. Мое намерение здесь — полностью программно и без виртуальных машин смоделировать, как пакеты пересылаются через стек ядра Linux. Я не создаю никаких новых сетевых пространств имен. Возможно, в этом проблема?

У меня всего два процесса. Процесс "чтения" имеет файловый дескриптор, открытый для tap2, и постоянно пытается читать из него. Процесс записи имеет файловый дескриптор, открытый для , tap1и ждет приглашения пользователя для отправки ARP-запроса. ARP-запрос имеет случайный исходный IP-адрес. Исходный MAC-адрес установлен как MAC-адрес tap1. Вот вывод tcpdump:

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap1, link-type EN10MB (Ethernet), capture size 262144 bytes
^[[A07:19:57.752990 ARP, Request who-has google-public-dns-a.google.com tell 0.0.248.17, length 28
    0x0000:  ffff ffff ffff ba9c 0589 16ad 0806 0001
    0x0010:  0800 0604 0001 ba9c 0589 16ad 0000 f811
    0x0020:  0000 0000 0000 0808 0808

Я настроил tap1и tap2не имею IP-адресов. Может ли быть проблема в этом?

brctl addbr br0
ip tuntap add name tap1 mode tap
ip tuntap add name tap2 mode tap
brctl addif br0 tap1
brctl addif br0 tap2
ifconfig tap1 0.0.0.0 up
ifconfig tap2 0.0.0.0 up
ifconfig br0 10.0.1.1 netmask 255.255.255.0 broadcast 10.0.1.255
ip link set br0 up
ip link set tap1 up
ip link set tap2 up

На основании ответа я проверил присоединение различных приложений к tap2. Я заметил следующее: когда ни одно приложение не использует tap1или tap2, у обоих интерфейсов не установлен флаг LOWER_UP.

4: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default 
    link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500
    link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500

При запуске приложений устанавливается флаг LOWER_UP:

4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
    link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
    link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff

Извините, что текст получился длинным, но я просто надеюсь, что информации достаточно, чтобы разобраться в проблеме.

решение1

На всякий случай, поскольку вы сказали, что вы полный нуб: Интерфейс tun (уровень 3) или tap (уровень 2) — это конечная точка сетевого интерфейса приложения, и приложение может читать и записывать пакеты с этого сетевого интерфейса. То, что вы создаете с помощью ip tuntap add ...или устаревшие tunctl,постоянные именадля таких конечных точек, и вы, как правило, все равно запустите приложение, и оно ничего не сделает, пока вы не запустите приложение.

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

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

Так что если вы хотите это сделать и не хотите экспериментировать с собственным приложением, создающим и получающим пакеты, вам не нужен интерфейс tun/tap.

Тем не менее, я только что протестировал вашу настройку с небольшим изменением, поскольку вы не сказали, что вы используете для «внедрения» пакетов: я использовал два socats для создания tap endpoint tap0aи tap1a, затем я соединил их мостом и использовал еще два socats в двух разных пространствах имен для создания правильных пакетов для меня. Они должны быть в другом пространстве имен, так как локальные пакеты всегда будут доставляться через loopback lo.

И, как и ожидалось, мостовые устройства для подключения работают отлично.

Так что я предполагаю, что проблема в пакете, который вы вводите: Неправильный адрес Ethernet или нет трансляции. Пожалуйста, отредактируйте свой вопрос с tcpdump -xx ...выводом при вводе пакета ARP.

Или, возможно, вы хотели бы создать сетевые пространства имен и объединить две конечные точки двух veth-пар? Это намного проще.

Редактировать

Пакет ARP выглядит хорошо. Похоже, что к не подключено ни одно приложение tap2. Если да , то флаг для ip linkне должен быть виден . Предположение: мост обнаруживает, что устройство работает только частично, и не отправляет пакеты на этот порт.LOWER_UPtap2

Попробуйте заменить его на tapтотимеетприложение, подключенное к нему, что-то вроде

sudo socat TUN:10.0.2.2/24,tun-name=tapx,tun-type=tap,iff-up - | hexdump -C

( 10.0.2.2/24адрес ничего не делает, но socatне будет работать, если вы не укажете адрес), а в другом терминале

sudo ip link set tapx master br0

(который заменяет brctl addif), затем введите свой пакет несколько раз и посмотрите, получите ли вы hexdump в первом окне. Также проверьте с LOWER_UPпомощью ip link show dev tapx.

Кстати, ifconfigи brctlустарели. Вместо этого используйте ipи bridge.

Не имеет значения, назначены ли IP-адреса портам моста, поскольку порты мостане имеют IP-адресов(если они получили назначение до того, как стали рабами моста, они игнорируются). См. напримерздесь.

решение2

Я долго с этим боролся и думаю, что нашел решение. Или, по крайней мере, лучшее понимание того, что происходит.

Важно помнить, что единственный способ доставить пакет на интерфейс ответвления на стороне приема («RX») — это записать этот пакет в дескриптор сокета.созданный процессом, который открыл кран(через open("/dev/net/tun",...)и ioctl). Только один процесс может иметь этот файловый дескриптор одновременно. Если устройство TAP открыто, а другой процесс пытается повторно открыть другое устройство TAP с тем же именем, этот системный вызов завершится ошибкой.

Поэтому, когда у вас есть любой другой процесс, например Wireshark, открывающий сырой сокет и затем связывающийчток tap0, он способен только записывать трафиквнесистемы (с точки зрения ядра). То есть, wireshark должен увеличить счетчик TX, tap0и только RXпакеты будут пересылаться на мостовой интерфейс.

Вы можете проверить счетчики для каждого лайка:

#!/bin/bash
for if in tap{0,1}; do
    stats=/sys/class/net/$if/statistics/
    rx=$(cat $stats/rx_packets)
    tx=$(cat $stats/tx_packets)
    echo "$if: rx=$rx, tx=$tx"
done

который выводит что-то вроде:

tap0: rx=0, tx=6
tap1: rx=0, tx=5

Итак, в вашем конкретном случае я подозреваю, что проблема здесь:

У меня есть программа, которая вводит ARPпакеты в tap1libpcap. Wireshark правильно показывает пакеты, входящие в tap1. Однако пакеты не отображаются в tap2.

Как вы вводите ARP-пакеты в tap1? Я предполагаю, что wireshark не вызывает fd = open("/dev/net/tun", ...)и ioctl(fd, TUNSETIFF, ...), поэтому отправленные пакеты будут TX, и, следовательно, не будут соединены мостом.

Вам понадобится программа, которая открывается tap0для записи пакетов в tap0файловый дескриптор , чтобы эти пакеты были пересланы br0и отображены на tap1.

Связанный контент