I am trying to get a VPN running. I'd like programs to explicitly request the interface rather than route ALL traffic, like with curl --interface.

curl --interface ppp0 ip.bsd-unix.net should send through the VPN, but somehow, using tcpdump or iftop, I can see traffic going through eth0 instead, even when the source IP is Here's my ip route show:

default via 149.x.y.z dev eth0 dev ppp0  proto kernel  scope link  src
149.x.y.128/25 dev eth0  proto kernel  scope link  src 149.x.y.172

Some IPs obscured. The second one is added by xl2tp when it starts and the ppp0 interface is created. 149.etc is my LAN, and 10.etc is my VPN.

Also, when I ping -I ppp0, I can see ppp0 activity, and I get replies with higher ms which would suggest they're going through the VPN.

  • This is pretty tricky - I have not tried it, hence a comment not an answer, but you probably need to set up 2 route tables for policy based routing, then use iptables with a module like nfacct or owner (and ensure curl runs with the same user) - marking those packets for routing down the alternative connection. If you know the specific site you want to access, and routing for that site does not need to split you can simply inject a static route into the vpn table, either in the VPN setup (depending on your VPN client) or by adding a route manually. – davidgo Sep 18 '15 at 5:51
  • @davidgo yikes... what's the point of an application binding to an interface if it's just going to go through the default? – Hypershadsy Sep 18 '15 at 6:00
  • 2
    I think you misunderstand me - there are 2 solutions - the simpler one would be to add a static route across the VPN for only the website(s) you are interested in getting. If, however, you need programs to access different paths to the internet (ie some over the VPN some not) then you will need to set up 2 routing tables, and use policy based routing to make the routing for that application work differently. – davidgo Sep 18 '15 at 6:06

I sort of assumed that if a source IP of a packet matches that of an interface, it would use said interface. And if that wasn't inherent IP behavior, then my second route would have made that happen: the src part of the route was a red herring for me.

So, my programs bind to the ppp0 address, which sets their source IP, right? I did what @davidgo said and made a separate routing table...

echo 200 custom | sudo tee -a /etc/iproute2/rt_tables

...then added a rule to use the custom table for packets that have that source IP...

sudo ip rule add from lookup custom

...and added a rule to the custom table to use ppp0 for any traffic it gets, going through ppp0's gateway.

sudo ip route add default via dev ppp0 table custom

curl ip.bsd-unix.net gives me my home IP and curl --interface ppp0 ip.bsd-unix.net gives me my VPN's remote IP. It works!

Still, I'm interested as to why ping went through ppp0 correctly all along.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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