Ретрансляция многоадресного трафика между сетью докеров и сетью хостов

#python #docker #sockets #networking #multicast

Вопрос:

Я пытался передать многоадресный трафик между сетью докеров и сетью хоста. Вот пример моей текущей настройки: контейнеры docker синего цвета внутри фиолетовой сети docker, а сетевые ПК хоста оранжевого цвета внутри желтой сети хоста:

Текст

Как вы можете видеть, я пытаюсь захватить и ретранслировать многоадресный трафик внутри контейнера докера «Ретрансляция». Я дал ему --net host возможность сделать доступным сетевой интерфейс хоста (ens160). Это позволяет мне захватывать трафик как в интерфейсе docker (docker0), так и в интерфейсе хоста, после чего я повторно отправляю трафик через противоположный интерфейс (трафик, захваченный в интерфейсе docker, получает возмущение с использованием интерфейса хоста и наоборот).

Похоже, это работает, когда я повторно отправляю трафик из сети докеров в сеть хоста. Но трафик из сети хоста не хочет передаваться в сеть докеров. Зеленые стрелки представляют успешные потоки многоадресного трафика, например, я подтвердил, что многоадресный трафик отправляется и принимается по стрелке. Красные стрелки показывают, что многоадресный трафик не принимается на концах стрелок. Весь трафик отправляется/принимается на одном и том же порту.

Вот некоторые из кода Python программы ретрансляции:

 import socket, netifaces as ni
from scapy.all import sniff, Raw, IP, UDP

def pkt_found(other_sock, multicast_address, port, iface_ip):
    def save_pkt(pkt):
        if pkt[IP].src != iface_ip:
            pkt[IP].src = iface_ip
            pkt[IP].dst = multicast_address
            pkt[UDP].sport = port
            pkt[UDP].dport = port
            del pkt[IP].chksum
            pkt.show2()
            other_sock.sendto(bytes(pkt[Raw]), (multicast_address, port))
    return save_pkt

def listen_for_traffic(iface_name, other_sock, multicast_address, port, iface_ip):
    sniff(iface=iface_name, filter="dst port " str(port), prn=pkt_found(other_sock, multicast_address, port, iface_ip))

def createMulticastSocket(iface_ip, multicast_address, port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, 
    socket.inet_aton(multicast_address) socket.inet_aton(iface_ip))
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 64)
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)
    sock.bind((multicast_address, port))
    return sock

multicast_address = "225.0.0.0"
port = 1234

docker_iface_name = "docker0"
host_iface_name = "ens160"

docker_iface_ip = ni.ifaddresses(docker_iface_name)[ni.AF_INET][0]['addr']
host_iface_ip = ni.ifaddresses(host_iface_name)[ni.AF_INET][0]['addr']

docker_sock = createMulticastSocket(docker_iface_ip, multicast_address, port)
host_sock = createMulticastSocket(host_iface_ip, multicast_address, port)

docker_thread = threading.Thread(target=listen_for_traffic, args=(docker_iface_name, host_sock, multicast_address, port, docker_iface_ip,))
host_thread = threading.Thread(target=listen_for_traffic, args=(host_iface_name, docker_sock, multicast_address, port, host_iface_ip,))

docker_thread.start()
host_thread.start()
 

Кто-нибудь знает, что я могу делать не так?

Ответ №1:

Очевидно, мне следовало вместо этого привязать сокеты к IP-адресам интерфейса. Изменение sock.bind((multicast_address, port)) на sock.bind((iface_ip, port)) сделало свое дело.