Unlike those enterpris-y VPN solutions that offer very easy ways to install them on all laptops and phones, OpenVPN (at least the community edition) provides a MSI, a service, and nothing else. This blog shares my experience in deploying always-on OpenVPN over group policy with zero user interaction.
The deployment consists of three parts:
- Deploy OpenVPN profiles and certificates
- Set OpenVPN service registry (strictly speaking: optional)
- Deploy unattended MSI install
This assumes you have a working OpenVPN setup and PKI.
Before replicating the settings over your machines, install OpenVPN (full
installation is OK) on a test machine and run
C:\Program Files\OpenVPN\bin\openvpn.exe \path\to\config.ovpn
to test it.
Note that I am using cryptoapicert "SUBJ:YUUTA.MOE"
for the client to obtain
the machine certificated issued by ADCS. You may do something else (like hard
coding the private key file), but it may not scale very well. This option is
actually not very easy to use because it does not support searching certs by
ADCS certificate template (see
Patch
). It does supports filtering with ISSUER:
, but it turns out that it is
always selecting some mysterious machine certificates that are located on a
smart card (and thus prompting me to insert the smart card, which I don’t have).
There is also no debug logs to show which certificate it is trying to get.
Anyways, the code is at
cryptoapi.c:203
. I am just using subjet match, which is not very well, but it works in my
simple environment.
Directory structures used in this deployment:
C:\Program Files\OpenVPN\
: binaries.C:\VPN\vpn.ovpn
: Profile.C:\VPN\ca.crt
: PEM-encoded root CA.C:\VPN\ca.crt
: PEM-encoded root CA.
Deploy profiles #
This step is basically group policy file deployment. Just use the Files policy in Computer Configuration > Preferences > Windows Settings. The good-old Windows XP GUI made my great-great-great-grandmother happy. lol.
Nothing to point out here. Make sure you use UNC path. The directory will be automatically created it not existing, so no need to do that.
Set registry #
OpenVPN ships with a very nice OpenVPNService
which automatically reads some
system profiles from a designated location and starts them. This requires no
user interaction (and the OpenVPN GUI component is completely unused as well).
This service best fits in our deployment senario, and it is also automatically started once installed, so no need to enable that service manually over GPO.
By default, it reads configuration files in
C:\Program Files\OpenVPN\config-auto\*.ovpn
and writes logs to
C:\Program Files\OpenVPN\log\*.log
. This works, but in my senario I want to
tweak that a little bit, so it uses the C:\VPN
path.
This is supported on their
Docs
. The only thing needed is the keys in HKEY_LOCAL_MACHINE\SOFTWARE\OpenVPN
.
Read that docs yourselves and change the location, or you can keep the default.
The good-old-XP-style GPO registry policy is your friend. No worries if
installing the MSI (which happens at boot, after the registry policy is applied)
will reset the values - it won’t, but uninstalling it will delete the whole
OpenVPN
key. Keep that in mind.
Install MSI #
Group policy MSI deployment sucks, but I don’t have SCCM, so that is the only choice. The routine MSI deployment stuff went pretty normal, until I need to specify the components to install.
Yes, the MSI by default installs lots of documentation and also the naughting
GUI with it. Whenever a user logs on, the OpenVPN gui will prompt a dialog
telling that there is no per-user configuration set. I definitely don’t want
anything user-interactive, so I have to remove that component. This is done by
the ADDLOCAL
variable when installing the MSI.
It turns out that you can use the MSI logging function to see the actual value
of that variable. Just do msiexec /i OpenVPN.msi /l*v log.txt
and choose your
components then install, and you will see the selection in the log
Lastly you have to tell GPO to use that variable. This is actually pretty
complicated (probably how all MSFT products are designed). You need to use a
tool called Orca from Windows SDK, load the MSI, create a transformation, set
the ADDLOCAL
property, generate a binary MST file, and finally load that file
into GPO.
So basically you install Windows SDK with the MSI component installed. This does
not install Orca directly, but instead it extracts an Orca MSI into
C:\Program Files\Windows Kits\10\
. Install that, and you will find Orca in
program files x86 Source.
Open that, and load the MSI. Then click on menu Transform -> New Transform.
Then locate to the Property
table and right-click the list in the right pane,
and click on Add Row.
Type ADDLOCAL
and your value in it.
Finally click on Transform menu again, Generate Transform, save that MST to your sysvol.
Lastly, go to the GPO software installation item property, add the MST.
See https://woshub.com/deploy-software-via-gpo/ for some screenshots.
That’s it, hope everything works.
Troubleshooting: DC sync #
You can’t wait for DC sync. For LDAP sync, use repadmin /syncall /AdeP
.
Remove P
if you are running on a RODC. This does not seem to work all the
time, so you can click on the sync menus in AD Sites and Services MMC to achieve
eventual consistency.
For sysvol:
Sync-DfsReplicationGroup -GroupName "Domain System Volume" -SourceComputerName From -DestinationComputerName To -DurationInMinutes 5 -Verbose
Troubleshooting: Wait for network #
You definitely saw something like “the group policy client side extension software installation was unable to apply” before.
Enable Computer Preferences > Templates > System > Logon > Always wait for the network at computer startup and logon.
And reboot multiple times? (I’m on WiFi)
Troubleshooting: msiexec problems #
“This installation package could not be opened. Verify that the package exists
and that you can access it, or contact the application vendor to verify that
this is a valid Windows intaller package.” when executing msiexec /i
.
Do not use msiexec /i .\OpenVPN.msi
. Remove the .\
part does the trick.
Or have a look at msiexec policies? I used to have problems with them.