1

I have a linux machine (Debian 10 based OS), with 3 hardware interfaces connected to the internet, 2 being USB modems: ifconfig gives ->

eth0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether b8:27:eb:95:a0:2c  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 14258  bytes 1613046 (1.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14258  bytes 1613046 (1.5 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ppp0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 10.199.25.78  netmask 255.255.255.255  destination 10.64.64.64
        ppp  txqueuelen 3  (Point-to-Point Protocol)
        RX packets 7  bytes 130 (130.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 181 (181.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ppp1: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 10.227.136.222  netmask 255.255.255.255  destination 10.64.64.65
        ppp  txqueuelen 3  (Point-to-Point Protocol)
        RX packets 7  bytes 130 (130.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 181 (181.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.105  netmask 255.255.255.0  broadcast 192.168.2.255
        inet6 fe80::e1b9:e62c:3140:bfc5  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:c0:f5:79  txqueuelen 1000  (Ethernet)
        RX packets 26548  bytes 5187998 (4.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20025  bytes 5171235 (4.9 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0 is the default interface here, when I try: curl --interface ppp1 ifconfig.me or curl --interface ppp0 ifconfig.me the request times out, with sudo, sudo curl --interface ppp1 ifconfig.me gives response but the equivalent for ppp0 times out, what are the right routing rules to add to be able to select the hardware interface to route through?

Actual routing rules:

default via 192.168.2.1 dev wlan0 proto dhcp src 192.168.2.105 metric 303 
10.64.64.64 dev ppp0 proto kernel scope link src 10.233.6.240 
10.64.64.65 dev ppp1 proto kernel scope link src 10.149.182.92 
192.168.2.0/24 dev wlan0 proto dhcp scope link src 192.168.2.105 metric 303 

ip rule gives:

0:  from all lookup local 
32766:  from all lookup main 
32767:  from all lookup default 

ip -4 route show table all :

default via 192.168.2.1 dev wlan0 
10.64.64.64 dev ppp0 proto kernel scope link src 10.235.137.107 
10.64.64.65 dev ppp1 proto kernel scope link src 10.121.55.130 
192.168.2.0/24 dev wlan0 proto kernel scope link src 192.168.2.101 
local 10.121.55.130 dev ppp1 table local proto kernel scope host src 10.121.55.130 
local 10.235.137.107 dev ppp0 table local proto kernel scope host src 10.235.137.107 
broadcast 127.0.0.0 dev lo table local proto kernel scope link src 127.0.0.1 
local 127.0.0.0/8 dev lo table local proto kernel scope host src 127.0.0.1 
local 127.0.0.1 dev lo table local proto kernel scope host src 127.0.0.1 
broadcast 127.255.255.255 dev lo table local proto kernel scope link src 127.0.0.1 
broadcast 192.168.2.0 dev wlan0 table local proto kernel scope link src 192.168.2.101 
local 192.168.2.101 dev wlan0 table local proto kernel scope host src 192.168.2.101 
broadcast 192.168.2.255 dev wlan0 table local proto kernel scope link src 192.168.2.101 

PS. after having rebooted, all the routing I tried was gone(as expected)

  • 1
    If you want to route packets based on any other criterion, you must use **Policy Based Routing**. This is quite configurable on Linux. The main information, you didn't provide is: how do you want to select the interfaces to use? Note: the interface `ppp0` seems to have a public IP address, while its peer (`10.64.64.64`) has a private IP address. That's unusual. – Piotr P. Karwasz Feb 14 '20 at 20:52
  • @PiotrP.Karwasz I didn't notice that public IP, I updated my description with the latest output which seems to be a local IP this time. What I want is to be able to use the interface I want at will, say for example I want to use ppp0 for curl, I could just do: curl --interface ppp0 ifconfig.co this request times out at the moment – Ernest Dujo Feb 14 '20 at 21:13
  • Can you add all routing tables to your question: `ip -4 route show table all` and the output of `ip rule`? – Piotr P. Karwasz Feb 15 '20 at 21:21

1 Answers1

1

What curl --interface <iface> http://example.com does is to connect to example.com, using interface's <iface> IP address as source. Otherwise routing proceeds as usual.

If you wish to route based on the packets source address, you need to add two routing tables (one for packets with source 10.199.25.78 and one for packets with source 10.227.136.222). Let's give the routing tables names, by adding:

200 ppp0
201 ppp1

to /etc/iproute2/rt_tables and fill them with default routes for packets from those interfaces:

ip route add default dev ppp0 via 10.64.64.64 table ppp0
ip route add default dev ppp1 via 10.64.64.65 table ppp1

Now, all you need to do is to add two rules which will select table ppp0 or ppp1 according to the source address:

ip rule add from 10.199.25.78 table ppp0
ip rule add from 10.227.136.222 table ppp1

Edit: I dug deeper into curl's --interface ppp0 option. It can work in two ways (cf. connect.c):

  • if the process has the CAP_NET_RAW capability (like when you are root) it binds to the given interface (through SO_BINDTODEVICE) and all routes that don't use the ppp0 interface are ignored.
  • if the process is unprivileged, curl binds to the IP address of the ppp0 interface (10.199.25.78) and routing proceeds as usual.
Piotr P. Karwasz
  • 5,748
  • 2
  • 11
  • 21
  • I did exactly that and it didn't change anything: curl --interface ppp1 ifconfig.co only works with sudo, and for ppp0 it doesn't work (times out) with or without sudo – Ernest Dujo Feb 15 '20 at 00:07
  • I added some details on **curl**'s `--interface` option. You should run curl with `-v` and check the connection errors you get. Most probably they are `No route to host` and `No route to network`. – Piotr P. Karwasz Feb 15 '20 at 21:19
  • I fixed the problem with ppp0 (it was wvdial config mistake) now they both work the same way but can't run the curl command without sudo – Ernest Dujo Feb 16 '20 at 08:04
  • 1
    well I think I found the issue ... after what you suggested, it is needed to flush the cache (like this: ip route flush cache) – Ernest Dujo Feb 17 '20 at 06:34