Posted: Thu Jan 12, 2017 9:41 Post subject: port forwarding with openvpn client enabled
I have the following (working) setup:
ISP router (ISP supplied WAN IP, LAN IP 192.168.10.1)
1043NDv1 running DD-WRT 11-14-2016-r30880 (WAN IP 192.168.10.2, LAN IP 192.168.1.1)
On the 1043ND I've configured an OpenVPN client so all LAN traffic is routed through the VPN.
I've also configured a kill switch in the 'firewall' script section to deny any non-VPN traffic to pass from LAN to WAN when the OpenVPN is down:
WAN_IF="$(ip route | awk '/^default/{print $NF}')"
iptables -I FORWARD -i br0 -o $WAN_IF -m state --state NEW -j REJECT --reject-with icmp-host-prohibited
iptables -I FORWARD -i br0 -p tcp -o $WAN_IF -m state --state NEW -j REJECT --reject-with tcp-reset
So, this is all working great but now I want ssh access from WAN to a server on the LAN, 192.168.1.10.
What I tried is to set up port forwarding on the ISP router to forward port 443 on WAN to port 22 on 192.168.10.2 (DD-WRT).
Then I set up port forwarding on DD-WRT to forward port 22 on its WAN to 192.168.1.10.
This doesn't work
I guess (I'm not sure how to debug this) my issue is that I'm accessing from WAN, and the replies are sent through the VPN.
So I'll have to add a line to my firewall commands to route traffic from 192.168.1.10 port 22 back through WAN?
Can anyone help me with this, as I'm not very familiar with iptables?
Thanks!
eibgrad is a bit of a expert around these parts regarding OpenVPN and routing stuff!
Essentially what you are after is marking specific traffic with the source of a specific IP/port to bypass your VPN. This can be achieved by creating a specific routing table with a unique fwmark value, then in iptables, do something like this to mark traffic to be routed via the WAN instead:
Example SSH rule: (Might have to be tweaked slightly)
Code:
iptables -t mangle -A PREROUTING -i br0 -p tcp --sport 22 -s 192.168.1.10 -j MARK --set-mark 1
In your case you'll need to also override your killswitch rule for this specific IP/port as well, otherwise the traffic will be always blocked regardless.
Alternatively, if you use policy routing, you could just not include this specific client in the list and solve the issue that way. _________________ James
Main router:
Netgear R7000 overclocked to 1.2GHz - DD-WRT v3.0-r35965M kongac
IPv6 6in4 (HE.net), OpenVPN (with PBR and split tunnelling), Entware, dnsmasq with ipset
I found the first post before but not being familiar with iptables I get a bit lost trying to modifying suggested solutions to my specifics..
I'll give it another go.
Two questions: I tried to ssh to the sshd of dd-wrt from WAN to try and confirm port forwarding from my ISP router works.
I can not connect: port 443 seems to be forwarded (to port 22) but times out. Port 442 for example rejects connection immediately.
Am I right that in my setup this should work without additional changes, or does the dd-wrt sshd also tries to reply through VPN here?
Another question to aid my debugging: there should be no difference in me trying to access from WAN, or from my LAN to VPN to WAN right, eg. use another machine on my LAN to test?
Progress is a bit slow if I can only test from a location outside my LAN (I don't have access to 4G or similar)..
You'll need to change tun11 to tun1 for it to work with DD-WRT.
This would go in your start up config, but I'd recommend running it manually via SSH first to test.
Its essentially a two part process, you need a specific routing table which copies various routes to go via the WAN, this is then marked with a specific fwmark value, in this case 1.
Then with iptables you craft specific rules that target the specific LAN IP and/or port and mark this traffic with the same fwmark chosen above.
So something like this:
Code:
iptables -t mangle -A PREROUTING -i br0 -p tcp --sport 22 -s 192.168.1.10 -j MARK --set-mark 1
You would then place any iptables rules in your firewall script, but again, I'd manually apply in SSH first to confirm, before committing to NVRAM.
Roughly translated in human form:
Match LAN traffic (br0)
From LAN client 192.168.1.10
From Source Port TCP 22
Mark the traffic with the value of 1
PREROUTING and MARK are your friends here.
This would match the custom routing table created which has been setup to use the WAN gateway and hence all traffic from 192.168.1.10 TCP 22 will go via the WAN. Other traffic that does not match this will continue to go via the VPN. You can obviously add as many selective rules you'd like.
The best approach with selective routing it to essentially route everything through the VPN then create your own rules to conditionally bypass it, its the best trade off for security and functionality.
Regards your other questions.
Your router itself should not ever go through the VPN. If it does, it usually breaks policy routing and everything falls down.
SSH forwarding is part of DD-WRT you need to enable it within the web interface, it can be any TCP port providing its not already taken i.e. 443 might not be usable if you have the web interface with a bind on port 443.
If you use NAT redirection you might experience issues, but in most cases you can test your WAN via the LAN, but you can also other sites for port visibility like http://www.yougetsignal.com/tools/open-ports/, be sure to make sure your ISPs WAN IP is shown and not the VPN. _________________ James
Main router:
Netgear R7000 overclocked to 1.2GHz - DD-WRT v3.0-r35965M kongac
IPv6 6in4 (HE.net), OpenVPN (with PBR and split tunnelling), Entware, dnsmasq with ipset
I made a little bit of progress: I confirmed yesterday that packets for port 22 from WAN are indeed arriving at 192.168.1.10 now.
Packets aren't routed back yet though: I added an iptables rule in the firewall commands but looking at it with fresh eyes now I see I made some wrong assumptions.
##############################
VPN related commands here
to setup VPN tunnel
##############################
sleep 10
for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
echo 0 > $i
done
#
# Delete table 100 and flush any existing rules if they exist.
#
ip route flush table 100
ip route del default table 100
ip rule del fwmark 1 table 100
ip route flush cache
iptables -t mangle -F PREROUTING
#
# Copy all non-default and non-VPN related routes from the main table into table 100.
# Then configure table 100 to route all traffic out the WAN gateway and assign it mark "1"
#
# NOTE: Here I assume the OpenVPN tunnel is named "tun1".
#
#
ip route show table main | grep -Ev ^default | grep -Ev tun1 \
| while read ROUTE ; do
ip route add table 100 $ROUTE
done
ip route add default table 100 via $(nvram get wan_gateway)
ip rule add fwmark 1 table 100
ip route flush cache
#
# Define the routing policies for the traffic. The rules will be applied in the order that they
# are listed. In the end, packets with MARK set to "0" will pass through the VPN. If MARK is set
# to "1" it will bypass the VPN.
#
I would recommended moving the two iptables rules into your firewall rather than startup. Have the PREROUTING -F rule first, as this flushes all rules, then followed by your SSH rule. _________________ James
Main router:
Netgear R7000 overclocked to 1.2GHz - DD-WRT v3.0-r35965M kongac
IPv6 6in4 (HE.net), OpenVPN (with PBR and split tunnelling), Entware, dnsmasq with ipset
It's working, hurray!
I has a slight hurdle with not realising I had secured my server pretty well for remote access so I had to modify some fail2ban rules too to allow access from the VPN assigned IP address..
Here is what I ended up with:
Startup script:
Code:
#!/bin/sh
# VPN setup
VPN magic here
# allow WAN to LAN access
#########################
sleep 10
for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
echo 0 > $i
done
#
# Delete table 100 and flush any existing rules if they exist.
#
ip route flush table 100
ip route del default table 100
ip rule del fwmark 1 table 100
ip route flush cache
#
# Copy all non-default and non-VPN related routes from the main table into table 100.
# Then configure table 100 to route all traffic out the WAN gateway and assign it mark "1"
#
# NOTE: Here I assume the OpenVPN tunnel is named "tun1".
#
#
ip route show table main | grep -Ev ^default | grep -Ev tun1 \
| while read ROUTE ; do
ip route add table 100 $ROUTE
done
ip route add default table 100 via $(nvram get wan_gateway)
ip rule add fwmark 1 table 100
ip route flush cache
And my firewall commands:
Code:
# Allow WAN to LAN access
iptables -t mangle -F PREROUTING
# SSH Traffic: Bypass VPN
#
# Define the routing policies for the traffic. The rules will be applied in the order that they
# are listed. In the end, packets with MARK set to "0" will pass through the VPN. If MARK is set
# to "1" it will bypass the VPN.
#
iptables -t mangle -A PREROUTING -i br0 -p tcp --sport 22 --match iprange --src-range 192.168.1.10 -j MARK --set-mark 1
I'm afraid I spoke too soon.. Everything works when I try from within the LAN from the same machine: I ssh to my WAN IP and can connect.
From outside if I do the same I see TCP packet arrive at 192.168.1.10 and reply packets sent back again to dd-wrt.
After some time the connection times out.
Using traceroute -p 22 <ip from outside> from 192.168.1.10 I see that packets are still routed through the VPN rather that WAN
Strangely I can't see any trace of the iptables rules I entered on dd-wrt using iptables -vL, ip route show or cat /tmp/.ipt
How can I confirm the iptables rules I entered are applied?
That's an interesting thread. I think I've tried the single IP with -s before, but I didn't check the results of running the script eg. if tables were applied correctly.
There may be more issues with my build r30880 than just the iprange module not loading?
I learned the hard way that the VPN client isn't working in r30949 for example, with is complicating matters a lot doing stuff like this for the first time. Still learning but moving forward
It might be worth trying a build with proven working VPN client and firewall scripting, is there such a build you could recommend?
In the mean time I'll dive deeper and see if my changes actually are applied.
After manually entering commands from this section
Code:
ip route show table main | grep -Ev ^default | grep -Ev tun1 \
| while read ROUTE ; do
ip route add table 100 $ROUTE
done
ip route add default table 100 via $(nvram get wan_gateway)
ip rule add fwmark 1 table 100
ip route flush cache
# ip route show table 100
now shows all routes previously shown with # ip route show table main | grep -Ev ^default | grep -Ev tun1
# ip rule list
shows nothing.. somehow I can't add # ip rule add fwmark 1 table 100