#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))
сделало свое дело.