Getting OpenVPN working on Ubuntu 22.04 LTS with CAC or PIV cards

So, once again, the OpenSSL team has broken something and is spouting self righteous indignation about how they are “right” to prevent the cached key updates and blah blah blah instead of actually fixing the problem. In the abstract, I’m sure that it makes sense to return const key objects, but it doesn’t if you’re using PIV or CAC cards, which apparently not a single one of the current OpenSSL team does. That said, let’s worry about fixing the problem instead of arguing the abstract.

Below you will find a series of steps to build a custom compiled version of OpenVPN and all the helper applications that allow it to work with PIV and CAC cards. Until (or if) Ubuntu / OpenSSL decides to fix this fiasco, these should get you through. Also, I built this stuff as root. Feel free to build all the stuff as your user and then sudo make install if that’s your jam.

Step 1: Install the precursors to allow your system to compile and build the software.

apt install liblzo2-dev liblz4-dev git build-essential automake autoconf autogen libtool autotools-dev clang libpcsclite-dev libpam0g-dev

Step 2: Install a custom version of OpenSSL (1.1.1o as of this writing)

wget https://www.openssl.org/source/openssl-1.1.1o.tar.gz
tar -xvzf openssl-1.1.1o.tar.gz
cd openssl-1.1.1o
./config --prefix=/opt/openvpn-custom --openssldir=/opt/openvpn-custom/etc
make -j 16
make install

Step 3: Install pkcs11-helper that is built against the OpenSSL you just built and installed.

wget https://github.com/OpenSC/pkcs11-helper/releases/download/pkcs11-helper-1.29.0/pkcs11-helper-1.29.0.tar.bz2
tar -xvzf pkcs11-helper-1.29.0.tar.bz2
cd pkcs11-helper-1.29.0
PKG_CONFIG_PATH="/opt/openvpn-custom/lib/pkgconfig/" ./configure --prefix=/opt/openvpn-custom
make -j 16
make install

Step 4: Install OpenSC built against the OpenSSL and pkcs11-helper you just built and installed.

wget https://github.com/OpenSC/OpenSC/archive/refs/tags/0.22.0.tar.gz
tar -xvzf 0.22.0.tar.gz
cd OpenSC-0.22.0
./bootstrap
PKG_CONFIG_PATH=/opt/openvpn-custom/lib/pkgconfig/ ./configure --prefix=/opt/openvpn-custom
make -j 16
make install

Step 5: Install OpenVPN built against all that other stuff you just built and installed.

wget https://swupdate.openvpn.org/community/releases/openvpn-2.5.7.tar.gz
tar -xvzf openvpn-2.5.7.tar.gz
cd openvpn-2.5.7
PKG_CONFIG_PATH="/opt/openvpn-custom/lib/pkgconfig/" ./configure --enable-pkcs11 --prefix=/opt/openvpn-custom
make -j 16
make install

Step 6: Add custom library path to the system so it can find them when you run the custom OpenVPN.

echo "/opt/openvpn-custom/lib" > /etc/ld.so.conf.d/openvpn-custom.conf
ldconfig

Step 7: Validate that the OpenVPN build can see your card when you instert it.

/opt/openvpn-custom/sbin/openvpn --show-pkcs11-ids /opt/openvpn-custom/lib/opensc-pkcs11.so

Step 8: Modify the path to the pkcs11-providers in your .ovpn (or whatever) file.

Modify your .ovpn file to change the line:
pkcs11-providers /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so

To:
pkcs11-providers /opt/openvpn-custom/lib/opensc-pkcs11.so

Step 9: Profit!

You should be good to go for connection with OpenVPN from the command line. There may be a way to specify which OpenVPN binary is used from the GUI in Ubuntu, but I didn’t need to go that far as my users are command line savvy. Ok, so I lied. I looked into it for you, the reader. It’s worse than I thought. Apparently the path is HARD CODED into the Gnome-NetworkManager-OpenVPN source with this silliness (in https://github.com/NetworkManager/NetworkManager-openvpn/blob/master/properties/nm-openvpn-editor.c):

static const char *
nm_find_openvpn (void)
{
	static const char *openvpn_binary_paths[] = {
		"/usr/sbin/openvpn",
		"/sbin/openvpn",
		NULL
	};
	const char  **openvpn_binary = openvpn_binary_paths;

	while (*openvpn_binary != NULL) {
		if (g_file_test (*openvpn_binary, G_FILE_TEST_EXISTS))
			break;
		openvpn_binary++;
	}

	return *openvpn_binary;
}

So the simplest way to make this happen is to simply:

mv /usr/sbin/openvpn /usr/sbin/openvpn.old
ln -s /opt/openvpn-custom/sbin/openvpn /usr/sbin/openvpn

I have thoughts about why this hasn’t been broken out into a separate Gnome default value… but hey, can’t argue with it working.

I hope this helps you avoid the five hours of effort it took me to figure this out. -Phorkus.

mm
About

Phorkus is just this guy...

Leave a Reply

Your email address will not be published. Required fields are marked *

*