forcing network traffic to route via a specific, non-default interface
Solution 1:
Routes are processed from the most specific route to the least specific (aka default) route.
default via 10.31.96.1 dev em3 proto static
10.0.0.0/8 dev em1 proto kernel scope link src 10.0.0.100
10.31.96.0/22 dev em3 proto kernel scope link src 10.31.97.100
10.31.96.0/22 dev em4 proto kernel scope link src 10.31.96.61
You said you want should be going out through em3 unless its destined for something else on the local 10.0.0.1/8 subnet
. This is exactly what is happening. The IP address 10.31.45.1
is within 10.0.0.0/8
and so it is leaving via em1. The 10.0.0.0/8
route matches that address is more specific then the default route. The address doesn't match the the 10.31.96.0/22
route. Therefore the em1 route is selected.
Your real problem is that you have a subnetmask on that em1 interface that is far too large for what you probably need, and it conflicts with the other networks. Anything destined for a IP address in the 10.0.0.1-10.255.255.254 range will attempt to use em1 as if it was local, which the exception of addresses in the 10.31.96.0/22 which will leave via em3/em4.
Your solution is to either fix the em1 subnet/network so that it doesn't conflict with your other networks, or to add lots of routes.
Something like ip route add 10.31.45.0/24 via 10.31.96.1
might do what you want.