I have a multicast system with multiple network interfaces. Packets transmitted using the socket I created are being sent out the correct interface, but the packet's source address is incorrect. The source address should match the interface that was used to transmit the packet over an isolated network, but it's using the source address from the interface on the private network (which ultimately connects to the internet).
What do I need to change about my socket configuration, so that transmitted packets are sent with the isolated network interface's IP address as the source address?
import socket
src_ip = '172.17.0.1' # isolated network interface IP address which should be source address but isn't
dst_ip = '225.17.0.18' # destination IP address
port = 30000
msg = bytes([0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x88, 0xAA, 0xBB, 0xCC, 0xDD ])
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.connect((dst_ip, port))
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(src_ip))
sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(dst_ip) + socket.inet_aton(src_ip))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.sendall(msg)
The packet gets transmitted as expected, except for the source address. Any thoughts? I'm using Python 3.6. I know it's old but it's what they're using here.
If you don't bind the socket to a specific address, the network stack chooses the source address arbitrarily, and it doesn't have to be the same as the address of the interface it sends from. If you want a specific source address, call sock.bind()
.
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.bind((src_ip, 0))
sock.connect((dst_ip, port))
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(src_ip))
sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(dst_ip) + socket.inet_aton(src_ip))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Specifying port 0 in bind()
allows the OS to select an unused source port.