[SOLVED] Trying to install OpenVPN results in networking issues

Hello,

I want to install a home-server for several purposes, VPN being one of them.
So I bought a RaspberryPI-4B and installed FreedomBox Stable on it, using the rpi-imager (this is how I found out about the existence of freedombox, I just wanted something debian based and easy to setup; I’m just some software devoloper who knows the basics of administrating a server and networking, but not the advanced stuff).

After setting up the freedombox on the Pi, I have installed the OpenVPN App using the FreedomBox-UI (Website) next, and (after some dynDNS and router port-forwaring stuff unrelated to the server itself) I could log into the VPN from my mobile phone, but the only server that is reachable using the VPN is the freedombox itself (using the tun0 IP 10.91.0.1), no other server from the network is reachable. This is not expected behaviour, is it? (I’m actually not sure, I have not found any documentation about what is supposed to be reachable when OpenVPN is installed, only that it should “just work”. For now I assume that this is not expected behaviour and I should be able to reach other servers in the network when OpenVPN is set up.)

After some searching why this is, I found that the VPN only works when there is at least one interface that is part of the external zone in the firewall. This was already the case, eth0 was already part of the external zone in the firewall UI. So that is not the reason.

At this point I left the path of what a non-techy user is expected to do and tried to solve this by connecting via ssh to it and messing with things. :wink:

First I activated IP packet forwarding:

echo 1 > /proc/sys/net/ipv4/ip_forward

That had no effect.
Then, after lots of googling, I stumbled over this:

# firewall-cmd --permanent --new-policy intToExt
# firewall-cmd --permanent --policy intToExt --add-ingress-zone internal
# firewall-cmd --permanent --policy intToExt --add-egress-zone external
# firewall-cmd --permanent --policy intToExt --set-target ACCEPT
# firewall-cmd --reload

(from here: filter_FWD_internal_REJECT internal zone -> external zone traffic is filtered · Issue #1015 · firewalld/firewalld · GitHub)

This finally allowed me to reach other servers in the network over VPN… Until the next reboot of the server that is. At that point, things got weird.

When the server booted up the next time, it had (seemingly) no networking whatsoever. So I plugged it into a keyboard and “monitor” (a.k.a. A HDMI capture card on my laptop) and tried to see what was happening. With tcpdump -v eth0 I could see the incoming connection attempts to the sshd server incoming, but they did not reach the sshd process. Just a series of [SYN] packets trying to open a TCP connection without a response from the ssh server. From the box itself I could connect to localhost via ssh without problems (ssh localhost), but not from the outside. Same story for the webserver: A curl http://localhost/ works fine, but when attempting a request from another device (my laptop), it ends with the [SYN] packages reaching the tcpdump on the freedombox, but not the webserver process (apache I presume).

To solve this, I tried several things from deactivating the firewall service firewalld stop (resulting in an empty nft ruleset) (And yes, I learned a lot about nftables that day) to deactivating IPv6 on the server.
And after bashing my head against the wall for several hours, I desperately tried to remove the tun0 device (ip link delete tun0) and this finally restored normal networking on the server. Both ssh and http(s) connections were possible again. Why in the world does the existance of the tun0 interface block packets from reaching their processes?

I can restore the broken state of the server just by rebooting it, and “fix” it by removing the tun0 interface again.

This is my current status. Can anybody tell me why this is happening? How do I make OpenVPN work so that the whole network is reachable and without networking getting broken?

Thank you for any answers.

2 Likes

Hi @addiks

My Pi is connected to a router/modem so technically I dont need an external network. In my experience, I believe Pi’s internal workings (blolbs or whatever it is), messes up when an external network is defined. Before proceeding, I removed all my external networks, leaving my setup win only internal network.

From there, here’s how I got my configuration working.

Good luck.

Status Update:

Thanks to the helpful folks over at the #debian channel on the matrix server, I figured out yesterday that the server was indeed routing all traffic into the tunnel because of a wrong route on the server:

# ip route
default via 192.168.2.1 dev eth0 proto dhcp src 192.168.2.143 metric 100 
10.91.0.0/24 via 10.91.0.2 dev tun0 
10.91.0.2 dev tun0 proto kernel scope link src 10.91.0.1 
192.168.2.0/24 via 10.91.0.2 dev tun0 # This route caused the issue
192.168.2.0/24 dev eth0 proto kernel scope link src 192.168.2.143 metric 100 

This was resolved using the command ip route del 192.168.2.0/24 via 10.91.0.2 dev tun0

After researching where this route came from, I found out (by trial and error) that the origin of that route was a wrongly (?) configured route in the /etc/openvpn/freedombox.conf file:

route 192.168.2.0 255.255.255.0

I probably copied that line from some forum-post somewhere without really understanding what it does and so created that issue. Commenting that line out resulted in networking being available again after a reboot of the server.

Now my local networking works reliable again, but the VPN still does not work as intended.
When connecting to the VPN from my (Android) Phone, I can browse the Internet but cannot reach anything in the network (apart from the freedombox itself using it’s tun0 IP address 10.91.0.1).

When I monitor all traffic on the server’s tun0 interface using nft monitor trace using this ruleset …

table ip filter {
	...
	chain trace_chain {
		type filter hook prerouting priority raw - 1; policy accept;
		iif "tun0" meta nftrace set 1
	}
}

… I can see traffic from the phone to the general internet being routed over the freedombox VPN. But any traffic directed at the local network (192.168.2.*) does not show up at all, it looks like the android phone does not even try to send that traffic over the VPN, even though “Redirect all Traffic over the VPN” is activated in the config.

I’m currently trying to convince the phone to route traffic for the local network over the VPN with something like this in the OpenVPN server config:

push "route 192.168.2.0 255.255.255.0 192.168.2.1"

But so far I did not have any luck with that. If I understand this line right, it should tell the OpenVPN Client to route all traffic to the network 192.168.2.* over the VPN with a default gateway of 192.168.2.1 (my router), but the traffic does not even appear on the tun0 device of the OpenVPN Server.

I’m searching the internet for a detailed reference on what the push "route ..." does exactly and what it’s exact syntax definition is, but so far I have not found much. I have to puzzle my understanding of this together from a bunch of posts on superuser.com, stack-overflow and several forums. Where is the official documentation for this?

I also tried to somehow look into the routing-table of the android device, but that seems to be impossible without rooting the device and connecting to it with adb, so I have no idea what is actually happening on my phone.

@Ged296123
Thank you for your reply. If I understand you correctly, you are suggesting that I execute these commands:

firewall-cmd --zone=internal --add-masquerade
firewall-cmd --zone=internal --add-masquerade --permanent

I actually did stumble upon that post and executed these commands a few days ago before making the big mistake with the OpenVPN-route (see above), but it had no effect. I also suspect that these commands would have no effect now because I moved my tun0 device from the internal zone into the trusted zone so that the firewall stop’s dropping all packages coming from tun0 which worked. Before that I could not even browse the internet using the VPN.

Status Update #2:

This is definitely an issue with the Android OpenVPN Client (Or Android itself).

After looking around for a while I found out that I can increase the verbosity of the logs in the android client. Near the bottom of that log I found this lines:

...
Routes: 10.91.0.0/24, 10.91.0.4/30
Routes excluded: 192.168.2.0/24
...

So it was, for some reason, excluding the route to the local network. That explains why the local network cannot be reached.

So I poked around the settings, but it turned out that the setting Use default Route (Redirects all Traffic over the VPN) is already turned on, and deactivating Bypass VPN for local networks did also not solve the issue. Only after turning off Use default Route and entering the route 192.168.0.2/24 manually by hand into the client did the issue finally go away, the local network was finally reachable over the VPN.

Why does the client refuse the route 192.168.0.2/24 regardless of configuration unless entered manually? Is this a bug in the client?

Anyway, my setup now works completely and I can deal with entering the route manually as a workaround. I guess this topic is now solved. Hopefully someone else can learn something from my journey. Thanks for reading. :slight_smile:

2 Likes

Thank you so much for posting this! I am having similar trouble with getting OpenVPN setup on my freedombox. I keep struggling at the moment with forcing it to use IPv4 only…but that’s a topic for different forum. I learned so much from your post, thank you again!

It’s good to hear that you found a solution to the OpenVPN issue. But also great to hear that getting FreedomBox listed in Raspberry Pi Imager is already having an impact!

5 Likes