OpenWRT openVPN client + WAN SSH access

Hello.
I have my OpenWRT configured to connect to NordVPN, as in OpenWrt-setup-with-NordVPN, the CLI instructions
The connections works as intended, all of the outgoing traffic goes through VPN

What I want to achieve is to be able to connect to my router via SSH on port 22 from the WAN interface - so from the outside world, directly to the router, without involving the VPN.
Unfortunately this does not work when the oVPN is running - I do have public IPv4 address, and this works when oVPN is stopped.

The related configuration is as follows:
/etc/config/network:

config interface 'wan'
	option device 'wan'
	option proto 'pppoe'
	option username 'xxx
	option password 'yyy'
	option ipv6 'auto'
	option peerdns '0'
	list dns '8.8.8.8'
	list dns '8.8.4.4'

config interface 'nordvpntun'
	option proto 'none'
	option device 'tun0'

/etc/config/firewall

config zone
	option name 'vpnfirewall'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'
	list network 'nordvpntun'

config forwarding
	option src 'lan'
	option dest 'vpnfirewall'

config rule
	option name 'Allow-Wan-SSH'
	option src 'wan'
	option target 'ACCEPT'
	list proto 'tcp'
	list proto 'udp'
	option dest_port '22'

I did an experiment, and the same situation applies if I setup port-forwarding - doesn't work with oVPN enabled, but works fine if I disable VPN.

config redirect
	option dest 'lan'
	option target 'DNAT'
	option name 'hassbian-wan'
	option src 'wan'
	option src_dport '1234'
	option dest_ip '192.168.1.99'
	option dest_port '8080'

What am I missing here ?

That is expected

Traffic comes in via the WAN and tries to get out via the VPN.
Your firewall will not allow that.

You have to use PBR to route port 22 out via the WAN.

There are several ways to do it e.g. see:

1 Like

Thank you !
So I'm one step closer.
Thanks to the following:

GATEWAY="$(ifstatus wan | grep nexthop | sed 's/[^0-9.]//g')"
ip route add default via $GATEWAY table 101
ip rule add sport 22 table 101

Resulting in:

root@OpenWrt:~# ip rule
0:	from all lookup local
32765:	from all sport 22 lookup 101
32766:	from all lookup main
32767:	from all lookup default

root@OpenWrt:~# ip route show table 101
default via 188.122.17.254 dev pppoe-wan

I'm able to connect via SSH to the router from the WAN, which was my intention.

However, now I lost the ability to connect to it from the LAN, using 192.168.1.1
This kind of makes sense to me, given that the outbound traffic from the router is going to be pushed to the WAN interface, and not to the host trying to connect (that exist on the LAN instead).

Also, I'm able to connect to other hosts in my network on port 22, regardless if it's from the router itself, or other hosts, which I don't really understand as I would assumed the outbound traffic should be routed through WAN and not LAN, as the sport=22 also in this case ?

Any hints would be much appreciated.

That is probably due to the fact that you are missing local routes in the table.

In the script at line 85 there is this:

			# ip route show | grep -Ev '^default |^0.0.0.0/1 |^128.0.0.0/1 ' | while read route; do
				# ip route add $route table $TID >/dev/null 2>&1
			# done

Remove the # at the beginning of these lines and the local routes will be copied to the table

2 Likes

Probably the simplest answer would be to add a route to the LAN to table 101, so when SSH packets use that table, the LAN is still properly routed. Another way would be to add a condition to the rule selecting table 101 so the table is never used for LAN traffic even if the source port is 22.

1 Like

@mk24 @egc
Thank you both.
I ended up with following script:

/etc/hotplug.d/iface/98-pbr-via-wan

#!/bin/ash

IFACE="nordvpntun"
SOURCE_PORT="22"
TABLE_ID="101"
EXCLUDED_CIDR="192.168.1.1/24"

if [ "$IFACE" == "$INTERFACE" ]; then
        if [ "ifup" == "$ACTION" ]; then
                logger -t hotplug "Enabling PBR-via-WAN"
                GATEWAY="$(ifstatus wan | grep nexthop | sed 's/[^0-9.]//g')"
                ip route add default via $GATEWAY table 101
                ip rule add sport $SOURCE_PORT table $TABLE_ID
                ip rule add from $EXCLUDED_CIDR lookup main
        fi
        if [ "ifdown" == "$ACTION" ]; then
                logger -t hotplug "Disabling PBR-via-WAN"
                while ip rule delete from 0/0 to 0/0 table $TABLE_ID >/dev/null 2>&1; do true; done
                ip rule delete from $EXCLUDED_CIDR lookup main
                ip route flush table $TABLE_ID
        fi
fi

which results in:

root@OpenWrt:~# ip rule show
0:	from all lookup local
32764:	from 192.168.1.1/24 lookup main
32765:	from all sport 22 lookup 101
32766:	from all lookup main
32767:	from all lookup default
root@OpenWrt:~# ip route show table 101
default via 188.122.17.254 dev pppoe-wan

Btw. additional question.
Am I right to assume, that this file should be added in:
OpenWrt -> Luci -> System -> Backup/Flash Firmware -> Configuration

as a single file, and not whole directory:
/etc/hotplug.d/iface/98-pbr-via-wan

so that it:
a) gets backed up using Generate Archive option
b) gets persisted during system upgrade
?

Correct :slight_smile:

OpenWrt will preserve any files or directories listed in /lib/upgrade/keep.d/ (e.g., /lib/upgrade/keep.d/keep.me) or /etc/sysupgrade.conf.
The easiest thing to do is list your needed files or directories in /etc/sysupgrade.conf

P.S. the more modern way to add local rules to your table instead of copying the rules as in my example is to do:

ip -4 rule add table main suppress_prefixlength 0 >/dev/null 2>&1
ip -4 rule add table main suppress_prefixlength 1 >/dev/null 2>&1

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.