77

I have two network interfaces on a Linux PC, and I need to manually set the interface that a given process will use.

The program (Twinkle softphone) does not have a similar option, so I believe that it must be set externally.

How can I do it?

Edit: I'm not trying to make a server process bind to a specific interface, but rather to make a client program contact a server using a specific interface.

2
  • clients use bind/connect as well, look at the bind.c.txt documentation of how to force ircII (an irc-client programm) to a given ip: 'Example in bash to use your virtual IP as your outgoing sourceaddress for ircII: BIND_ADDR="your-virt-ip" LD_PRELOAD=./bind.so ircII'
    – akira
    Feb 3, 2011 at 13:34
  • I found a different approach here, I hope it's helpful (I sure hope the described kernel policy routing is enabled by default nowadays): kindlund.wordpress.com/2007/11/19/… Jan 28, 2012 at 23:52

7 Answers 7

54

you can replace code at runtime by the use of LD_PRELOAD (@windows you can use a similar technique called detours, quite fancy). what this does is to inform the dynamic linker to first load all libs into the process you want to run and then add some more ontop of it. you normally use it like this:

% LD_PRELOAD=./mylib.so ls

and by that you change what ls does.

for your problem i would try http://www.ryde.net/code/bind.c.txt, which you can use like:

% BIND_ADDR="ip_of_ethX" LD_PRELOAD=./bind.so twinkle

here is how you build it:

% wget http://www.ryde.net/code/bind.c.txt -O bind.c
% gcc -nostartfiles -fpic -shared bind.c -o bind.so -ldl -D_GNU_SOURCE

a longer howto is http://daniel-lange.com/archives/53-Binding-applications-to-a-specific-IP.html

similar hacks and tools:

5
  • 1
    Hi, this seems a really nice trick, but it does not work for me. I have two 3G modems that, when connected, open two interfaces (ppp0 and ppp1). If I try to force one of the two IPs, I always end up going out with the same interface (I see it because I have two instances of wireshark, one for each interface). I also removed the debug prints from bind.c and indeed I see that the "overloaded" library is loaded, so I don't know why it doesn't work. Feb 9, 2011 at 17:18
  • 4
    LD_PRELOAD is ignored if your effective UID is not the same as your real UID. Mar 24, 2011 at 17:59
  • The force_bind project by Catalin M. Boie supports ipv6
    – BurnsBA
    Jan 12, 2016 at 5:52
  • 1
    Works great but had to add #include <arpa/inet.h> for compilation to succeed.
    – anno
    Feb 11, 2019 at 23:12
  • 1
    This post is so old and ryde.net who had hosted bind.c is now dead. You can find that code here.
    – MortezaE
    Dec 1, 2021 at 9:21
42

ip netns can do this.

TL;DR: Create network namespaces, associate interfaces to them and then run "ip netns exec NAME cmd..."

Just check if your distro supports ip netns... (Backtrack 5r3 does not, whereas Kali does ;) )

IN MORE DETAILS:

#create netns
ip netns add myNamespace
#link iface to netns
ip link set eth0 netns myNamespace
#set ip address in namespace
ip netns exec myNamespace ifconfig eth0 192.168.0.10/24 up
#set loopback (may be needed by process run in this namespace)
ip netns exec myNamespace ifconfig lo 127.0.0.1/8 up
#set route in namespace
ip netns exec myNamespace route add default gw 192.168.0.1
#force firefox to run inside namespace (using eth0 as outgoing interface and the route)
ip netns exec myNamespace firefox

Why is this better than binding the ip via LD_PRELOAD? Because LD_PRELOAD does not control the route that the processes uses. It will use the first route.

And since it always uses the same route, it will default to the interface registered to the route.(which is not what we want)

9
  • 4
    don't do this on the remote server if eth0 is the public network interface..
    – ygrek
    Jul 21, 2014 at 7:46
  • 1
    the last line should be ip netns exec myNamespace firefox
    – meuh
    Jun 20, 2015 at 15:01
  • This is the easiest solution that I found., better than use the rt_tables files, wich can be a solution for incomming connections but not for the outgoing.
    – rfmoz
    Feb 15, 2017 at 10:58
  • 1
    Use "sudo ip netns del <namespace-name>" to remove the namespace when needed! Aug 8, 2017 at 14:13
  • 1
    @EduardoLucio it should be possible to execute it like: sudo ip netns exec myNamespace su -u someUser -c firefox
    – olivervbk
    Aug 9, 2017 at 15:32
4

Based on @olivervbk 's answer below is mine!

Run all commands as "root".

Use the command...

ip a

... to find out the name of the network interface you will want to use.

Run the commands below as the template...

ip netns add [INTERFACE_NAME]_ns
ip link set dev [INTERFACE_NAME] netns [INTERFACE_NAME]_ns
ip netns exec [INTERFACE_NAME]_ns ifconfig [INTERFACE_NAME] 10.1.1.10/24 up
ip netns exec [INTERFACE_NAME]_ns ifconfig lo 127.0.0.1/8 up
ip netns exec [INTERFACE_NAME]_ns route add default gw 10.1.1.1
ip netns exec [INTERFACE_NAME]_ns dhcpcd [INTERFACE_NAME]
ip netns exec [INTERFACE_NAME]_ns sudo -b -u [YOUR_USER] [APP_NAME] 2> /dev/null 1> /dev/null &
  • [INTERFACE_NAME] - Replace with the name of the chosen network interface.
  • [YOUR_USER] - Replace with your user name.
  • [APP_NAME] - Name of the application that will be executed in the namespace "[INTERFACE_NAME]_ns". Eg.: "firefox".

NOTE I: The "-b -u" flags in the "sudo" command allow the application to run using your user (not "root") and in the background releasing the terminal. The 2> /dev/null 1> /dev/null & snippet is to prevent outputs from "[APP_NAME]" being printed at the terminal.
NOTE II: The values of ip "10.1.1.10" and "10.1.1.1" are arbitrary.
NOTE III: To work for me I had to run the dhcpcd [INTERFACE_NAME] command.

To remove the namespace use...

ip netns del [INTERFACE_NAME]_ns

... or...

ip -all netns delete

... to remove any that exists.

4

Alternative I:

Using ld_preload to force the interface gateway https://github.com/Intika-Linux-Network/App-Route-Jail

Force an application to use a specific network interface

We need to find what gateway the network interface is using then force that gateway to our jailed application and thus force the application to bind to a specific network interface

  • How to find the interface gateway (there are many solution to find the gateway here are some commands that permit to find the used gateway)?
$ route
$ route -n
$ ip rule list
$ ip route show
$ netstat -rn
$ cat /etc/network/interfaces
$ cat /etc/sysconfig/network-scripts/ifcfg-eth0
$ traceroute www.google.com
$ ip route show 0.0.0.0/0 dev eth0

Per application gateway

  • Build App-Route-Jail
git clone https://github.com/Intika-Linux-Network/App-Route-Jail.git
cd Approute-Utils
chmod 755 make.sh
./make.sh
  • Add a route for the future marked packets (for the jailed application) in this example 192.168.1.1 is used as the forced gateway, this route rule will not affect other applications, this manipulation have to be done only once at the system boot for instance if you want to use this solution daily
ip rule add fwmark 10 table 100
ip route add default via 192.168.1.1 table 100
  • Start the application that you want to jail
MARK=10 LD_PRELOAD=./mark.so firefox
  • Testing the WAN IP address
MARK=10 LD_PRELOAD=./mark.so wget -qO- ifconfig.me

Alternative II:

Firejail https://firejail.wordpress.com/ can force an application to use a specific network, but the compatibility is limited.

firejail --dns=8.8.8.8 --net=eth0 --ip=192.168.1.1

Sources: Linuxhacks.org
Disclosure: I am the owner of Linuxhacks.org

1
  • Note that mark is not possible for normal users, you must run as root.
    – jornane
    Aug 9, 2019 at 12:54
3

I don't think it is possible to force a process to use a certain interface.

However, I think you might be able to play with ipchain/iptables and force that a certain port your process is listening at will only get packets coming through a particular interface.

Useful HOWTO: http://tldp.org/HOWTO/IPCHAINS-HOWTO.html

1
  • 7
    The two higher-voted posts prove otherwise.
    – Paul Gear
    Jul 6, 2016 at 7:36
1

Usually if a program has no option for setting listening interface, it's listening on ALL interfaces. (You can verify this with lsof -i).

Creating iptables firewall rules that drop incoming traffic pointed towards its ports on interfaces you don't want it to be visible on is the easiest thing to do.

-1

Why would you want a program to use an interface other than the one connected to the server to talk to that server? And if the system isn't using the interface connected to a server to talk to that server, it's a system-level (routing table) issue and has nothing to do with which process happens to want to talk to that server.

Different servers on IP networks have different IP addresses. The kernel should know which interface to use to reach a particular IP address based on the routing table. If you're trying to talk to two different servers that have the same IP address, the system will get confused (because, among other things, it only indexes the connections internally by destination address). You can make that work, but it's a system-level fix involving putting one server in a separate logical network that's only connected to the machine through software NAT.

So if they have different IP addresses, use routes to select the correct interface. If they have the same IP address, you need to use NAT so that they appear to have different IP addresses to the system.

2
  • 3
    Firstly, there may be multiple valid routes between the client & server, but with different characteristics suitable for different traffic types; e.g. UMTS (Cellular Data) may cost money but has greater range than WiFi, but both are slower than a fiber connection. If the upstream providers do source filtering (or NAT), you have no choice but to send out the 'right' interface. Secondly, influencing routing is not the only reason to select a source address. Even when both addresses are on the same interface it can be useful to control which is bound to when initiating connections, as the server
    – user139322
    Jun 11, 2012 at 5:58
  • One case is if you have different public IPs and you want to launch a new process in each one for outgoing connections.
    – rfmoz
    Feb 15, 2017 at 10:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .