Your phone shows the tunnel as connected, the client reports a private address, and the first page still hangs halfway through loading. That combination sends most people into cipher settings and CPU temperatures, where nothing is actually wrong. The tunnel came up, so negotiation finished; what failed is the step after it, when the server tries to hand client packets to the internet. Walk the same path those packets take and the mismatch is usually visible in one line of the NAT table.

Start from what the client can and cannot reach

From the connected client, load a page that lives on the public internet and note whether it fails instantly or stalls partway. Then open a resource on the VPN server's own private address and compare the two results.

A tunnel address that answers pings while public sites time out is the signature of a forwarding or translation problem, not a broken handshake. The client's own status panel cannot tell those apart, because it only knows that the control channel is up. Check the tunnel interface on the server with ip -br addr show tun0 and confirm the client's assigned address falls inside the pool you configured. If the pool and the client address disagree, fix that first, because every rule below matches on the pool.

Next, ask the server which interface it would use to reach a public address. ip route get 203.0.113.9 prints the chosen device and source on its first line. Write that device name down, since it is the value the NAT rule must contain.

Read the rule that decides whether packets leave

MASQUERADE rewrites a packet only when the packet departs through the interface named in the rule. A rule scoped to a wired device does nothing for traffic that leaves over Wi-Fi, and the packet keeps its private source address all the way to the upstream router. That router has no route back to your tunnel pool, so it drops the reply, and the client sees a connection that opens and then dies. The symptom scales with how much of the page arrives before the first reply is needed.

List the live table and read the out-interface column rather than skimming for the word MASQUERADE. The add-form output is easier to compare than a formatted listing:

ip -br addr show tun0
ip route get 203.0.113.9
sudo iptables -t nat -S POSTROUTING

On a Raspberry Pi that once used Ethernet and now uses Wi-Fi, the stale name is almost always the whole story. The installer recorded whatever device was present at setup, and the saved ruleset replays it at every boot. Compare the device from the route lookup with the one in the rule before changing anything else. If they match, the interface is not your problem and you should move to the counters in the last section. If they differ, the fix is a one-word edit in the persistence file.

Correct the saved ruleset, not just the running one

Editing the live table alone survives until the next reboot, which is exactly long enough to convince you the problem is fixed. The rules that come back at boot live in a file that a firewall persistence package reloads. On Debian-based Pi images that file is usually /etc/iptables/rules.v4.

Take a copy before touching it, then replace the out-interface on the MASQUERADE line with the device you recorded, for example -o wlan0 instead of -o eth0. Keep the source range as it is unless your client pool changed. Reload and confirm the rule now names the right device:

sudo cp /etc/iptables/rules.v4 /root/rules.v4.bak
sudo iptables-restore < /etc/iptables/rules.v4
sudo iptables -t nat -L POSTROUTING -v -n

Two adjacent settings are easy to forget. sysctl net.ipv4.ip_forward must report 1, and the upstream router must not be filtering private source addresses on its own.

Prove the rule fires, then isolate what is still slow

Counters are the only honest proof that a rule matched. Run the verbose listing, start a download on the client, and run it again. The packet and byte columns beside your rule should climb, and a rule that stays at zero is still not matching. If the counters move but pages still fail, compare the source range against the actual pool with grep -n "^server " /etc/openvpn/server.conf. If they move and pages load but throughput is poor, translation is done and the remaining problem is elsewhere.

Compare two transfers from the same client, one to a host on the local network and one through the tunnel to that same host. Slow in both cases points at the Pi's uplink or Wi-Fi link, not the VPN. Slow only through the tunnel points at MTU and retransmissions, which you can inspect with ip -s link show tun0 before changing any crypto setting.

To undo the experiment, restore the copy and reload it again, then confirm the original rule and its counters are back. Write the egress device and the reload command into the server notes, because the next uplink change rediscovers the same mismatch. A rule that names the wrong device stays invisible until traffic needs it.

Amanqephe ahlobene