Я хочу обмениваться пакетами Ethernet между двумя устройствами (для реализации стека протоколов TCP/IP в пользовательском режиме).
Проблема, с которой я столкнулся, заключается в том, что tap1 и tap2 могут принимать только широковещательные пакеты через мост, но не пакеты точка-точка!
Например, когда я отправляю пакет с tap1 на tap2, tcmpdump может захватить пакет на tap1, но tap2 не может получить пакет. Однако, когда я устанавливаю адрес назначения как «ff:ff:ff:ff:ff:ff» или любой другой неизвестный mac-адрес (это будет триггерная трансляция), tap2 получит пакет.
Моя конфигурация:
- создать устройство с двумя кранами
ip tuntap добавить режим нажмите tun1
ip tuntap добавить режим нажмите tun2
# назначаем ip адрес для реализации протокола arp
IP-адрес добавить 172.19.16.1 dev tun1
IP-адрес добавить 172.19.16.2 dev tun2
ip link set tun1 up
ip link настроить tun2 вверх
- создать мост
brctl addbr br0
brctl addif br0 tun1
brctl addif br0 tun2
ip link set br0 up
Ниже приведено состояние интерфейса моста и крана:
маки:
порт без MAC-адреса является локальным? таймер старения
2 46:44:6e:55:9b:c5 да 0.00
2 46:44:6e:55:9b:c5 да 0.00
1 f2:6b:68:c9:60:6b да 0,00
1 f2:6b:68:c9:60:6b да 0,00
государство:
бр0
идентификатор моста 8000.46446e559bc5
назначенный корень 8000.46446e559bc5
корневой порт 0 стоимость пути 0
максимальный возраст 20.00 бридж максимальный возраст 20.00
привет время 2.00 мост привет время 2.00
задержка пересылки 15.00 задержка пересылки моста 15.00
время старения 300.00
привет таймер 0.00 tcn таймер 0.00
таймер изменения топологии 0.00 gc timer 89.77
флаги
тун1 (1)
идентификатор порта 8001 состояние переадресации
назначенный корневой путь 8000.46446e559bc5 стоимость пути 100
назначенный мост 8000.46446e559bc5 таймер возраста сообщения 0,00
назначенный порт 8001 таймер задержки пересылки 0,00
назначенная стоимость 0 таймер удержания 0.00
флаги
тун2 (2)
идентификатор порта 8002 состояние переадресации
назначенный корневой путь 8000.46446e559bc5 стоимость пути 100
назначенный мост 8000.46446e559bc5 таймер возраста сообщения 0,00
назначенный порт 8002 таймер задержки пересылки 0.00
назначенная стоимость 0 таймер удержания 0.00
флаги
Ниже приведен мой тестовый код:
импортировать fcntl
импорт ОС
импортировать if_tun
импорт ctypes
импортировать структуру
из импорта scapy.all *
из if_tun импортировать IfReq, TUNSETIFF, IFF_TUN
def register_tun (имя: улица):
fd = os.open ("/dev/net/tun", os.O_RDWR)
если fd < 0:
вернуть фд
г = если требуется ()
ctypes.memset (ctypes.byref (r), 0, ctypes.sizeof (r))
r.ifr_ifru.ifru_flags = 0x0002 | 0x1000
r.ifr_ifrn.ifrn_name = имя.кодировать("utf-8")
fcntl.ioctl(fd, TUNSETIFF,r)
вернуть фд
если __name__ == "__main__":
name = input("имя устройства ввода")
fd = register_tun (имя)
если fd < 0:
распечатать("ошибка")
если имя == "tun2":
пока верно:
buf = os.read(fd,1024)
print(f"получить {len(buf)} данные")
Эфир (сырой (баф)). показать ()
mac1 = "f2:6b:68:c9:60:6b"
mac2 = "46:44:6e:55:9b:c5"
пока верно:
тип = ввод ()
a = Эфир(dst=mac2,src=mac1)/ARP(pdst="172.19.16.1",psrc="172.19.16.2")
шоу()
распечатать("написать:")
print(os.write(fd, raw(a)))
Примечания:
- Хотя имя устройства называется tun, его тип — tap
- Я запускаю два тестовых кода одновременно, один подключается к tun1, а другой подключается к tun2. Таким образом, два устройства находятся в состоянии LOWWER_UP.