What's new

Port Forwarding when Connected to VPN

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

Saturnine

New Around Here
Hello,

I should start out by saying I'm a network engineer. I should be able to work this out myself but to my discredit, I'm struggling a bit...

My 86U is permanently connected to a VPN service. In addition, I've set up a port-forward to a local web server on my LAN.

When the VPN is disconnected, the port forwarding works perfectly and I'm able to access the web server from a remote location. Once I connect the VPN, this stops working.

I have DDNS set up so that the 'real' external IP of my router is always placed in DNS. It would be pointless to use the VPN IP since my provider doesn't support port forwarding anyway.

What I believe is happening is that my HTTP requests are reaching the web server, which is responding however the router then routes the return packets through the VPN tunnel instead of directly out of the WAN interface. This asymmetry is causing the connection to fail.

In a work environment I would get around this by setting up some form of SNAT from the router to the webserver but I can't seem to figure out how to do that on the 86U.

Has anybody got any ideas?

Thanks.
 
What I believe is happening is that my HTTP requests are reaching the web server, which is responding however the router then routes the return packets through the VPN tunnel instead of directly out of the WAN interface. This asymmetry is causing the connection to fail.
Your assumption is correct. You need to setup the policy based routing in the VPN to exclude the web server.
 
Hi Colin,

I've already done a bit of that. My PBR is that the router itself goes straight out. Anything on the LAN subnet gets routed down the tunnel.

The problem is that the return traffic from the web server will always be sourced from (in this case) 10.0.0.20. It will always be destined to a public IP address, so policy-based routing doesn't help us much here.

What would help is if I could SNAT the incoming requests. That way, the return traffic would be destined for a known IP address regardless of where the request came from. Only then can I use PBR to 'override' the VPN traffic and sent it back out through the WAN.

Since the router doesn't seem to support SNAT through the GUI, I'm now looking into using iptables to do it. Any advice anybody could give that might get me moving in the right direction would be appreciated.
 
The problem is that the return traffic from the web server will always be sourced from (in this case) 10.0.0.20. It will always be destined to a public IP address, so policy-based routing doesn't help us much here.
Sorry, I don't see what the problem is. Just setup a rule that says everything from 10.0.0.20 goes out through the WAN.
 
The problem with that suggestion is that any traffic generated by the web server will go out through the WAN, and not the VPN. That isn't what I want. Responses to clients should go out via the WAN but traffic originating from the server should go through the VPN.
 
I got it working!

I didn't use SNAT in the end.

Instead, packets coming into the router from a source port of 443 (which will only ever be return traffic) are marked with '10'. The marked packets are then diverted to use the main routing table, rather than the ovpnc1 table.

iptables -t mangle -A PREROUTING -p tcp -m multiport --sports 443 -j MARK --set-mark 10
ip route add table 100 default via 192.168.0.1
ip rule add fwmark 10 table 100
ip route flush cache

Now I just need to get this in a script, but I'm sure there's plenty of documentation on that.
 
Last edited:
I finally got this working just as I wanted. Unfortunately the script I posted above didn't quite work as intended, as ALL packets (including those coming in from the Internet) were marked and thus I lost access to Internet servers on port 443. Oops.

Here is my final configuration, which I leave here in case it'll help others. Most likely, I'll factory reset my router at some point and have to come back here to figure out how I ever got it working.

First of all, I created a script named openvpn-event in /jffs/scripts/ and run chmod 0777 openvpn-event.

Code:
#!/bin/sh

scr_name="$(basename $0)[$$]"

case "$1" in
    "tun11")
        vpn_name="client1"
        ;;
    "tun12")
        vpn_name="client2"
        ;;
    "tun13")
        vpn_name="client3"
        ;;
    "tun14")
        vpn_name="client4"
        ;;
    "tun15")
        vpn_name="client5"
        ;;
    "tun21")
        vpn_name="server1"
        ;;
    "tun22")
        vpn_name="server2"
        ;;
    *)
        vpn_name=""
        ;;
esac

# Call appropriate script based on script_type
vpn_script_name="vpn$vpn_name-$script_type"

if [[ -f "/jffs/scripts/$vpn_script_name" ]] ; then
    echo "Script" $vpn_scipt_name" running.
    sh /jffs/scripts/$vpn_script_name $*
else
    echo "Script not defined for event: "$vpn_script_name | logger -t $scr_name
    exit 0                                                                  
fi

I didn't create the above script. It was posted here in this forum. Essentially, it finds out which VPN Client/Server change caused the script to run, and then calls a script named 'vpnvpnname-script-type'

In my case, it's my Client 1 VPN that I need to call a script whenever it goes up or down. So my two scripts being called are named vpnclient1-up and vpnclient1-down

So I then created a script named vpnclient1-up and put it in the /jffs/scripts/ folder (and chmodded it 0777)

Code:
#!/bin/sh

iptables -t mangle -A PREROUTING -p tcp -s 10.0.0.0/24 -m multiport --sports 443 -j MARK --set-mark 10
ip route add table 100 default via 192.168.0.1
ip rule add prio 5 fwmark 10 table 100
ip route flush cache
exit 1

This script does a few things.

First of all it adds an iptables entry, which marks all packets coming into the router from 10.0.0.0/24 and source port 443. Essentially it adds a little marker (10) on the packet. We'll use this little mark in a moment. 10.0.0.0/24 is my local LAN. You can enter multiple ports here if needed.

We then add a default route in a new routing table called 100. The default route is my default gateway. In most cases this will be a public IP address but I have a double-NAT setup.

The next line adds a new ip rule at priority 5 (so it's high up in the ip rules table.) It sends all packets with our little '10' mark into the new routing table.

The net effect is that any packets coming into my router from 10.0.0.0/24 and source port 443 are sent to the WAN - NOT the VPN. All other packets, such as web browsing from any machine on my LAN, get sent to through the VPN.

Of course, if the VPN goes down we want to remove this configuration. To do that, I created a script in the /jffs/scripts/ folder named vpnclient1-down:

Code:
#!/bin/sh

iptables -t mangle -D PREROUTING -p tcp -s 10.0.0.0/24 -m multiport --sports 443 -j MARK --set-mark 10
ip rule del fwmark 10 table 100
ip route flush table 100
ip route flush cache

exit 1

I have no idea if this is the best way to achieve what I wanted, but it certainly seems to work. If there is a simpler, cleaner way I'd be happy to hear it.

I hope this helps somebody in the future and I'm very grateful to Asus and RMerlin for creating such a flexible platform on which I can do these things.
 

Similar threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top