My situation is that I want all my outgoing connections from my Debian server to pass through a commercial VPN service I've subscribed to, but I still want to run public-accessible services on this server, and not have them pass through the VPN.

That is, I have BIND9 (authoritative), SMTP, Apache, SSH etc running on this server, and I want incoming connections to be able to reach these services without using the VPN.

To clarify, I only want to use the VPN to hide my outgoing connections, but still be able to answer requests on my real IP for anything that has come in that way.

To make matters even more complicated—I use BIND as both an authoritative server for my domain (on the public internet), and I also have recursion turned on so I can use it as the resolver for my local network (private ip range). Is it possible to VPN the outgoing DNS connections from BIND but still allow incoming requests to reach the authoritative bit?

I gather this has something to do with iproute2, but I can't figure out the correct config.

I'm on Debian 6.0.7. The VPN is OpenVPN.


You should use policy routing to implement this. The rules won't be too complicated.

Your (main) default route should point toward the VPN interface. You'll probably use OpenVPN's --redirect-gateway def1 option to have this managed automatically for you when the VPN comes up. It makes OpenVPN override the system default route with a couple of /1 routes that have the same effect and makes sure OpenVPN itself can still reach its remote peer in the normal way without the obvious routing loop.

This default route will make locally originated traffic go out through the VPN and it will also make replies to traffic that came in through the VPN go out the VPN.

Now you want to override this with a policy rule for packets that are associated with connections that came in on the non-VPN interface. You want to make those packets go back out through the non-VPN interface.

The following should accomplish this by (1) matching packets that have the non-VPN public IP address as a source address and asking those to be routed via a different routing table, (2) in that routing table, sending everything to your original (non-VPN) default route.

ip route add table 42 default via X.Y.Z.W
ip rule add from A.B.C.D/32 table 42

A.B.C.D should be your public (non-VPN) IP address, and X.Y.Z.W should be your original system default route (through your ISP, not through your VPN).

The similar config for IPv6 traffic is left as an exercise for you :-)

| improve this answer | |
  • Nice! This did the trick. Thanks for your help! – lloydsmart Feb 28 '13 at 17:58
  • Follow-up question: Is there any way to configure my SMTP server (Postfix in this case) to use the non-VPN route? I mean for both incoming and outgoing. Perhaps a way to make all port-25 traffic go non-VPN? Thanks! – lloydsmart Feb 28 '13 at 18:03
  • I think it might do that already if you simply make Postfix bind to the non-VPN address instead of to the wildcard (default) address. That is, try changing smtp inet in /etc/postfix/master.cf to A.B.C.D:smtp inet. – Celada Feb 28 '13 at 18:20
  • Thanks - that was the basic idea, but as it turns out the actual configuration for getting Postfix to bind to the correct address is in main.cf, using the option "smtp_bind_address = A.B.C.D". Props to this page for the answer: faqforge.com/tag/smtp_bind_address – lloydsmart Feb 28 '13 at 19:45
  • I tried these instructions on a machine that is behind a router on a LAN. For A.B.C.D, I used the machine's LAN IP (not the external IP) and for X.Y.Z.W, I used the router's address. This worked for external connections. I could now ssh to my machine from the outside world, and connections originating from my machine would go through the VPN. However, I am now unable to connect from another computer on my network to the machine via ssh (but I can if going through the external internet). How do the instructions need to be modified to work on a machine behind a network router? – dannyadam Mar 22 '14 at 20:43

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.