Debian – Incoming/Outgoing seperation for VPN

debiandnsnetworkingvpn

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.

Best Answer

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 :-)

Related Question