A tool to change the default bind interface for a given command?

This is somehow related to Change interface for doing a whois

The differece is that I'd like to know if it's possible to specify the default interface only for a specific program - not system-wide. For example: let's say my server has several IPs. I want to run program X (say wget) and I want it to use one of my IPs as the source address. It would look like this:

theprogram --use-interface=1.2.3.4 wget google.com

and wget would use my IP 1.2.3.4 to connect to google.com and fetch the html. Is it possible?


Solution 1:

Folks here have some suggested some workable alternatives for what you want to do. Routing and source NAT can help out, but may or may not solve the problem you're trying to solve.

You can do exactly what you've asked if you're willing to much about a little. You can use the magic of function interposition via LD_PRELOAD to wrap the bind() system call with code of your choice.

The follow pages have information that provides more details about this solution:

  • http://www.semicomplete.com/blog/tags/ld_preload
  • http://manpages.ubuntu.com/manpages/hardy/man1/authbind.1.html
  • http://daniel-lange.com/software/bindhack.c

This will only work as long as the code you're running is not SUID (for security reasons SUID/SGID programs cannot be modified using LD_PRELOAD).

Solution 2:

With wget you can use --bind-address

Otherwise I think you either need to specify a route for the destination IP address, or look in the program you're trying to use if it has a way of deciding the bind/source address.

Solution 3:

Many, but by no means all, programs have the option to bind to a specific address. Some, like wget (as pointed out by fbh) have a command-line option to specify which address to bind to. Many more server-like programs, such as apache and squid, control this in their configuration file. It's always going to be program-specific.

For programs that don't support binding to a specific address, your options may be more limited, depending on what sort of program you're dealing with.

For a server program (that accepts incoming connections), you can usually accomplish the same thing by listening on all addresses (which is usually the default), then using iptables, or your external router, to forewall the other addresses.

The trickier thing is for outbound connections. Here you'll need something more like described in the answer you linked to in your question. The problem with that is its dependent on the destination address, not the source program.

You may be able to accomplish what you want with iptables and a SNAT rule.

iptables -A POSTROUTING -p tcp --dport 80 -j SNAT --to-source 1.2.3.4

This iptables rule (which I have not tested), ought to change the source address on any traffic going to port 80. If you need the same behavior for both tcp and udp traffic, you'd need to create two rules, replacing '-p tcp' with '-p udp' in the second one.