How to route TCP/IP responses through a different interface?
You could add an additional address to the lo
interface on each system and use these new addresses as the TCP connection endpoints. You can then use static routes to direct which path each machine takes to get to the other machine's lo
address.
For example:
Machine A:
ip addr add 1.1.1.1/32 dev lo
ip route add 2.2.2.2/32 dev eth0 via <eth0 default gateway>
Machine B:
ip addr add 2.2.2.2/32 dev lo
ip route add 1.1.1.1/32 dev gr0
Then bind to 1.1.1.1 on machine A and connect to 2.2.2.2.
TCP/IP connection on a specific interface
Use the bind()
function to bind the socket to either 192.168.1.3
or 192.168.1.2
before calling connect()
, ConnectEx()
, or WSAConnect()
. That tells the socket which specific interface to use for the outgoing connection. For example:
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in localaddr = {0};
localaddr.sin_family = AF_INET;
localaddr.sin_addr.s_addr = inet_addr("192.168.1.3");
bind(s, (sockaddr*)&localaddr, sizeof(localaddr));
sockaddr_in remoteaddr = {0};
remoteaddr.sin_family = AF_INET;
remoteaddr.sin_addr.s_addr = inet_addr("192.168.1.4");
remoteaddr.sin_port = 12345; // whatever the server is listening on
connect(s, (sockaddr*)&remoteaddr, sizeof(remoteaddr));
Alternatively:
addrinfo localhints = {0};
localhints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
localhints.ai_family = AF_INET;
localhints.ai_socktype = SOCK_STREAM;
localhints.ai_protocol = IPPROTO_TCP;
addrinfo *localaddr = NULL;
getaddrinfo("192.168.1.3", "0", &localhints, &localaddr);
bind(s, localaddr->ai_addr, localaddr->ai_addrlen);
freeaddrinfo(localaddr);
addrinfo remotehints = {0};
remotehints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
remotehints.ai_family = AF_INET;
remotehints.ai_socktype = SOCK_STREAM;
remotehints.ai_protocol = IPPROTO_TCP;
addrinfo *remoteaddr = NULL;
getaddrinfo("192.168.1.4", "12345", &remotehints, &remoteaddr);
connect(s, remoteaddr->ai_addr, remoteaddr->ai_addrlen);
freeaddrinfo(remoteaddr);
How to find the interface offering the route to a specific IP in Python3?
Provided that there is any known service to connect to on the remote host, use socket.getsockname()
to find out which local IP is used for connecting:
import socket
# connect to known destination, e.g. via UDP port 80
test_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
test_sock.connect(("10.2.1.1", 80))
# check which local IP was used to connect
with test_sock:
private_ip, *_ = test_sock.getsockname()
Host-device communication in terms of subnet mask and routing
the netmask can be thought as a bitmask for an IP address.
if (address1 & netmask) == (address2 & netmask)
then the 2 ip addresses are considered on the same subnet. (this expression can be written in many different ways...)
the netmask is only a way to 'virtually' divide a network: the netmask is not part of the ip header, and is not transmitted on the wire. no-one knows the netmask of a device on the network, except the device itself. it is used internally inside the tcp stack of a device to take some basic routing decisions. note that there are other ways to define a subnet, which may not involve a netmask but achieves the same result: grouping multiple devices into a 'virtual' network.
a router on which a device is plugged may even have a different definition of the netmask for this same device: it does not matter as long as the router is routing packets correctly. the netmask is used primarily to automatically compute some well-known addresses: for example, the broadcast address used for udp broadcast packets is computed from the ip address of a device and its netmask.
in your specific case:
there is no physical router, but your computer is a router (it routes packets internally to the different network interfaces). your computer contains a routing table which tells which outgoing interface a specific packet should use (on windows, try route print
, on linux, as root, try route
).
generally, the routing table is setup so that a packet goes out on the interface which is on the same subnet as the target device. the computer uses the above logical expression on each interface to determine if the destination is on the same subnet than this interface. if the expression is true, the packet goes out. each entry has a parameter (called a metric) which allows to chose the seemingly best interface in case multiple routes are possible.
you should note that the routing table is dynamic: it can be modified manually, to add a specific route (e.g. if you know that a particular device is reachable through an interface but that device has an ip address which has no relation with this interface ip address/netmask). there are also some protocols (arp, dhcp...) used in a local network which broadcast routing informations, which are automatically handled by your system to modify the routing table.
Related Topics
Getting Android Sdk Tools to Work on Raspberry Pi
Graphics Card Memory and Virtual Address Space of a Process
New Syscall Not Found (Linux Kernel 3.0.0) Where Should I Start Looking
How to Get Errno When Epoll_Wait Returns Epollerr
Bash Script That Creates a Directory Structure
How to Programmatically Pick and Choose Which Core of a Multi-Core CPU My Thread Should Run On
Why Use G++ Instead of Gcc to Compile *.Cc Files
Is Number of Frame = Number of Pages(Linux)
Amazon Ec2 Lost Private Key, How to Get Access to The Server
Unknown Symbol in While Loading a Kernel Module
Bash: Split Stdout from Multiple Concurrent Commands into Columns
Create a Hard Link from a File Handle on Unix
Running Docker on Google Colab