Specify a network interface with curl

4

2

For some reasons, i want to code a proxy server that route its requests through its wifi interface instead of ethernet (which is the default route on the OS level). I know i could do that by fiddling with os routes but i would prefer to do it directly in curl for instance.

I have read that you actually can choose the network interface a socket will use with the --interface option but it doesn't seem to work for me :(

I tried the following:

curl --interface wlp2s0 google.com

But i only get ETIMEDOUT errors.. On the other hand if i do

curl --interface enp0s20 google.com

it works as expected..

Does anyone has a clue what is going on ?

cp2587

Posted 2016-11-22T14:19:54.533

Reputation: 43

ETIMEDOUT means the request was sent - but the server did not respond.. I just tried, and this worked for me no problem. – Matt Clark – 2016-11-22T15:21:56.820

Answers

4

As correctly pointed out by Matt Clark, ETIMEDOUT means you could not reach the specified site, for whichever reason.

But let me also point out you misinterpret the meaning of the --interface option. What it means is: if I have two or more interfaces, use the IP address of the interface that I specify, rather than the default one". But as for routing, i.e., deciding which interface the request is routed thru, it is the kernel that decides, not your command, according to the routing table you have: if the routing table specifies a default gateway over eth0, for instance, the curl request will be routed thru it even though you have specified --interface wlan0.

Let's check this: I have set up two tcpdump sessions, one on my ethernet device (usb0), one on the wifi device (wlan0); both are connected, but the routing table has the gateway over usb0. Now, in a third shell, I send two curl requests, as follows:

$ date && curl --interface usb0 146.255.36.1/plain
mar 22 nov 2016, 18.44.21, CET
<!-- pageok -->
<!-- managed by puppet -->
<html>
<pre>pageok</pre>
</html>
$ date && curl --interface wlan0 146.255.36.1/plain
mar 22 nov 2016, 18.44.44, CET
<!-- pageok -->
<!-- managed by puppet -->
<html>
<pre>pageok</pre>
</html>

and this is what my two tcpdump sessions record: the one on wifi

# tcpdump -i wlan0 -n host 146.255.36.1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wlan0, link-type EN10MB (Ethernet), capture size 262144 bytes

and the one on ethernet

# tcpdump -i usb0 -n host 146.255.36.1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on usb0, link-type EN10MB (Ethernet), capture size 262144 bytes
18:44:21.118505 IP 192.168.73.74.52601 > 146.255.36.1.80: Flags [S], seq 2178801514, win 29200, options [mss 1460,sackOK,TS val 10527374 ecr 0,nop,wscale 7], length 0
18:44:21.147291 IP 146.255.36.1.80 > 192.168.73.74.52601: Flags [S.], seq 95036242, ack 2178801515, win 14480, options [mss 1460,nop,nop,TS val 500605800 ecr 10527374,nop,wscale 8], length 0
18:44:21.147322 IP 192.168.73.74.52601 > 146.255.36.1.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 10527381 ecr 500605800], length 0
18:44:21.147375 IP 192.168.73.74.52601 > 146.255.36.1.80: Flags [P.], seq 1:82, ack 1, win 229, options [nop,nop,TS val 10527381 ecr 500605800], length 81: HTTP: GET /plain HTTP/1.1
18:44:21.175829 IP 146.255.36.1.80 > 192.168.73.74.52601: Flags [.], ack 82, win 57, options [nop,nop,TS val 500605829 ecr 10527381], length 0
18:44:21.178222 IP 146.255.36.1.80 > 192.168.73.74.52601: Flags [P.], seq 1:285, ack 82, win 57, options [nop,nop,TS val 500605832 ecr 10527381], length 284: HTTP: HTTP/1.1 200 OK
18:44:21.178236 IP 192.168.73.74.52601 > 146.255.36.1.80: Flags [.], ack 285, win 237, options [nop,nop,TS val 10527389 ecr 500605832], length 0
18:44:21.178321 IP 192.168.73.74.52601 > 146.255.36.1.80: Flags [F.], seq 82, ack 285, win 237, options [nop,nop,TS val 10527389 ecr 500605832], length 0
18:44:21.206618 IP 146.255.36.1.80 > 192.168.73.74.52601: Flags [F.], seq 285, ack 83, win 57, options [nop,nop,TS val 500605860 ecr 10527389], length 0
18:44:21.206642 IP 192.168.73.74.52601 > 146.255.36.1.80: Flags [.], ack 286, win 237, options [nop,nop,TS val 10527396 ecr 500605860], length 0
18:44:44.284057 IP 192.168.73.45.41804 > 146.255.36.1.80: Flags [S], seq 2817430695, win 29200, options [mss 1460,sackOK,TS val 10533165 ecr 0,nop,wscale 7], length 0
18:44:44.313090 IP 146.255.36.1.80 > 192.168.73.45.41804: Flags [S.], seq 3652186052, ack 2817430696, win 14480, options [mss 1460,nop,nop,TS val 500628966 ecr 10533165,nop,wscale 8], length 0
18:44:44.313117 IP 192.168.73.45.41804 > 146.255.36.1.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 10533172 ecr 500628966], length 0
18:44:44.313152 IP 192.168.73.45.41804 > 146.255.36.1.80: Flags [P.], seq 1:82, ack 1, win 229, options [nop,nop,TS val 10533172 ecr 500628966], length 81: HTTP: GET /plain HTTP/1.1
18:44:44.342243 IP 146.255.36.1.80 > 192.168.73.45.41804: Flags [.], ack 82, win 57, options [nop,nop,TS val 500628995 ecr 10533172], length 0
18:44:44.343076 IP 146.255.36.1.80 > 192.168.73.45.41804: Flags [P.], seq 1:285, ack 82, win 57, options [nop,nop,TS val 500628996 ecr 10533172], length 284: HTTP: HTTP/1.1 200 OK
18:44:44.343090 IP 192.168.73.45.41804 > 146.255.36.1.80: Flags [.], ack 285, win 237, options [nop,nop,TS val 10533180 ecr 500628996], length 0
18:44:44.343168 IP 192.168.73.45.41804 > 146.255.36.1.80: Flags [F.], seq 82, ack 285, win 237, options [nop,nop,TS val 10533180 ecr 500628996], length 0
18:44:44.372262 IP 146.255.36.1.80 > 192.168.73.45.41804: Flags [F.], seq 285, ack 83, win 57, options [nop,nop,TS val 500629025 ecr 10533180], length 0
18:44:44.372302 IP 192.168.73.45.41804 > 146.255.36.1.80: Flags [.], ack 286, win 237, options [nop,nop,TS val 10533187 ecr 500629025], length 0
^C
20 packets captured
20 packets received by filter
0 packets dropped by kernel

Notice:

  1. The time stamps, corresponding to each request,

  2. the different LAN Ip addresses, 192.168.73.74 for ethernet and 192.168.73.45 for wifi.

  3. That all packets are detected by the tcpdump session on the ethernet interface, irrespective of my choice of --interface.

You may ask: so when is the --interface option useful? When you have two (or more) routing tables, one per each interface, each with its own gateway. Then --interface allows you to specify which interface is used to reach curl's destination. If you want to know more about how to setup up policy routing, you may read here.

MariusMatutiae

Posted 2016-11-22T14:19:54.533

Reputation: 41 321

1Thanks for the comprehensive answer. I really am clueless when it comes to networking. Your link is exactly what i was looking for. – cp2587 – 2016-11-28T10:34:14.630

1@cp2587 I really am clueless when it comes to networking: do not worry, we have all been there. :-) – MariusMatutiae – 2016-11-28T10:55:15.070