The problem is,
1. you want most outbound traffic not to go through VPN
2. but inbound connections and their reply traffic must go through VPN
1 is for performance, 2 is for necessity
You can't just apply rule 1 unconditionally, because anyone connecting to the public IP address expects replies to come from this public IP address. The server, that is reached via DNAT I guess, does not know this, and sends its replies directly, and they go their usual way bypassing VPN and DNAT.
There is no simple openvpn-only configuration that can achieve this.
I had this problem before, I hat cheap NAT routers with forced NAT inside the home network, but wanted a server to be reachable from outside the NAT router.
Server and VPN endpoint on the same box, the solution was (on the server box, vtun syntax):
Code: Select all
ifconfig "%% 10.X.Y.2 pointopoint 10.X.Y.1 mtu 1450"; # necessary part of the vtun config
ip "rule add priority 32700 from 10.X.Y.2 table 240";
ip "route add default via 10.X.Y.1 table 240";
ip "route flush cache";
This takes advantage of server and vpn endpoint running on the same box. Whenever the server is contacted, its replies come from the tun interface with address 10.X.Y.2. This activates a special routing table, I chose 240, where everything gets routed through VPN, according to rule 2. above. Everything else uses the normal routing table, following rule 1. above.
Now if the server and the vpn are running on different boxes, this cannot be used. Still, a similar configuration is possible. The configuration must be on the VPN box. The "ip route"... lines can stay the same. (I have never tested or tried this)
The "ip rule" lines are different. They identify the traffic that is replies from the world-reachable servers and must therefore go through VPN.
If you don't mind everything from the server box to go through VPN, you can use "ip rule add ... from ...". This identifies traffic based on the source IP address (of the server).
To optimize more, you can use "ip rule add ... fwmark ..." and then add iptables rules to identify traffic based on source IP and source port (of the server). For a webserver, the source of its replies may be "-p tcp -s www --sport https". www must resolve to (or be replaced by) the webserver's IP address. Continue with e.g. "-j MARK --set-mark 123" on the iptables line.
Do not set the mark for the wrong ports or the wrong direction. Only the servers' reply packets must be marked. They go in the opposite direction of what is usually described in iptables filter rules.
Then, leave out redirect-private from openvpn config, and use the "ip rule" and "ip route" commands instead.
SNAT, as mentioned, might work too, but I avoided that when faced with the problem. I think in that case the traffic should SNAT or MASQUERADE, on the VPN endpoint, everything going _to_ the world-reachable servers. This rule should look something like "-p tcp -d www --dport https". Or just masquerade everything that is coming from tun (this may have undesirable side effects if the VPN has more purposes). However, I think this means the server never knows who is contacting it. Only the iptables system does.