Why does Linux network traffic only go through eth0?

There are two possible design models for a TCP/IP network stack: a strong host model and a weak host model. You're expecting behavior that would match the strong host model. Linux is designed to use the weak host model. In general the weak host model is more common as it reduces the complexity of the routing code and thus might offer better performance. Otherwise the two host models are just different design principles: neither is inherently better than the other.

Basically, the weak host model means that outgoing traffic will be sent out the first interface listed in the routing table that matches the IP address of the destination (or selected gateway, if the destination is not reachable directly), without regard to the source IP address.

This is basically why it's generally inadvisable to use two separate physical interfaces if you need two IP addresses on the same network segment. Instead assign two IP addresses for one interface (IP aliases: e.g. eth1 = 192.168.8.142 and eth1:0 = 192.168.8.140). If you need more bandwidth than a single interface can provide, bond (or team, if applicable) two or more interfaces together, and then run both IPs on the bond/team.

By tweaking a number of sysctl settings and using the "advanced routing" functionality to set up independent routing tables for each NIC, it is possible to make Linux behave like a strong-host-model system. But that is a very special configuration, and I would recommend thinking twice before implementing it.

See the answers at Linux Source Routing, Strong End System Model / Strong Host Model? if you really need it.


An additional point to consider is that the eth1 interface is configured with a subnet mask of 255.255.255.255.

This means that the eth1 interface is configured to expect no other devices(hosts) on its network interface. This means that it won't be able to communicate with your 192.168.8.142 client.


After a lot of search, I found Why netcat doesn't use the right interface associated with the IP?, and this is the same problem. As @telcoM said, outgoing traffic will be sent out to the first interface, and that's the problem, so, the easiest way to solve this is:

ip route add default via 192.168.8.142 dev eth1 table 142
ip rule add from 192.168.8.142 table 142

This route will make ip route get 192.168.8.135 from 192.168.8.142 return eth1 instead of eth0. Then everything works as expected.