Hosting VPN server on a working OpenWrt setup but unable to access internet via Android device connected to the VPN

My problem is this:

I've configured a VPN server on a Raspberry Pi 3 using the instructions provided by the OpenWrt documentation. OpenWrt itself has an internet connection and devices attached to its wifi network can access the internet.

However, when I connect to the VPN using the recommended OpenWrt client app there is no internet access.

Normally I am a fairly skilled troubleshooter (having even rolled my own Linux kernels back in the day to backport a server) but this is one problem that has yet to be solved.

Here's my setup: OpenWrt is installed on a Raspberry Pi 3 which is connected to a cable modem/router (Hitron 4680) through the built-in Ethernet port.

Note: As per OpenWrt install instruction advice, the OpenWrt install was configured to use an arbitrary IP address (192.168.0.13) on the Hitron's network since the default settings resulted in a non-functional network for all attached devices on the Hitron (multiple DHCP servers?).

The Raspberry Pi 3 has a working wifi network. Devices attached to the Pi 3's wifi network can access the internet. My Android phone (Pixel 6a) is able to connect to the VPN but it is unable to get internet service.

I have only used the default settings from the install instructions.

Links I've used:

https://openwrt.org/docs/guide-user/services/vpn/openvpn/server (set up vpn)

https://openwrt.org/docs/guide-quick-start/checks_and_troubleshooting (not entirely sure I configured it correctly but OpenWrt had internet access afterwards)

https://openwrt.org/docs/guide-user/services/nas/sftp.server (to download the ovpn file from the Raspberry Pi 3 OpenWrt install)

https://openwrt.org/docs/guide-user/network/network_configuration (not used)

root@OpenWrt:~# logread -e openvpn; netstat -l -n -p | grep -e openvpn
Sat Sep 28 23:06:56 2024 daemon.err openvpn(server)[3414]: event_wait : Interrupted system call (code=4)
Sat Sep 28 23:06:56 2024 daemon.notice openvpn(server)[3414]: /usr/libexec/openvpn-hotplug route-pre-down server tun0 1500 1621 192.168.9.1 255.255.255.0 init
Sat Sep 28 23:06:56 2024 daemon.notice openvpn(server)[3414]: net_addr_v4_del: 192.168.9.1 dev tun0
Sat Sep 28 23:06:56 2024 daemon.warn openvpn(server)[3414]: sitnl_send: rtnl: generic error (-1): Operation not permitted
Sat Sep 28 23:06:56 2024 daemon.warn openvpn(server)[3414]: Linux can't del IP from iface tun0
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[3414]: /usr/libexec/openvpn-hotplug down server tun0 1500 1621 192.168.9.1 255.255.255.0 init
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[3414]: SIGTERM[hard,] received, process exiting
Sat Sep 28 23:06:57 2024 daemon.warn openvpn(server)[6527]: --cipher is not set. Previous OpenVPN version defaulted to BF-CBC as fallback when cipher negotiation failed in this case. If you need this fallback please add '--data-ciphers-fallback BF-CBC' to your configuration and/or add BF-CBC to --data-ciphers.
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: OpenVPN 2.5.8 aarch64-openwrt-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [MH/PKTINFO] [AEAD]
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: library versions: OpenSSL 3.0.15 3 Sep 2024, LZO 2.10
Sat Sep 28 23:06:57 2024 daemon.warn openvpn(server)[6527]: NOTE: your local LAN uses the extremely common subnet address 192.168.0.x or 192.168.1.x.  Be aware that this might create routing conflicts if you connect to the VPN server from public locations such as internet cafes that use the same subnet.
Sat Sep 28 23:06:57 2024 daemon.warn openvpn(server)[6527]: NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: TUN/TAP device tun0 opened
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: net_iface_mtu_set: mtu 1500 for tun0
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: net_iface_up: set tun0 up
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: net_addr_v4_add: 192.168.9.1/24 dev tun0
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: /usr/libexec/openvpn-hotplug up server tun0 1500 1621 192.168.9.1 255.255.255.0 init
Sat Sep 28 23:06:57 2024 daemon.warn openvpn(server)[6527]: Could not determine IPv4/IPv6 protocol. Using AF_INET
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: UDPv4 link local (bound): [AF_INET][undef]:1194
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: UDPv4 link remote: [AF_UNSPEC]
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: GID set to nogroup
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: UID set to nobody
Sat Sep 28 23:06:57 2024 daemon.notice openvpn(server)[6527]: Initialization Sequence Completed
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 peer info: IV_VER=3.8.5connectQA3
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 peer info: IV_PLAT=android
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 peer info: IV_NCP=2
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 peer info: IV_TCPNL=1
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 peer info: IV_PROTO=990
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 peer info: IV_MTU=1600
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 peer info: IV_CIPHERS=AES-128-CBC:AES-192-CBC:AES-256-CBC:AES-128-GCM:AES-192-GCM:AES-256-GCM:CHACHA20-POLY1305
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 peer info: IV_AUTO_SESS=1
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 peer info: IV_GUI_VER=net.openvpn.connect.android_3.4.2-9909
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 peer info: IV_SSO=webauth,openurl,crtext
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 peer info: IV_BS64DL=1
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: 192.168.0.230:39727 [client] Peer Connection Initiated with [AF_INET]192.168.0.230:39727
Sat Sep 28 23:07:30 2024 daemon.notice openvpn(server)[6527]: client/192.168.0.230:39727 MULTI_sva: pool returned IPv4=192.168.9.2, IPv6=(Not enabled)
udp        0      0 0.0.0.0:1194            0.0.0.0:*                           6527/openvpn
root@OpenWrt:~# ip address show; ip route show table all
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br-lan state UP qlen 1000
    link/ether b8:27:eb:96:91:06 brd ff:ff:ff:ff:ff:ff
3: phy0-ap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br-lan state UP qlen 1000
    link/ether ba:27:eb:c3:c4:52 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::b827:ebff:fec3:c452/64 scope link 
       valid_lft forever preferred_lft forever
7: br-lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether b8:27:eb:96:91:06 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.13/24 brd 192.168.0.255 scope global br-lan
       valid_lft forever preferred_lft forever
    inet6 fdba:e0a3:d422::1/60 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::ba27:ebff:fe96:9106/64 scope link 
       valid_lft forever preferred_lft forever
8: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN qlen 500
    link/[65534] 
    inet 192.168.9.1/24 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::b249:65ef:533e:84f2/64 scope link flags 800 
       valid_lft forever preferred_lft forever
default via 192.168.0.1 dev br-lan 
192.168.0.0/24 dev br-lan scope link  src 192.168.0.13 
192.168.9.0/24 dev tun0 scope link  src 192.168.9.1 
local 127.0.0.0/8 dev lo table local scope host  src 127.0.0.1 
local 127.0.0.1 dev lo table local scope host  src 127.0.0.1 
broadcast 127.255.255.255 dev lo table local scope link  src 127.0.0.1 
local 192.168.0.13 dev br-lan table local scope host  src 192.168.0.13 
broadcast 192.168.0.255 dev br-lan table local scope link  src 192.168.0.13 
local 192.168.9.1 dev tun0 table local scope host  src 192.168.9.1 
broadcast 192.168.9.255 dev tun0 table local scope link  src 192.168.9.1 
fdba:e0a3:d422::/64 dev br-lan  metric 1024 
unreachable fdba:e0a3:d422::/48 dev lo  metric 2147483647 
fe80::/64 dev phy0-ap0  metric 256 
fe80::/64 dev br-lan  metric 256 
fe80::/64 dev tun0  metric 256 
local ::1 dev lo table local  metric 0 
anycast fdba:e0a3:d422:: dev br-lan table local  metric 0 
local fdba:e0a3:d422::1 dev br-lan table local  metric 0 
anycast fe80:: dev phy0-ap0 table local  metric 0 
anycast fe80:: dev br-lan table local  metric 0 
anycast fe80:: dev tun0 table local  metric 0 
local fe80::b249:65ef:533e:84f2 dev tun0 table local  metric 0 
local fe80::b827:ebff:fec3:c452 dev phy0-ap0 table local  metric 0 
local fe80::ba27:ebff:fe96:9106 dev br-lan table local  metric 0 
multicast ff00::/8 dev phy0-ap0 table local  metric 256 
multicast ff00::/8 dev br-lan table local  metric 256 
multicast ff00::/8 dev tun0 table local  metric 256 

root@OpenWrt:~# ip rule show; ip -6 rule show; nft list ruleset
0:	from all lookup local 
32766:	from all lookup main 
32767:	from all lookup default 
0:	from all lookup local 
32766:	from all lookup main 
table inet fw4 {
	chain input {
		type filter hook input priority filter; policy drop;
		iifname "lo" accept comment "!fw4: Accept traffic from loopback"
		ct state established,related accept comment "!fw4: Allow inbound established and related flows"
		tcp flags syn / fin,syn,rst,ack jump syn_flood comment "!fw4: Rate limit TCP syn packets"
		iifname "tun*" jump input_lan comment "!fw4: Handle lan IPv4/IPv6 input traffic"
		iifname "br-lan" jump input_lan comment "!fw4: Handle lan IPv4/IPv6 input traffic"
		jump handle_reject
	}

	chain forward {
		type filter hook forward priority filter; policy drop;
		ct state established,related accept comment "!fw4: Allow forwarded established and related flows"
		iifname "tun*" jump forward_lan comment "!fw4: Handle lan IPv4/IPv6 forward traffic"
		iifname "br-lan" jump forward_lan comment "!fw4: Handle lan IPv4/IPv6 forward traffic"
		jump handle_reject
	}

	chain output {
		type filter hook output priority filter; policy accept;
		oifname "lo" accept comment "!fw4: Accept traffic towards loopback"
		ct state established,related accept comment "!fw4: Allow outbound established and related flows"
		oifname "tun*" jump output_lan comment "!fw4: Handle lan IPv4/IPv6 output traffic"
		oifname "br-lan" jump output_lan comment "!fw4: Handle lan IPv4/IPv6 output traffic"
	}

	chain prerouting {
		type filter hook prerouting priority filter; policy accept;
		iifname "tun*" jump helper_lan comment "!fw4: Handle lan IPv4/IPv6 helper assignment"
		iifname "br-lan" jump helper_lan comment "!fw4: Handle lan IPv4/IPv6 helper assignment"
	}

	chain handle_reject {
		meta l4proto tcp reject with tcp reset comment "!fw4: Reject TCP traffic"
		reject comment "!fw4: Reject any other traffic"
	}

	chain syn_flood {
		limit rate 25/second burst 50 packets return comment "!fw4: Accept SYN packets below rate-limit"
		drop comment "!fw4: Drop excess packets"
	}

	chain input_lan {
		jump accept_from_lan
	}

	chain output_lan {
		jump accept_to_lan
	}

	chain forward_lan {
		jump accept_to_wan comment "!fw4: Accept lan to wan forwarding"
		jump accept_to_lan
	}

	chain helper_lan {
	}

	chain accept_from_lan {
		iifname "tun*" counter packets 49 bytes 3389 accept comment "!fw4: accept lan IPv4/IPv6 traffic"
		iifname "br-lan" counter packets 3802 bytes 380952 accept comment "!fw4: accept lan IPv4/IPv6 traffic"
	}

	chain accept_to_lan {
		oifname "tun*" counter packets 4 bytes 304 accept comment "!fw4: accept lan IPv4/IPv6 traffic"
		oifname "br-lan" counter packets 38533 bytes 11833594 accept comment "!fw4: accept lan IPv4/IPv6 traffic"
	}

	chain input_wan {
		meta nfproto ipv4 udp dport 68 counter packets 0 bytes 0 accept comment "!fw4: Allow-DHCP-Renew"
		icmp type echo-request counter packets 0 bytes 0 accept comment "!fw4: Allow-Ping"
		meta nfproto ipv4 meta l4proto igmp counter packets 0 bytes 0 accept comment "!fw4: Allow-IGMP"
		meta nfproto ipv6 udp dport 546 counter packets 0 bytes 0 accept comment "!fw4: Allow-DHCPv6"
		ip6 saddr fe80::/10 icmpv6 type . icmpv6 code { mld-listener-query . no-route, mld-listener-report . no-route, mld-listener-done . no-route, mld2-listener-report . no-route } counter packets 0 bytes 0 accept comment "!fw4: Allow-MLD"
		icmpv6 type { destination-unreachable, time-exceeded, echo-request, echo-reply, nd-router-solicit, nd-router-advert } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Input"
		icmpv6 type . icmpv6 code { packet-too-big . no-route, parameter-problem . no-route, nd-neighbor-solicit . no-route, nd-neighbor-advert . no-route, parameter-problem . admin-prohibited } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Input"
		udp dport 1194 counter packets 0 bytes 0 accept comment "!fw4: Allow-OpenVPN"
		jump reject_from_wan
	}

	chain output_wan {
		jump accept_to_wan
	}

	chain forward_wan {
		icmpv6 type { destination-unreachable, time-exceeded, echo-request, echo-reply } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Forward"
		icmpv6 type . icmpv6 code { packet-too-big . no-route, parameter-problem . no-route, parameter-problem . admin-prohibited } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Forward"
		meta l4proto esp counter packets 0 bytes 0 jump accept_to_lan comment "!fw4: Allow-IPSec-ESP"
		udp dport 500 counter packets 0 bytes 0 jump accept_to_lan comment "!fw4: Allow-ISAKMP"
		jump reject_to_wan
	}

	chain accept_to_wan {
	}

	chain reject_from_wan {
	}

	chain reject_to_wan {
	}

	chain dstnat {
		type nat hook prerouting priority dstnat; policy accept;
	}

	chain srcnat {
		type nat hook postrouting priority srcnat; policy accept;
	}

	chain srcnat_wan {
		meta nfproto ipv4 masquerade comment "!fw4: Masquerade IPv4 wan traffic"
	}

	chain raw_prerouting {
		type filter hook prerouting priority raw; policy accept;
	}

	chain raw_output {
		type filter hook output priority raw; policy accept;
	}

	chain mangle_prerouting {
		type filter hook prerouting priority mangle; policy accept;
	}

	chain mangle_postrouting {
		type filter hook postrouting priority mangle; policy accept;
	}

	chain mangle_input {
		type filter hook input priority mangle; policy accept;
	}

	chain mangle_output {
		type route hook output priority mangle; policy accept;
	}

	chain mangle_forward {
		type filter hook forward priority mangle; policy accept;
	}
}

root@OpenWrt:~# uci show network; uci show firewall; uci show openvpn
network.loopback=interface
network.loopback.device='lo'
network.loopback.proto='static'
network.loopback.ipaddr='127.0.0.1'
network.loopback.netmask='255.0.0.0'
network.globals=globals
network.globals.ula_prefix='fdba:e0a3:d422::/48'
network.@device[0]=device
network.@device[0].name='br-lan'
network.@device[0].type='bridge'
network.@device[0].ports='eth0'
network.lan=interface
network.lan.device='br-lan'
network.lan.proto='static'
network.lan.ipaddr='192.168.0.13'
network.lan.netmask='255.255.255.0'
network.lan.ip6assign='60'
network.lan.gateway='192.168.0.1'
network.lan.dns='192.168.0.1'
firewall.@defaults[0]=defaults
firewall.@defaults[0].syn_flood='1'
firewall.@defaults[0].input='REJECT'
firewall.@defaults[0].output='ACCEPT'
firewall.@defaults[0].forward='REJECT'
firewall.lan=zone
firewall.lan.name='lan'
firewall.lan.network='lan'
firewall.lan.input='ACCEPT'
firewall.lan.output='ACCEPT'
firewall.lan.forward='ACCEPT'
firewall.lan.device='tun+'
firewall.wan=zone
firewall.wan.name='wan'
firewall.wan.network='wan' 'wan6'
firewall.wan.input='REJECT'
firewall.wan.output='ACCEPT'
firewall.wan.forward='REJECT'
firewall.wan.masq='1'
firewall.wan.mtu_fix='1'
firewall.@forwarding[0]=forwarding
firewall.@forwarding[0].src='lan'
firewall.@forwarding[0].dest='wan'
firewall.@rule[0]=rule
firewall.@rule[0].name='Allow-DHCP-Renew'
firewall.@rule[0].src='wan'
firewall.@rule[0].proto='udp'
firewall.@rule[0].dest_port='68'
firewall.@rule[0].target='ACCEPT'
firewall.@rule[0].family='ipv4'
firewall.@rule[1]=rule
firewall.@rule[1].name='Allow-Ping'
firewall.@rule[1].src='wan'
firewall.@rule[1].proto='icmp'
firewall.@rule[1].icmp_type='echo-request'
firewall.@rule[1].family='ipv4'
firewall.@rule[1].target='ACCEPT'
firewall.@rule[2]=rule
firewall.@rule[2].name='Allow-IGMP'
firewall.@rule[2].src='wan'
firewall.@rule[2].proto='igmp'
firewall.@rule[2].family='ipv4'
firewall.@rule[2].target='ACCEPT'
firewall.@rule[3]=rule
firewall.@rule[3].name='Allow-DHCPv6'
firewall.@rule[3].src='wan'
firewall.@rule[3].proto='udp'
firewall.@rule[3].dest_port='546'
firewall.@rule[3].family='ipv6'
firewall.@rule[3].target='ACCEPT'
firewall.@rule[4]=rule
firewall.@rule[4].name='Allow-MLD'
firewall.@rule[4].src='wan'
firewall.@rule[4].proto='icmp'
firewall.@rule[4].src_ip='fe80::/10'
firewall.@rule[4].icmp_type='130/0' '131/0' '132/0' '143/0'
firewall.@rule[4].family='ipv6'
firewall.@rule[4].target='ACCEPT'
firewall.@rule[5]=rule
firewall.@rule[5].name='Allow-ICMPv6-Input'
firewall.@rule[5].src='wan'
firewall.@rule[5].proto='icmp'
firewall.@rule[5].icmp_type='echo-request' 'echo-reply' 'destination-unreachable' 'packet-too-big' 'time-exceeded' 'bad-header' 'unknown-header-type' 'router-solicitation' 'neighbour-solicitation' 'router-advertisement' 'neighbour-advertisement'
firewall.@rule[5].limit='1000/sec'
firewall.@rule[5].family='ipv6'
firewall.@rule[5].target='ACCEPT'
firewall.@rule[6]=rule
firewall.@rule[6].name='Allow-ICMPv6-Forward'
firewall.@rule[6].src='wan'
firewall.@rule[6].dest='*'
firewall.@rule[6].proto='icmp'
firewall.@rule[6].icmp_type='echo-request' 'echo-reply' 'destination-unreachable' 'packet-too-big' 'time-exceeded' 'bad-header' 'unknown-header-type'
firewall.@rule[6].limit='1000/sec'
firewall.@rule[6].family='ipv6'
firewall.@rule[6].target='ACCEPT'
firewall.@rule[7]=rule
firewall.@rule[7].name='Allow-IPSec-ESP'
firewall.@rule[7].src='wan'
firewall.@rule[7].dest='lan'
firewall.@rule[7].proto='esp'
firewall.@rule[7].target='ACCEPT'
firewall.@rule[8]=rule
firewall.@rule[8].name='Allow-ISAKMP'
firewall.@rule[8].src='wan'
firewall.@rule[8].dest='lan'
firewall.@rule[8].dest_port='500'
firewall.@rule[8].proto='udp'
firewall.@rule[8].target='ACCEPT'
firewall.ovpn=rule
firewall.ovpn.name='Allow-OpenVPN'
firewall.ovpn.src='wan'
firewall.ovpn.dest_port='1194'
firewall.ovpn.proto='udp'
firewall.ovpn.target='ACCEPT'
openvpn.custom_config=openvpn
openvpn.custom_config.enabled='0'
openvpn.custom_config.config='/etc/openvpn/my-vpn.conf'
openvpn.sample_server=openvpn
openvpn.sample_server.enabled='0'
openvpn.sample_server.port='1194'
openvpn.sample_server.proto='udp'
openvpn.sample_server.dev='tun'
openvpn.sample_server.ca='/etc/openvpn/ca.crt'
openvpn.sample_server.cert='/etc/openvpn/server.crt'
openvpn.sample_server.key='/etc/openvpn/server.key'
openvpn.sample_server.dh='/etc/openvpn/dh2048.pem'
openvpn.sample_server.server='10.8.0.0 255.255.255.0'
openvpn.sample_server.ifconfig_pool_persist='/tmp/ipp.txt'
openvpn.sample_server.keepalive='10 120'
openvpn.sample_server.persist_key='1'
openvpn.sample_server.persist_tun='1'
openvpn.sample_server.user='nobody'
openvpn.sample_server.status='/tmp/openvpn-status.log'
openvpn.sample_server.verb='3'
openvpn.sample_client=openvpn
openvpn.sample_client.enabled='0'
openvpn.sample_client.client='1'
openvpn.sample_client.dev='tun'
openvpn.sample_client.proto='udp'
openvpn.sample_client.remote='my_server_1 1194'
openvpn.sample_client.resolv_retry='infinite'
openvpn.sample_client.nobind='1'
openvpn.sample_client.persist_key='1'
openvpn.sample_client.persist_tun='1'
openvpn.sample_client.user='nobody'
openvpn.sample_client.ca='/etc/openvpn/ca.crt'
openvpn.sample_client.cert='/etc/openvpn/client.crt'
openvpn.sample_client.key='/etc/openvpn/client.key'
openvpn.sample_client.verb='3'
root@OpenWrt:~# head -v -n -0 /etc/openvpn/*.conf
==> /etc/openvpn/server.conf <==
user nobody
group nogroup
dev tun
port 1194
proto udp
server 192.168.9.0 255.255.255.0
topology subnet
client-to-client
keepalive 10 60
persist-tun
persist-key
push "dhcp-option DNS 192.168.9.1"
push "dhcp-option DOMAIN lan"
push "redirect-gateway def1"
push "persist-tun"
push "persist-key"
<dh>
-----BEGIN DH PARAMETERS-----
XXX==
-----END DH PARAMETERS-----
</dh>
<tls-crypt-v2>
-----BEGIN OpenVPN tls-crypt-v2 server key-----
XXX=
-----END OpenVPN tls-crypt-v2 server key-----
</tls-crypt-v2>
<key>
-----BEGIN PRIVATE KEY-----
XXX==
-----END PRIVATE KEY-----
</key>
<cert>
-----BEGIN CERTIFICATE-----
XXX
-----END CERTIFICATE-----
</cert>
<ca>
-----BEGIN CERTIFICATE-----

XXX
-----END CERTIFICATE-----
</ca>

Have you considered using wireguard?

Your VPN network is configured on the 192.168.1.0 range, and your LAN network (where the VPN server is not the main router) is on the 192.168.0.0 range; your main router is going to receive packets (on it's internal network) from an unexpected range.

You probably need to enable NAT on the LAN interface.

1 Like

Hi, thank you for taking the time to respond. I'm struggling to see 192.168.1 in the logs. The only hit (when I ctrl-F :slightly_smiling_face:) for 192.168.1 is in this quote: "192.168.0.x or 192.168.1.x" which seems like a boilerplate warning.

Is it perhaps configured on "net_addr_v4_add: 192.168.9.1/24 dev tun0"?

My gut instinct was that it's a problem with the IP address range. I just couldn't figure out where to start. I will research NAT settings changes (soon--am quite busy).

PS One thing I forgot to mention is that I'm connecting to the VPN from the same 192.168.0 network that the OpenWrt server is connected to. This is for testing purposes only (since the goal is to use my own internet connection while on a network that is blocking some important websites).

I chose VPN because, well, because, no particular reason.

Is wireguard easier to set up/less difficult to get going?

It certainly is.

But I agree with eduperez. It looks like this is setup on a Bridged (Dumb) AP.
So you either have to enable Masquerading on the LAN interface (or on the main router set a static route for the VPN subnet 192.168.9.0/24 gateway 192.168.0.13).

Further more test from outside with your phone on cellular (make sure you portforward from your main router to the VPN router)

1 Like

I just did test externally seconds ago (using cellular data with my actual IP and with a bad IP). I've got my external ports configured so that the connection can be negotiated externally and can't connect if the IP is bad.

Will check out Masquerading or "static route" when I get a chance.

PS Thank you for your reply :slight_smile:

You need to do a few things on your modem/main router box. First check that the IP it holds on its wan interface is not from a private range (starts with 10 or 100), and it is the same one that you have registered in DDNS and that visiting a "whats my IP" test site on a LAN computer reports. If your ISP is not routing a public IP to your house, you can't run any services with incoming connections.

Assuming that's OK then inside the modem/router as @egc said, you need to find and make the setting that forwards port 1194 UDP from the Internet to your OpenWrt Pi's LAN address.

These same things would also be an issue with WIreguard. Since you've already done most of the setup for OpenVPN, you can stay on that path. OpenVPN is better than Wireguard in maybe one respect in that it logs a lot of stuff which is useful to diagnose problems.

1 Like

I couldn't make sense of most of what I found on the web so I just tried something at random... and it worked!

I couldn't get 'masquerade' working so, on a hunch, I went with the default SNAT and was successful.

PS I'm guessing that 192.168.9.0/24 means that all 192.168.9.x IP addresses are covered (I'm not familiar with /24 notation).

Yes, I've confirmed that my IP address is indeed not a private range (I was able to connect to the VPN from my cellular data, even if I couldn't access the internet from it). And, yes, my modem is forwarding UDP on port 1194 to the OpenWrt Pi's LAN address.

Now I'll have to test it on the network that is the reason I want my own VPN. Though, I do prefer to have a VPN when connecting on any public network so this'll be better than paying upwards of $100/year to a reputable VPN service provider.

The only thing I'd want a paid VPN for is to access geoblocked content, but, most services can now detect that you're using a VPN so paying for a VPN doesn't solve that problem (I'd love to pay for the geoblocked content but I'm not even allowed to do that since I no longer have means to pay for things with a registered Dutch bank account).

1 Like

Thank you to everyone who chimed in with advice. Now that I've got a working solution to host a vpn on an OpenWrt install I figure I should document the hardware configuration and what I've done. There seems to be a 30% to 40% bandwidth and latency penalty to using the vpn with the Raspberry Pi 3, e.g. 90 Mbps drops to 60 Mbps.

What I wanted to do is setup a vpn server (host) on my home network so that I would be able to access the internet from my home network even when I was not at home (mainly to bypass a rather disruptive proxy server on another network that causes numerous services on my cell phone to misbehave).

I didn't see the point of paying for a commercial vpn server when (a) I don't need anonymity and (b) I can't defeat geoblocks since the services that I would like to access with a geoblock are usually capable of detecting vpn access.

Hardware:
ISP > cable modem (Hitron 4680) > OpenWrt installed onto a Raspberry Pi with only its one built in Ethernet port

Software:
OpenWrt compiled specifically for the version of Raspberry Pi 3 that I've got (d/l from OpenWrt)

Configuration Steps:

  1. Setup OpenWrt using the OpenWrt instructions, turn off built-in DHCP server (I think) and set a fixed IP address to avoid having conflicting DHCP servers on the main network. Since the Raspberry Pi 3 has wifi (that I turned on) this creates a bridged or "dumb" AP.
  2. Use openvpn server setup guide to configure the openvpn server
  3. Configured SNAT to bridge the openvpn private network (virtual network? Not sure about term) to the IP address the OpenWrt device itself has on the LAN
  4. Download the ovpn key file from the server using sftp
  5. Modify ovpn key file so the IP address is the EXTERNAL IP address of my home network. Depending on how often my external IP address changes I may set up a solution that relies on a dynamic DNS service.
  6. Open up port 1194 on the ISP's modem/router combo and forward UDP traffic to the fixed IP address of the OpenWrt Pi.
  7. Use ovpn key file with the Android OpenVPN Client app to gain access to my personal vpn server

Note: Clients for most operating systems can be found here: https://openvpn.net/client/

I leave it as an exercise to the reader to discover the exact details. I think I've linked all the relevant pages in this thread.

FYI I did set up on a Linux Mint desktop with FileZilla as my sftp client and regular ssh for ssh. You could just as easily use the built-in sftp client from bash (the Terminal) using:

ssh -l root 192.168.YOUR.IP
sftp root@192.168.YOUR.IP

Network > Interfaces

Masquerading is just a check box on the LAN zone

But your solution also works

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