Tag: pfsense

Fixing pfSense 22.05 to 23.01 upgrade breaking OpenVPN tunnels

After upgrading pfSense from 22.05 to 23.01, some users report that OpenVPN tunnels fail to establish with a “Cannot open TUN/TAP dev /dev/tun*: No such file or directory” error. I, too, ran full speed into this issue during what initially looked like it should have been a relatively straight-forward upgrade. In my case, I got that error soon after “Peer Connection Initiated” for a case where the pfSense instance acts as an OpenVPN client.

One reason why this can happen is because under some conditions, the linker.hints file isn’t refreshed to match an upgraded kernel. Since the upgrade from 22.05 to 23.01 includes an upgrade from FreeBSD 12 to FreeBSD 14 as the underlying operating system, naturally the kernel is also upgraded.

To fix this in the short term, one can use the web interface command line tool (found as Diagnostics > Command Prompt in the menu) to manually regenerate the linker.hints file by running the command:

kldxref /boot/kernel

and rebooting the instance. This is suggested by Netgate employee stephenw10, and several affected users have subsequently confirmed in that forum thread that doing so solved the problem. It also solved the problem for me.

Supposedly a fix to automatically regenerate the linker.hints file on each reboot will be included in the next scheduled pfSense update, which will very likely be 23.05.

It’s just too bad that this still isn’t mentioned in the 23.01 release notes and errata, which is where information about this type of potential issues should be collected. That way, users wouldn’t have to go digging around the forums after the fact when they are hit by an already-known issue.

Exposing pfSense uplink information to LAN hosts

Sometimes, it’s beneficial to be able to programatically tell from a client which uplink connection is being used by pfSense to route traffic, or simply have access to the current value of some property that maps to each respective uplink. This can be the case if, for example, there is a desire to pause certain network-intense activities running on a client when a metered, data-capped or lower-bandwidth uplink (for example mobile broadband) is in use.

Unfortunately, this information is not readily exposed in any way I have been able to find. However, it also isn’t that difficult to get at.

This post is aimed mainly at simple primary/backup multi-homed configurations, not load-balancing configurations or primary/backup load-balanced configurations. Some adjusting may be required if your multi-homed pfSense configuration includes load-balancing.

On FreeBSD (on which pfSense is based), the way to print the routing table is netstat -r -n. Add an additional either -4 or -6 to print only the IPv4 or IPv6 routing table, respectively; by default, it prints both.

The uplink that at each time is being used by pfSense will typically be the default IP route. The default route, when printing the routing table through netstat -r -n, will have a first field with the value default.

To view the full output through the web interface, use Diagnostics > Command Prompt > Execute Shell Command. Be very careful; a typo or errant whitespace can be critical!

pfSense also includes awk, which is quite handy for filtering table-like text output such as that produced by netstat. We are primarily interested in the “Netif” (network interface) column of the output, for the line where the “Destination” field (the first one) has the value default.

Log in to the administration interface. If you haven’t already installed the Cron package, do so first through System > Package Manager.

Once Cron is installed, go to Services > Cron > Settings, and add a new entry. The command to be executed should be something very similar to:

/usr/bin/netstat -rn4 | /usr/bin/awk '($1 == "default" && $4 == "mvnetaMM") { print "ONE" } ($1 == "default" && $4 == "mvnetaNN") { print "OTHER" }' >/usr/local/www/uplink.local.txt

This will write ONE to /usr/local/www/uplink.local.txt if the default route is through the interface mvnetaMM, and will write OTHER if the default route is through mvnetaNN. The directory /usr/local/www, in turn, is exposed to local clients as / by the built-in administration interface web server.

You can add additional mappings (from physical interface name to an arbitrary value) on the same form if you have additional uplink interfaces. Look at Interfaces > Assignments in the administration web interface to see which physical interface name maps to which mnenomic name, and then from there decide what to expose if the default route is through that interface.

To avoid issues with quoting and encoding, I suggest only using US-ASCII alphanumeric characters in the awk print statements.

Do note that because Cron can only be configured to execute commands at a minute granularity, there will be a slight delay before a change in the default route is reflected in the file that is accessible from clients.

With the cron job in place, make the client request /uplink.local.txt from the firewall (no authentication required!) and take whatever action is desired based on its contents, or the change in its contents. For example, on Linux, you might do:

wget -q -O - --no-check-certificate https://pfsense.home.arpa/uplink.local.txt


curl -s --insecure https://pfsense.home.arpa/uplink.local.txt

The --no-check-certificate or --insecure respectively is needed if the respective tool does not trust the TLS certificate for the pfSense host. If your client trusts the certificate, it’s better to remove that part.

Powered by WordPress & Theme by Anders Norén