For building with Visual Studio 2008 please refer to BuildingOnWindows.
For building with MinGW please refer to Windows下编译OpenVPN 2.1.1.

The building procedure is very similar with building with VS 2008 but slightly different.

Why Build OpenVPN Yourself
  1. The official build does not support saving or reading username & password from file.
  2. The official build does not support tunneling through IPv6.
  3. You may want to use your own logo or add customized configuration files if you are offering VPN service.
Prequisites
A Clean System

Windows XP SP3 or later versions are required. I cannot suggest you to install a clean system in a virtual machine.

Visual Studio 2010

Express edition is OK and Professional is better. Note there is a small difference in the building procedure between Express edition and Professional / Premium / Ultimate editions. Express edition does not come with Microsoft Visual C++ 2010 Redistributable Package, you have to install it manually.

Python

The new OpenVPN Windows build system is written in Python. Version 2.7 is fine. The Windows installer does not seem to add the python.exe to the PATH, so you need to do it manually.

ActivePerl

ActivePerl is required to build OpenSSL, which in turn is required to build OpenVPN.

NASM assembler

Also required by OpenSSL. And you'll need to add nasm.exe to PATH as well.

Building OpenSSL

First download OpenSSL from here and extract it somewhere. Using the latest one ensures there are no (known) security holes in OpenSSL or 1.0.0a if you want to apply the AES-NI patch. For the most part you can then follow the instructions in INSTALL.W32 and INSTALL.W64 files. Before you start, though, launch the Visual Studio Command Prompt (2010), 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.0d> perl Configure VC-WIN32 --prefix=c:/

Some of the crypto routines are written in assembler to increase performance, so you need to/should use an assembler in the next step.

C:\openssl-1.0.0d> ms\do_nasm

Next compile OpenSSL using the generated makefile:

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

Building LZO

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. 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.

Building pkcs11-helper

Download latest release of pkcs11-helper from http://www.opensc-project.org and extract it somewhere. The install process for Visual Studio is described in the INSTALL file.

First we have to patch the code a little bit to avoid a CE. In pkcs11h-threading.c find the following line,

ret = (unsigned)(_data->start (_data->data) - (void*)0);

and change it to

ret = (unsigned)((char*)_data->start (_data->data) - (char*)0);

To build pkcs11-helper, do the following:

  1. Go to pkcs11-helper-<version>\lib.
  2. Copy <openssl-install-directory>\lib\libeay32.lib to that directory - this is required by the linker.
  3. C:\pkcs11-helper-1.07\lib> nmake -f Makefile.w32-vc OPENSSL=1 OPENSSL_HOME=

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

Building OpenVPN

OpenVPN source package can be downloaded here.

If you want to enable password save, you have to modify misc.c, add #define ENABLE_PASSWORD_SAVE right before #ifundef ENABLE_PASSWORD_SAVE. That section will look like this:

/*
* Get username/password from a file.
*/
FILE *fp;
#define ENABLE_PASSWORD_SAVE
#ifndef ENABLE_PASSWORD_SAVE
/*
* Unless ENABLE_PASSWORD_SAVE is defined, don't allow sensitive passwords
* to be read from a file.
*/
if (flags & GET_USER_PASS_SENSITIVE)
msg (M_FATAL, "Sorry, '%s' password cannot be read from a file", prefix);
#endif

Simply uncomment !define ENABLE_PASSWORD_SAVE in settings.in will NOT work.

If you want to setup IPv6 VPN, I suggest you to use jjo's merged branch. But there are still several patches have to be done.

In config-win32.h, add #define USE_PF_INET6 1 after #define USE_LZO 1 (other places are fine too).

/* Use LZO compression library */
#define USE_LZO 1
#define USE_PF_INET6 1

Comment or delete #define socklen_t unsigned int.

/* type to use in place of socklen_t if not defined */
//#define socklen_t unsigned int

In options.c, comment the #ifdef USE_PF_INET6 & the matched #endif at line 1703, 1705, 1714, 1716. Those codes are not supported in VC.
And line 1654, 1656 in socket.c, same reason.

socket.c, line 637, CLEAR(sin6); generates a CE and I have no idea on what lead to this. Simply commenting it will get passed.
There is a MACRO IF_NAMESIZE at line 2461, which is defined in Windows DDK and we don't have it. Replace it by value 256 (this is the correct value and will not cause any problems).

In win\settings.in, change the !define MSVC "C:/Program Files/Microsoft Visual Studio 9.0" to the correct path VS2010 installed to. Change Microsoft.VC90.CRT to Microsoft.VC100.CRT.

In win\config_all.py, comment or delete config_tap and config_ti lines. We are not to build tap drivers nor to sign it. And comment build_ddk and sign lines in build_all.py too.

In win\make_dist.py, comment or delete cp(home_fn('openvpn.exe.manifest'), bin).

Now the pre-steps are almost complete, but the Python-based OpenVPN build system is pretty picky about it's directory layout, which should be like this:

  • C:\openvpn-build: root build directory.
  • C:\openvpn-build\openvpn-2.1.4: openvpn sources.
  • C:\openvpn-build\pkcs11-helper: pkcs11-helper build directory.
  • C:\openvpn-build\pkcs11-helper\lib: must contain libpkcs11-helper-1.dll, the product of pkcs11-helper build.
  • C:\openvpn-build\openssl: copy of the openssl install directory which contains the openssl libraries you built earlier. It's location depends on the parameter --prefix paramter you when configuring the openssl build.
  • C:\openvpn-build\lzo\include: this directory is a copy of the include directory in the lzo source package.
  • C:\openvpn-build\lzo\bin: this directory must contain the lzo2.dll file generated during lzo build.
  • C:\openvpn-build\lzo\lib: this directory must contain the lzo2.lib file generated during lzo build.
  • C:\openvpn-build\Microsoft.VC100.CRT: this directory is a copy of C:\Program Files\MicrosofT Visual Studio 10.0\VC\redist\x86\Microsoft.VC100.CRT directory. The exact path may vary. Visual Studio Express does not have this directory, and you may make a blank directory named that and obtain 2 files - msvcr100.dll & msvcp100.dll from C:\WINDOWS\system32 (these 2 files come from Microsoft Visual C++ 2010 Redistributable Package).

Next fire up a Visual Studio Command Prompt in win directory and start the build:

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

When building finishes without any errors, openvpn.exe and all DLLs it needs will lie in dist\bin directory.

Building OpenVPN Installer

This is not necessary if you only plan to install the built version yourself, but if you are going to distribute it, building a installer is a more professional way.

You need NSIS and the prebuilt OpenVPN binaries (because we didn't and couldn't build tap drivers).

In 2.1_rc22-prebuilt.tbz there's a gen-prebuilt directory, that's what we need. Replace the binary files in bin\ with our ones (don't forget openssl.exe) and http://openvpn.se/files/binary/openvpn-gui-1.0.3.exe; leave openvpnserv.exe unchanged. Replace DLL files in lib\ with our ones (libssl32.dll is taken over by ssleay32.dll) and add lzo2.dll, msvcp100.dll & msvcr100.dll.

In nsi\defs.nsi, edit PRODUCT_VERSION to be "2.1.4" or what ever you like.

Find Section "${PRODUCT_NAME} User-Space Components" SecOpenVPNUserSpace in nsi\openvpn.nsi, change it to be like this:

Section "${PRODUCT_NAME} User-Space Components" SecOpenVPNUserSpace

SetOverwrite on
SetOutPath "$INSTDIR\bin"

File "${BIN}\${PRODUCT_UNIX_NAME}.exe"
File "${LIB}\msvcp100.dll"
File "${LIB}\msvcr100.dll"
File "${LIB}\lzo2.dll"

SectionEnd

Section "OpenSSL DLLs" SecOpenSSLDLLs to be like this:

Section "OpenSSL DLLs" SecOpenSSLDLLs

SetOverwrite on
SetOutPath "$INSTDIR\bin"
File "${LIB}\libeay32.dll"
File "${LIB}\ssleay32.dll"

SectionEnd

And section Delete "$INSTDIR\bin\${PRODUCT_UNIX_NAME}.exe" to be like this:

Delete "$INSTDIR\bin\${PRODUCT_UNIX_NAME}.exe"
Delete "$INSTDIR\bin\${PRODUCT_UNIX_NAME}serv.exe"
Delete "$INSTDIR\bin\libeay32.dll"
Delete "$INSTDIR\bin\ssleay32.dll"
Delete "$INSTDIR\bin\lzo2.dll.dll"
Delete "$INSTDIR\bin\msvcp100.dll"
Delete "$INSTDIR\bin\msvcr100.dll"
Delete "$INSTDIR\bin\libpkcs11-helper-1.dll"
Delete "$INSTDIR\bin\tapinstall.exe"
Delete "$INSTDIR\bin\addtap.bat"
Delete "$INSTDIR\bin\deltapall.bat"

Finally, run (suggest your gen-prebuilt directory is C:\gen-prebuilt, or change it if not)

C:\> "C:\Program Files\NSIS\makensis.exe" C:\gen-prebuilt\nsi\openvpn.nsi