There's a simple solution - Daniel Ryde wrote an LD_PRELOAD "shim" library (bind.c) that modifies bind behaviour, for this purpose. Check out this tutorial:
https://www.x4b.net/kb/BindProcessToIPonLinux
Given there is effectively a default bind address for applications (see your routing table), it is in my opinion superbly strange that there usually is no standard way (as in "distribution package code") to override that default interface, yes; on the system level, for a particular set of applications.
Some programs do have command line options to listen to the interface of your choice, which is all fine and well.
My default route goes via a VPN proxy (surely a pretty common scenario). A good default for outgoing connections, this tunnel does not support inbound connections from the internet very well. Therefore I need to force server-oriented programs A, B, and C to bind to some other IP (main ISP provided address). And client-oriented program D, I want to use my public interface for different reasons.
The above library works well, for this purpose!
A solution is:
- Create a new user
- Header-mangle ALL the packets of that particular user
- Run the programs as that user, ONLY to "effectively bind" to the desired interface seems like... an ugly hack, in comparison.
Alternatively:
- Create new user SuperFluous
- Make SuperFluous use different routing table
- Run A, B, C as user SuperFluous; Still not good enough! I want to run "my" servers as "me" (I might not even have privileges to create new users and routing policies).
LISTEN_TO=$THIS_INTERFACE Command; # <- It should be that simple.