wiki:BuildingOnWindows

Introduction

WARNING: This documentation is obsolete and only applies to some historical versions of OpenVPN. The current instructions for building OpenVPN for Windows are available here.


The traditional way to build OpenVPN for Windows is using the "domake-win" script on Windows. It uses GNU autotools and GCC, either in a MinGW environment or inside a cross-compiling environment on *NIX. The former option is documented here, although at the moment (29th June 2011) the instructions are incomplete. You should refer to the script itself for more information. Also note that "domake-win" will run into trouble with newer software versions, such as OpenSSL 1.0.0*.

Because the "domake-win" buildsystem was found laborious to maintain, a new, relatively simple Python-based build system was written. This new build system allows building OpenVPN on Windows more easily. Fortunately the new build system only uses Visual Studio Express tools (nmake, compiler, linker, etc.), so learning VS's graphical user interface is not necessary. Full integration with Visual Studio should be possible, too.

Installing prequisites

Common

  • Windows Software Development Kit (Wikipedia page) may be necessary to build OpenVPN (verify!)
  • Windows Driver Kit (Wikipedia page) is required to build the TUN/TAP driver.
  • WinRAR or some other tool capable of extracting .tar.gz and .tar.bz2 archives is necessary to extract the LZO and OpenSSL release archives. You can skip this if you install GitExtensions and are not afraid of the *NIX command-line.
  • GitExtensions is a GUI designed to make working with Git easier on Windows. Among many things, it includes Git Bash, which gives you the most common *NIX tools on your Windows box. Git support is only needed if you want to use the latest development code.

Python-based buildsystem

  • Visual Studio 2008 Professional is used to build OpenVPN on Windows. Note that the free Express edition might not work. Also make sure you select "Typical installation", not "Full installation". Full installation installs x86 cross-tools which may cause nasty, hard to debug issues. See Troubleshooting section for details.
  • Python is required to build OpenVPN using the new buildsystem. The Windows installer does not seem to add the python.exe to the PATH, so you need to do it manually.
  • ActivePerl is required to build OpenSSL, which in turn is required to build OpenVPN. Look here for details. Probably a standard Perl installation would also do the trick.
  • NASM is required for enhancing performance of some OpenSSL crypto routines. All build instructions are in it's INSTALL file. After building it, you need to add nasm.exe to your PATH.

MinGW buildsystem

  • MinGW: C compiler and developer toolkit. Both are included in the standard MinGW installation executable. Note that MinGW buildsystem includes nasm and Perl by default.
  • Man2html is required to build pkcs11-helper using MinGW. Make sure the first line in man2html file is #!/bin/perl and copy it to /bin.

Building OpenSSL

Common steps

Download OpenSSL from here and extract it somewhere using tar.exe bundled with either GitExtensions? or MinGw? (see INSTALL.W32 why). Using the latest release ensures there are no (known) security holes in OpenSSL. For the most part you can then follow the instructions in INSTALL.W32 and INSTALL.W64 files.

After building OpenSSL (see below) copy the contents of OpenSSL install directory to <openvpn-build-root>/openssl.

Python-based buildsystem

Launch the Visual Studio 2008 Command Prompt, which can be found from the Start menu. Unlike the standard command prompt it has all the paths to VC binaries set correctly.

From within this command prompt you'll first configure OpenSSL using the provided Perl script:

C:\openssl-1.0.0> perl Configure VC-WIN32 --prefix=c:/<openssl-install-directory>

Next run the steps requiring the NASM assembler:

C:\openssl-1.0.0> ms\do_nasm

Next compile OpenSSL using the generated makefile:

C:\openssl-1.0.0> nmake -f ms\ntdll.mak
C:\openssl-1.0.0> nmake -f ms\ntdll.mak test
C:\openssl-1.0.0> nmake -f ms\ntdll.mak install 

MinGW buildsystem

Launch MinGW command prompt and go to <openssl-sources>. The usual process goes like this:

$ ./config
$ make
$ make test

OpenSSL installation has to be done manually using something like this:

$ mkdir -p /c/openssl/include /c/openssl/bin /c/openssl/lib
$ cp -r include/openssl /c/openssl/include/
$ cp apps/openssl.exe /c/openssl/bin
$ cp libcrypto.a libssl.a /c/openssl/lib

Building pkcs11-helper

Common steps

Download latest release of pkcs11-helper from http://www.opensc-project.org and extract it somewhere.

Python-based buildsystem

The install process for Visual Studio is described in the INSTALL file.

To build pkcs11-helper, do the following:

  • Go to pkcs11-helper-<version>/lib
  • Copy <openssl-install-directory>/lib/libeay32.lib to that directory - this is required by the linker
  • Run nmake -f Makefile.w32-vc OPENSSL=1 OPENSSL_HOME=<path-to-openssl-sources>

In theory this should do it. If you need to rebuild, clean up first with

$ nmake -f Makefile.w32-vc clean

and then repeat the above steps. Unless you're using 1.08 or later, you probably get this error message during build:

pkcs11h-threading.c(477) : error C2036: 'void *' : unknown size

If so, edit that file as suggested here. After this build should succeed, as long as libeay32.lib is present in the build directory.

OpenVPN is only interested is lib/libpkcs11-helper-1.dll and uses it when generating the NSI installer.

MinGW buildsystem

You need to link pkcs11-helper against OpenSSL libraries. To do this, launch MinGW command-line and do something like this:

$ openssl_home=/c/openssl
$ ./configure --prefix=/ --disable-crypto-engine-gnutls --disable-crypto-engine-nss PKG_CONFIG=true OPENSSL_CFLAGS="-I${openssl_home}/include" OPENSSL_LIBS="-L${openssl_home}/lib -lcrypto"

Building LZO

Common steps

The LZO library is required to build OpenVPN. Once you've unpacked the source package, open the B/00README.txt file to get an overview of the Windows build process.

Python-based buildsystem

If all goes well, you'll only need to run one .bat file:

C:\lzo-2.0.4> B\win32\vc_dll.bat

Note that this does not install lzo; in fact, you need to copy the relevant files to openvpn's build directory manually as shown below.

MinGW buildsystem

The usual autotools process applies here:

$ ./configure
$ make
$ make check
$ make test

OpenVPN build

Setting up dependencies

Python-based buildsystem

The new Python-based build system we're using in this article has gone through significant changes during late 2010 and early 2011. You're strongly encouraged to fetch latest Git development code using Git for Windows (Git shell) or GitExtensions (GUI). Check these instructions to see which Git URI to use. Alternatively get OpenVPN 2.2.0 or later, where all the major buildsystem changes have been implemented.

OpenVPN has several build and runtime dependencies that need to be placed into a strict directory hierarchy along with OpenVPN sources:

  • <openvpn-build-root>: root build directory, e.g. C:\openvpn-build
    • <openvpn-sources>: a directory containing openvpn sources (from tarball/zip/git)
    • tapinstall
      • 7600: copy of devcon.exe build directory. Can be found from C:\WINDDK\7600.16385.1\src\setup\devcon or similar, depending on the version of WINDDK. Note that in OpenVPN world devcon.exe is (confusingly) also known as tapinstall.exe. This directory is not needed if you use prebuilt TAP-drivers. NOTE: This directory gets copied during configuration phase (win/config_ti.py) to <openvpn-sources>/tapinstall.
    • pkcs11-helper: copy of pkcs11-helper build directory
      • lib: must also contain libpkcs11-helper-1.dll and libpkcs11-helper-1.dll.manifest files produced by pkcs11-helper build
    • openssl: copy of the openssl install directory
    • lzo
      • include: a copy of the include directory in the lzo build directory
        • lzo: the directory with actual lzo header files
      • bin: must also contain the lzo2.dll and lzo2.dll.manifest files generated by lzo build
      • lib: must also contain the lzo2.lib file generated by lzo build
    • Microsoft.VC90.CRT: a copy of C:\Program Files\MicrosofT Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT directory; the exact path may vary. Note that using the wrong version will cause issues on 32-bit or 64-bit Windows versions.
    • tap-prebuilt: this directory contain prebuilt, signed TAP-drivers and tapinstall.exe extracted from an OpenVPN installer. This is only needed if you don't build the TAP-drivers yourself.
      • i386: should contain 32-bit versions of the TAP-driver and tapinstall.exe
      • amd64: should contain 64-bit versions of the above
    • openvpn-gui: this directory should contain the openvpn-gui*.exe executable (see win/settings.in)
    • signtool: this directory should contain signtool.exe, which can be found from the Microsoft SDK directory (e.g. C:\Program Files\Microsoft SDKs\Windows\V6.0A\bin). However, it's Python wrapper (Sign class) is only available internally at OpenVPN Technologies, so you can skip this dependency.

MinGW buildsystem

Refer to old dependency packages to get an idea about the proper layout.

Setting build parameters

After setting up the directories, you should check if OpenVPN's build configuration files need modifications.

Python-based buildsystem

  • <openvpn-sources>\win\settings.in: build configuration for Python-based builds. Most build configuration - if any - is done in this file.
  • <openvpn-sources>\win\config.h.in: static header file, functionally the same as config.h generated by autotools; not usually modified.
  • <openvpn-sources\version.m4: contains TAP-driver version information. Normally there's no need to modify this.

NOTE: You may need to add vcvarsall.bat to PATH manually. On 64-bit platforms it usually lives in the C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC directory.

MinGW buildsystem

  • <openvpn-sources>/install-win32/settings.in: build configuration file for MinGW builds. Usually only this file needs to be edited.
  • <openvpn-sources>/version.m4: contains TAP-driver version information. Normally there's no need to modify this.

Building OpenVPN

Python-based buildsystem

Next fire up a Visual Studio 2008 Command Prompt and go to <openvpn-sources>\win directory. You should now build OpenVPN + the TAP driver using

C:\openvpn-build\openvpn-testing\win> python build_all.py --unsigned

This builds openvpn.exe, openvpnserv.exe and the TAP driver and copies the results to <openvpn-sources>\dist. The --unsigned switch disables TAP driver signing, which would not work anyways because the Sign Python module is only available internally at OpenVPN Technologies. In case you want to test new TAP-driver versions on Windows Vista/7 64-bit you need to self-sign them and jump through several hoops. If you intend to use signed TAP drivers from an existing OpenVPN installer, you can extract signed TAP drivers from an existing installer and skip building the TAP driver altogether:

C:\openvpn-build\openvpn-testing\win> python build_all.py --unsigned --notap

To clean up before or after the build, issue

C:\openvpn-build\openvpn-testing\win> python build.py clean

To see all available build options, use

C:\openvpn-build\openvpn-testing\win> python build_all.py --help

MinGW buildsystem

Build process is very simple:

$ cd <openvpn-sources>
$ ./domake-win

Watch what error it gives, fix and retry. Repeat until everything builds properly.

Using signed TAP-drivers from an OpenVPN installer

First extract TAP-drivers from an OpenVPN installer. Then do the following:

  • Place 32-bit signed TAP drivers and corresponding tapinstall.exe to <openvpn-build-root>\tap-prebuilt\i386
  • Place 64-bit versions to <openvpn-build-root>\tap-prebuilt\amd64

Packaging OpenVPN

Python-based buildsystem

Once OpenVPN build is finished, you may want to make an installer executable. OpenVPN installers are packaged using NSIS, which you can download from here. The buildsystem, or more correctly <openvpn-sources>\win\make_dist.py - puts most of what the NSI script (<openvpn-sources>\win\openvpn.nsi) needs to <openvpn-sources>\dist. The NSI script still (as of 2.2-RC2) pulls some files from directories other that dist, but that will be fixed later.

OpenVPN installer is driven by the <openvpn-sources>\win\openvpn.nsi NSI script, which has to be loaded with the MakeNSIS application to generate an installer. If the <openvpn-sources>\dist directory has been properly set up, you should not encounter any errors. However, if MakeNSIS complains about missing files, make sure the <openvpn-sources>\dist directory contains all of the packaging dependencies:

  • amd64
    • OemWin2k.inf
    • tap0901.cat
    • tap0901.sys
    • tapinstall.exe
  • bin
    • Microsoft.VC90.CRT
      • msvcr90.dll
      • Microsoft.VC90.CRT.manifest
    • libeay32.dll
    • libpkcs11-helper-1.dll
    • lzo2.dll
    • openssl.exe
    • openvpn-gui-1.0.3.exe
    • openvpn.exe
    • openvpnserv.exe
    • ssleay32.dll
  • i386
    • OemWin2k.inf
    • tap0901.cat
    • tap0901.sys
    • tapinstall.exe
  • samples
    • client.ovpn
    • sample.ovpn
    • server.ovpn

MinGW buildsystem

Using unverified TAP-drivers on 64-bit Windows

The 64-bit versions of Windows Vista/7 (and later) only allow installing drivers with certificates that have Microsoft as CA. Or, in other words, drivers verified by Microsoft. Installation of unsigned nor unauthorized device drivers is not allowed by default. This is very problematic when testing the TAP-driver, as signing it after every small change makes no sense. Fortunately there are two ways to work around this:

  • Self-sign the TAP-driver and configure Windows to accept self-signed (unauthorized) drivers.
  • Switch on Test mode during boot. This allows loading unsigned drivers.

To get a good idea how this all works, read these two documents:

Method 1: Self-signing the TAP-drivers

IMPORTANT: so far (18th March 2011) I have not managed to make Windows 7 64-bit accept self-signed certificates created on WinXP 32-bit. Until this is fixed, please use method 2 to test 64-bit TAP-drivers.

Creating a test certificate on build computer

Creating a test certificate (and it's keystore) is easy if Visual Studio is is installed. Open the Visual Studio command-line and issue

Makecert -r -pe -ss teststore -n “CN=OpenVPN project test labs” teststore.cer

For details on the syntax see Makecert.exe reference; for higher-level details look here.

Installing the test certificate to build and target computers

Both build and target computers need to have the test certificate in their keystores. The build computer needs it for signing the driver catalog with signtool.exe. The target computer, on the other hand, needs to have the certificate installed or it won't trust the driver and won't allow loading it to the kernel.

In both cases the certificate is imported using certmgr.exe:

certmgr.exe -add teststore.cer -s -r localMachine root
certmgr.exe -add teststore.cer -s -r localMachine trustedpublisher

You can also launch certmgr.exe without parameters and use the certificate import wizard. Although usage of certmgr.exe is straightforward, it is included (only?) in the massive Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 package, which you need to install.

Creating the catalog file using makecat

There are two ways to create the catalog file that contains hashes of the TAP-driver files. It is this catalog file that is signed and verified by Windows kernel. The first option is to create a catalog definition file (.cdf) with a text editor and generate the real catalog file from it using MakeCat.exe. The problem with this approach is that makecat does not warn about errors in the .cdf file. This results in everything looking just fine, but failing when loading the driver into the kernel.

Nevertheless, if you want to try this approach, go to <openvpn-sources>/dist/amd64 after building There you'll find tap0901.sys and OemWin2k.inf files. Create a catalog definition file (e.g. tap.cdf) with a text editor; it contents should be similar to the one below:

[CatalogHeader]
Name=tap0901.cat
PublicVersion=0x00000010
ResultDir=.\
EncodingType= 

[CatalogFiles]
tap0901.sys=.\tap0901.sys
OemWin2k.inf=.\OemWin2k.inf

Make sure you have a linefeed at the end. Please note that this file did not work properly for unknown reasons, and the .cdf file format seems mostly undocumented. Once the catalog definition file is finished you can create the real catalog file using makecat:

makecat -v tap.cdf

Creating the catalog file using inf2cat

Inf2Cat.exe is a tool used to generate an unsigned catalog file from driver's INF file. It should be more easier to use than makecat, as it can automatically generate a .cat file with correct syntax. This tool is included in the Windows Driver Kit, which you have to install. Use it like this:

cd C:\WINDDK\\7600.16385.1\bin\selfsign
Inf2Cat.exe /driver:<openvpn-sources>\dist\i386 /os:XP_X86
Inf2Cat.exe /driver:<openvpn-sources>\dist\amd64 /os:Vista_X64

Where <openvpn-sources> is something like C:\openvpn-build\openvpn-macbook.

Signing the catalog file

Now sign the catalog file with signtool:

signtool sign /v /s teststore /n "OpenVPN project test labs" tap0901.cat

As long as the test certificate has been imported using certmgr.exe (see above), this command should work.

If you want, repeat this process for 32-bit version of the TAP-driver starting from <openvpn-sources>/dist/i386.

Method 2: Enabling test mode on target computer

Test mode boot setting allows loading test-signed drivers to the Windows kernel. You can use the Driver Signature Enforcement Overrider tool to enable it. After a reboot you should see

Test Mode
Windows 7
Build xxxx

Or similar at bottom left corner of the desktop. Windows kernel should now load unsigned drivers without any issues.

Troubleshooting

Compiler warnings during OpenSSL build

When building OpenSSL you're most likely encounter issues with trivial compiler warnings stopping the entire build. To circumvent this remove the /WX flag in the makefile as suggested in INSTALL.W32 file. This is harder than it seems for two reasons:

  • The correct makefile is ms\ntdll.mak (not the Makefile in build root)
  • You need to use Wordpad or other UNIX linefeed-aware editor to open and save the makefile

VS 2008 cross-tools issues during OpenSSL build

OpenSSL build is likely to break at several places if you're running Visual Studio 2008 x64 Cross-Tools Command Prompt instead of plain Visual Studio 2008 Command prompt. Consider reinstalling Visual Studio without cross-tools if you encounter either of these errors:

  • fatal error LNK1112: module machine type X86 conflicts with target machine type x64 (in the middle of the build)
  • Linker can't find link.obj (at the end of the build)

Issues with self-signed TAP-driver certificates

Certificates Console can be used to view and move around certificates stored for the local computer or the current user. The Device Manager can be used to view driver status and the cause of malfunctions. Event viewer can be used to view Code integratity events, including failures to verify driver signatures. These can be found from Applications and Services Logs -> Microsoft -> Windows -> CodeIntegrity?.

File vcvarsall.bat not found

Sometimes - not always - the "Visual Studio Command Prompt" might not find vcvarsall.bat, which is needed to build OpenVPN using the Python-based buildsystem. In this case you can add it to PATH manually. The path is C:\Program Files (x86)\Microsoft Visual Studio 9.0\vc or similar.

Code debugging

Visual Studio (2008+ at least) has a Just in time debugger that - by default - launches automatically when a binary crashes. This can be very useful when debugging openvpn.exe, as the debugger show on which line the error occured, which files it tried to access, etc.

To use the debugger, you need to compile openvpn.exe with appropriate debug flags. This is done by uncommenting the enabling PRODUCT_OPEVPN_DEBUG in win/settings.in, as shown below:

# Build debugging version of openvpn.exe
!define PRODUCT_OPENVPN_DEBUG

In most cases, full uninstall/reinstall procedure is not necessary. If that's the case, you can quickly test the binary like this from Git Bash with administrator rights (adapt as necessary for different shells):

$ cd /C/Program\ Files\ \(x86\)\OpenVPN\config
$ cp <openvpn-sources>/dist/bin/openvpn.exe ../bin/
$ ../bin/openvpn.exe --config <your-openvpn-config-file>

If/when the process crashes, the Visual Studio JIT debugger pops up. Provided you built OpenVPN with debugging information (see above), you should be able to pinpoint the issue fairly easily.

External links

Last modified 3 months ago Last modified on 04/24/14 11:19:41