I’m looking to leverage a Linux device as a default gateway, routing off-host traffic over an OpenVPN connection without impacting the hosts route the internet. I don’t want traffic for the host to egress via the VPN, only that traffic that is coming from other devices.

I have successfully configured the NATing, have the traffic from devices using my host as a default gateway egress using whatever the default route is on the host (e.g. if the VPN is open, it goes via the VPN, if it’s not, goes via the hosts normal internet connection, with the host as an additional hop in traceroute)

However, I cannot successfully configure this so that the OpenVPN connection doesn’t impact the hosts networking and have the host route gateway traffic via the OpenVPN interface

Things I have done: - Configured IP forwarding & verified it works - Been able to stop OpenVPN updating the default route on the host with route-nopull and pull-filter ignore redirect-gateway

I’m guessing that there is either a dynamic part of this (pull the route information from the open vpn config), or hopefully a ‘no, really, just apply these routes for the NAT traffic’ flag/setting.

Network config:

  • Internet access is via a boring router with no fancy capabilities
  • Linux device (Raspberry Pi) wired to the network, running ufw, iptables, openvpn
  • Other device(s) wired, some of which I want to manually set their default gateway to the Linux device
  • Subnet is
  • Why do you want to NAT on the VPN? One of the great things about using a VPN is that you do not need to use NAT. Certainly, using a private network needs NAT to go out normally to the public Internet, but unless there is something you are not explaining, the VPN should not need NAT, only routing. – Ron Maupin Feb 9 at 23:42
  • I would see NAT useful in case the VPN clients is connecting to VPN server to use it to communicate not only with internal resources. In that case NAT is needed for the traffic leaving the environment in direction to outside. This can be result of "use as default gateway / route all the traffic from client through the VPN tunnel". – Kamil J Feb 10 at 0:05
  • @KamilJ, the router to the public Internet can NAT. NAT is something to be avoided if at all possible. Use NAT on a private to public address change at the Internet edge, or if there is overlapping network addressing. Other than that, simply use routing between networks. – Ron Maupin Feb 10 at 1:13
  • The devices I wish to egress to the internet via the VPN are not capable of running a VPN themselves, hence this Rube Goldberg solution. – Dominic Hopton Feb 10 at 2:28
  • I believe I need NAT because the devices on the intranet do not have public internet addresses, so can’t directly route to the internet, and there are multiple devices, so it can’t perform a 1:1 address rewrite. – Dominic Hopton Feb 10 at 2:30

Not sitting at a computer right now, but here is my general idea:

First of:

Let the Raspberry have a static ip address with its default gateway is the boring router.

If the boring router is acting as the DHCP server, then deactivate it! Let the Raspberry be the DHCP server instead (or another host on the network).

Let the DHCP server broadcast the Raspberry device as the default router for the network instead of the boring router.

Traceroute will then be:

Host -> Raspberry -> Boring router-> Internet

Now here comes the magic.

If you want to divert traffic to go over the VPN instead of the default way out of the house, then you should use source based routing on the Raspberry.

Traceroute for those specific host that goes via VPN would then be:

Host -> Raspberry -> Openvpn tunnel -> Internet.

For this to work ip forwarding has to be enabled on the Raspberry and on the VPN server.

I will expand on the answer when I get home from work. :-)


A quick recap about source based routing:

I am using this page as a base for my solution.

The idea is that you determine how traffic is forwarded depending on where the traffic originated from.

The default routing table in Linux is called main. You can see the names of all your routing tables with the command ip rule show.

It should give this output as default:

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

The Raspberry will go through all the matching rules and forward the package using the first rule that matches.

Since the table main contains a rule saying something like:

default via <boring routers ip address> dev eth0

It will then forward all traffic to the boring router in order to reach the Internet.

But here comes the kicker: You can make a seperate routing table for all the host you want to sent via VPN connection. For simplicity sake lets call this routing table openvpn.

You have to change /etc/iproute2/rt_tables so it look something like this:

# reserved values
255     local
254     main
253     default
200     openvpn # <-- Note THIS line!
0       unspec
# local
#1      inr.ruhep

Lets say you want to divert another machine with the IP address through the VPN you would then make a rule saying shomething like:

ip rule add from table openvpn

If we assume the ip address of your VPN gateway inside the tunnel is you could then use the following command to set the default route:

ip route add default via table openvpn dev tun0

If all hosts on your network uses the Raspberry as their gateway then all their traffic will be forwarded to the router except if the traffic originates from In that case it will be forwarded over the VPN link.

Is this what you are searching for? :-)

| improve this answer | |
  • I've left DHCP on since on the devices I'm fiddling with, I can manually configure the IP, subnet, DNS and gateway. I've tried searching for source based routing, and there's quite a lot, and I'm struggling to find the 'tl;dr' / the from-first-principles tutorial – Dominic Hopton Feb 13 at 17:09
  • 1
    Updated my answer with an example of source based routing. You can try changing a test host to use the raspberry as a gateway to see what happens when source based routing is activated. – Lasse Michael Mølgaard Feb 13 at 18:00
  • This seems to be ~ working: 1. I did have to do iptables-SNAT config 2. When the VPN is down, some sort of 'default' rules come into play, and packets are routed out via the 'boring' route, rather than getting packet dropped. – Dominic Hopton Feb 16 at 22:44
  • Well you add or remove source based routing based on whether or not the VPN is up or down. So when VPN is down all traffic gets routed over the router, but changed automatically when VPN goes up. – Lasse Michael Mølgaard Feb 16 at 22:53
  • Yes -- although I was kinda hoping to not have to do that, since I was still seeing routing with no custom routes (just IP Forwarding). But after I added the right magic to turn that on/off in the openvpn up/down scripts, it's working well, now. – Dominic Hopton Feb 18 at 17:07

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.