Search code examples
javalinuxsocketsnetwork-interfaceoutbound

Java Sockets and multiple outgoing interfaces on Linux


There are quite a couple of related questions (e.g. Java Socket specify a certain network interface for outgoing connections ) however I couldn't find a satisfying i.e. practical solution to my problem:

On my target (Linux) platform there are multiple network interfaces (eth0...ethN) from which a Server S is reachable. The default route is normally via eth0, however I'm trying to connect S via e.g. eth4 using

new java.net.Socket(IP_of_S, targetport, IP_of_eth4, srcport)

or

sock.bind( eth4_SocketAddress );
sock.connect( S_SocketAddress );

In this example case the IP of eth4 is assigned correctly but traffic is still going out trough the interface of the default route. I've learned this is due to the the "weak end system model" RFC 1122. However I'm wondering whether there's still a Java-based solution to achieving my original goal or whether I have to trigger external iptables or route calls from my program.

(BTW: The outgoing interface needs to be chosen dynamically at runtime, i.e. my program closes the connection and tries to reconnect using a different outbound interface quite frequently.)


Solution

  • As far as I know, you cannot choose the outgoing interface without some routing table setup.

    In my opinion, the best solution is to set up a bunch of source-specific routes, routes that match on the source address of a packet, and bind to a given source address in order to select the route (as you already do). There are two ways of achieving that:

    • use ip rule and multiple routing tables — this is described in http://lartc.org/howto/lartc.rpdb.html ;
    • use ip route add ... from .... As far as I know, this only works for IPv6, but avoids the complexity of multiple routing tables.

    You'll find some background about source-specific routing in https://arxiv.org/pdf/1403.0445v4.pdf (disclaimer, I'm a co-author).