On Ubuntu 14.04 x86-64 I have a wireless broadband connection and a USB tethered one (it's on 4G, not the same wireless):

route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface         UG    0      0        0 usb0   U     9      0        0 wlan1   U     1      0        0 usb0

I have then the following also:



usb0      Link encap:Ethernet  HWaddr 02:36:2c:04:05:7c  
          inet addr:  Bcast:  Mask:
          inet6 addr: fe80::36:2cff:fe04:57c/64 Scope:Link
          RX packets:3367 errors:1 dropped:0 overruns:0 frame:1
          TX packets:3669 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:2434689 (2.4 MB)  TX bytes:637911 (637.9 KB)

wlan1     Link encap:Ethernet  HWaddr 14:cc:20:75:e1:8d  
          inet addr:  Bcast:  Mask:
          inet6 addr: fe80::16cc:20ff:fe75:e18d/64 Scope:Link
          RX packets:3806 errors:0 dropped:0 overruns:0 frame:0
          TX packets:4110 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:2283536 (2.2 MB)  TX bytes:583794 (583.7 KB)

It all looks like it's supposed to be working as intended (i.e. both network connections are up, my machine got 2 IPs, ...).
Then I wanted to use the bind shim to force processes on one connection (or another) and those only work when I specify the IP of the default connection/gateway.
The following works (please note this is on the tethered USB - 4G):

BIND_ADDR="" LD_PRELOAD=./bind.so chromium-browser

And this doesn't (my broadband):

BIND_ADDR="" LD_PRELOAD=./bind.so chromium-browser

Of course, when I unplug the USB phone, wlan0 magically starts working again...

What am I doing wrong? Any idea?

  • From the looks of it, your .0.0 route doesn't work when you're bound to the 42.0 network because your default route points to a gateway at 42.129, which you can't access on the other network. You need a route for on, probably whatever your router is. – Xyon Dec 26 '15 at 15:47
  • @Xyon How can I verify that? Even if I use the bind shim? That LD_PRELOAD trick is supposed to force all binds and connect to – Emanuele Dec 26 '15 at 15:50
  • Well it not pulling external sites suggests that it is working, because otherwise you'd get connectivity through the other link. Your broadband network isn't completely set up, I don't know how bind is supposed to handle that situation but the kernel doesn't know where to send your packets. – Xyon Dec 26 '15 at 15:52
  • @Xyon I guess I'll have to write a simple test executable to see what errors the kernel is returning when creating TCP/UDP connections? – Emanuele Dec 26 '15 at 15:53
  • No, I wouldn't go that far. What you're trying to do needs a second route table, bound to your other interface, so the system understands how to handle requests from each interface. See thomas-krenn.com/en/wiki/Two_Default_Gateways_on_One_System for a good resource on the concept. – Xyon Dec 26 '15 at 15:55

The reason why your bind does not work has nothing to with bind, a trick I use too, and everything to do with the fact that you have only one default gateway, on the usb0 NIC, while you should have one on either NIC, otherwise connection to WAN sites from wlan0 will not be routed.

Linux allows the existence of multiple gateways (one per interface, virtual or not), under the regimen of policy-based routing. What you need to do is to have two separate routing tables, one for usb0 and one for wlan0, and a rule telling the kernel which one to use; then binding an application to either interface will allow you to reach WAN sites.

You handle two routing tables as follows: First, create two tables (Replace and with sensible names, same with IP1, DEV1, and so on):

echo 200 <NAME1> >> /etc/iproute2/rt_tables
echo 201 <NAME2> >> /etc/iproute2/rt_tables

Add a gateway to each routing table (if needed):

ip route add <NET1> dev <DEV1> src <SRC1> table <NAME1>
ip route add <NET2> dev <DEV2> src <SRC2> table <NAME2>

Then a default route:

ip route add default via <IP1> table <NAME1>
ip route add default via <IP2> table <NAME2>

Then the rules to select the route table based on the source address:

ip rule add from <IP1> table <NAME1>
ip rule add from <IP2> table <NAME2>

Now you can bind application to either interface.

  • Thanks, this looks like the answer I was looking for. Do you know if there's a way to do it programmatically? Are the changes persistent? – Emanuele Dec 26 '15 at 16:27
  • @Emanuele No, these changes are not persistent. The easiest thing is to put all of the above in an executable file, call it my_config, then, in /etc/network/interfaces, use auto usb0; interface usb0 inet dhcp; post-up /path/to/my_config, and raise interfaces with ifup/ifdown usb0/wlan0. – MariusMatutiae Dec 26 '15 at 17:17
  • Actually my next question would have been what is the one liner command I can use to setup a temporary default gateway for a given IP address. Again, I don't want a static configuration, more than happy to input the one liner command each time. Thanks! – Emanuele Dec 26 '15 at 18:53
  • @Emanuele Put the above commands into an executable file, you have your one liner; to go back to the previous situation, bring don the two interfaces, then back up, and erase the two lines in the /etc/iproute2/rt_tables file. – MariusMatutiae Dec 26 '15 at 19:15
  • Would ip route add dev wlan1 (or ip route add dev do the trick of temporarily route all the packets for this subnet through that gateway? – Emanuele Dec 26 '15 at 22:29

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.