OpenVPN client - use separate routing table possible?

Is it possible for openvpn in openwrt to map route push to a specific routing table ID that is not the main one?

I have tried to do this in a similar way as I did my wireguard interface but did not work, the routing table 30 I had set for tun0 interface is empty. To do this I temporarily re-enabled openvpn's ability to setup a route (commented out "--pull-filter ignore redirect-gateway" from my .ovpn)

We see the route from this openvpn provider tun0 but its on the main table.

root@meow:~# ip route
0.0.0.0/1 via 10.8.8.1 dev tun0
default via 192.168.12.1 dev eth1 proto static src 192.168.12.103
10.8.8.0/24 dev tun0 proto kernel scope link src 10.8.8.7
x via 192.168.12.1 dev eth1 proto static
x5 via 192.168.12.1 dev eth1
128.0.0.0/1 via 10.8.8.1 dev tun0
172.17.200.0/24 dev eth0.200 proto kernel scope link src 172.17.200.1
172.66.0.0/24 dev eth0.666 proto kernel scope link src 172.66.0.1
192.168.12.0/24 dev eth1 proto kernel scope link src 192.168.12.103
192.168.44.0/24 dev br-lan proto kernel scope link src 192.168.44.1

my ip route tables (openvpn is lookup = 30) but notice how lookup 20 is different with bidirectional rules existing

root@meow:~# ip rule list
0:      from all lookup local
10000:  from 10.100.100.10 lookup 20
20000:  from all to 10.100.100.10/24 lookup 20
32766:  from all lookup main
32767:  from all lookup default
90008:  from all iif lo lookup 20
90009:  from all iif lo lookup 30

I believe the bidirectional rules are set by wireguard since I have route enabled (expected). My best guess is that openvpn on openwrt does not behave in this way - I am assuming this because the pitch to using 'vpn-policy-routing' package seems to be this is a limitation and that is why I may be forced to use that package for managing routes.

Not trying to do everything the hard way but wanted to learn and see if I can keep my openwrt setup in a standard way (alas the same way I setup wireguard)- rather than treating openvpn as an oddball that requires me to setup vpn-policy-routing rules rather than table lookups which is what I am doing elsewhere.

I disabled openvpn route push since I don't want it as my default gateway, then below is my configuration (not including the wireguard interface thats not needed for this question).

config/network

root@meow:~# cat /etc/config/network

config interface 'loopback'
        option ifname 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fdb6:bf3f:ddd8::/48'

config interface 'lan'
        option type 'bridge'
        option ifname 'eth0'
        option proto 'static'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option ipaddr '192.168.44.1'
        option ipv6 'on'

config interface 'wan'
        option ifname 'eth1'
        option proto 'dhcp'

config interface 'wan6'
        option ifname 'eth1'
        option proto 'dhcpv6'
        option reqaddress 'force'
        option reqprefix 'no'
        option defaultroute '1'

config interface 'surfshark'
        option ifname 'eth0.666'
        option netmask '255.255.255.0'
        option ipaddr '172.66.0.1'
        option proto 'static'

config interface 'untrusted'
        option ifname 'eth0.200'
        option netmask '255.255.255.0'
        option ip6assign '64'
        option ipaddr '172.17.200.1'
        option proto 'static'

config interface 'surfsharktun'
        option ifname 'tun0'
        option ip4table '30'
        option ip6table '30'
        option proto 'none'

/config/firewall

root@meow:~# cat /etc/config/firewall

config defaults
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option synflood_protect '1'

config zone
        option name 'lan'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        option network 'lan'

config zone
        option name 'wan'
        list network 'wan'
        list network 'wan6'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        option input 'ACCEPT'
        option masq6 '1'

config forwarding
        option src 'lan'
        option dest 'wan'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

config rule
        option name 'Allow-Ping'
        option src 'wan'
        option proto 'icmp'
        option icmp_type 'echo-request'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-IGMP'
        option src 'wan'
        option proto 'igmp'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option src_ip 'fc00::/6'
        option dest_ip 'fc00::/6'
        option dest_port '546'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-MLD'
        option src 'wan'
        option proto 'icmp'
        option src_ip 'fe80::/10'
        list icmp_type '130/0'
        list icmp_type '131/0'
        list icmp_type '132/0'
        list icmp_type '143/0'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Input'
        option src 'wan'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        list icmp_type 'router-solicitation'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'neighbour-advertisement'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Forward'
        option src 'wan'
        option dest '*'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        option enabled '0'

config rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

config include
        option path '/etc/firewall.user'

config include
        option path '/etc/firewall.nat6'
        option name 'nat6'
        option reload '1'

config zone
        option name 'surfshark'
        option device 'eth0.666'
        option input 'ACCEPT'
        option forward 'ACCEPT'
        option network 'surfshark'
        option output 'ACCEPT'

config rule
        option name 'Allow-vlan666-Ping'
        option src 'surfshark'
        option target 'ACCEPT'
        option proto 'icmp'

config rule
        option name 'vlan666-to-router'
        option src 'surfshark'
        option target 'ACCEPT'

config forwarding
        option dest 'surfsharktun'
        option src 'surfshark'

config zone
        option name 'untrusted'
        option device 'eth0.200'
        option input 'ACCEPT'
        option forward 'ACCEPT'
        option network 'untrusted'
        option output 'ACCEPT'

config rule
        option name 'Allow-vlan200-Ping'
        option src 'untrusted'
        option target 'ACCEPT'
        option proto 'icmp'

config rule
        option name 'vlan200-to-router'
        option src 'untrusted'
        option target 'ACCEPT'

config forwarding
        option dest 'vpsgw'
        option src 'untrusted'

config forwarding
        option dest 'surfsharktun'
        option src 'untrusted'

config forwarding
        option dest 'wan'
        option src 'untrusted'

config zone
        option name 'surfsharktun'
        option network 'surfsharktun'
        option forward 'REJECT'
        option masq '1'
        option output 'ACCEPT'
        option device 'tun0'
        option input 'REJECT'
        option mtu_fix '1'

config zone
        option device 'vpsgw'
        option masq6 '1'
        option forward 'REJECT'
        option masq '1'
        option output 'ACCEPT'
        option input 'REJECT'
        option network 'vpsgw'
        option name 'vpsgw'

tun0 = 'surfsharktun' interface
surfshark FW zone has forwarding to surfsharktun enabled.

ping -I tun0 8.8.8.8 works fine thru the ovpn tunnel (route push was disabled).

Unsure if proto 'none' breaks ip4table / ip6table usage in config - why I don't see a biredirectional rule as I see for vpsgw? curious about this

I tried to force default gateway on table = 30 and used a lookup with priority 30000 but it won't work since table 30 is empty by default for some reason. Perhaps because my interface has no IP set?

If I manually add routing tables to table = 30 (which is empty) via ip route add 0.0.0.0/0 dev tun0 table 30 then viola traffic starts working as I would expect.

My question is now, is there an openwrt configuration I can use to ensure this route gets setup automatically, preferably outside ovpn config file?

Interestingly, I guess trying to hack this into the configuration file doesn't seem to be working?

Fri Jul 30 22:20:16 2021 daemon.notice openvpn(surfsharktun)[5902]: /sbin/ifconfig tun0 10.8.8.8 netmask 255.255.255.0 mtu 1500 broadcast 10.8.8.255
Fri Jul 30 22:20:16 2021 daemon.notice netifd: Interface 'surfsharktun' is enabled
Fri Jul 30 22:20:16 2021 daemon.notice netifd: Network device 'tun0' link is up
Fri Jul 30 22:20:16 2021 daemon.notice netifd: Interface 'surfsharktun' has link connectivity
Fri Jul 30 22:20:16 2021 daemon.notice netifd: Interface 'surfsharktun' is setting up now
Fri Jul 30 22:20:16 2021 daemon.notice netifd: Interface 'surfsharktun' is now up
Fri Jul 30 22:20:16 2021 daemon.warn dnsmasq[2978]: failed to create listening socket for 10.8.8.8: Address not available
Fri Jul 30 22:20:16 2021 daemon.warn dnsmasq[2978]: failed to create listening socket for 10.8.8.8: Address not available
Fri Jul 30 22:20:16 2021 daemon.notice openvpn(surfsharktun)[5902]: ip route add 0.0.0.0/0 dev tun0 table 30 tun0 1500 1584 10.8.8.8 255.255.255.0 init
Fri Jul 30 22:20:16 2021 daemon.err openvpn(surfsharktun)[5902]: WARNING: Failed running command (--up/--down): could not execute external program
Fri Jul 30 22:20:16 2021 daemon.notice openvpn(surfsharktun)[5902]: Exiting due to fatal error
Fri Jul 30 22:20:16 2021 daemon.notice netifd: Network device 'tun0' link is down
Fri Jul 30 22:20:16 2021 daemon.notice netifd: Interface 'surfsharktun' has link connectivity loss
Fri Jul 30 22:20:16 2021 daemon.notice netifd: Interface 'surfsharktun' is now down
Fri Jul 30 22:20:16 2021 daemon.notice netifd: Interface 'surfsharktun' is disabled
Fri Jul 30 22:20:16 2021 user.notice firewall: Reloading firewall due to ifup of surfsharktun (tun0)

I had added this to the .ovpn configuration, is it wrong?

 # My custom routing fix, so we map to the correct route table
--script-security 2
up "ip route add 0.0.0.0/0 dev tun0 table 30"
down "ip route delete 0.0.0.0/0 dev tun0 table 30"
 # end.

I also tried with /sbin/ip full path and it fails.

The rules with priorities of 10000 and 20000 are created by netifd.
But netifd has no native support for OpenVPN, so it doesn't create those rules.
You can use the VPN policy routing app, but it lacks integration with netifd rules.
That leaves you with scripts invoked by Hotplug or OpenVPN itself:

cat << "EOF" >> /etc/openvpn/client.conf
pull-filter ignore redirect-gateway
script-security 2
route-up "/sbin/ip route add default dev tun0 table 3"
EOF
2 Likes

thanks again!

I ended up with this in my client.ovpn file:

# Ensure this ovpn tunnel doesn't become default gateway
 --pull-filter ignore redirect-gateway

 # My custom routing fix, so we map to the correct route table
--script-security 2
route-up "/sbin/ip route add 0.0.0.0/0 dev tun0 table 30"
down "/sbin/ip route delete 0.0.0.0/0 dev tun0 table 30"
 # end.

This seems to work. I learned if /etc/init.d/network restart - the table 30 gets wiped out and empty again. Restarting openvpn runs the commands again and restores it - so something for me to keep in mind.

I think I have been able to achieve somewhat of what I was looking for :slight_smile:

1 Like

There's a Hotplug-based workaround to solve race conditions with netifd:
https://openwrt.org/docs/guide-user/services/vpn/openvpn/extras#dynamic_connection

2 Likes

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