深度定制 OpenVPN for Windows

编译OpenVPN需要的环境:

  1. MinGW:编译环境
  2. MSYS:编译环境
  3. msysDTK:编译环境
  4. nsis:安装包生成工具
  5. openvpn-prebuilt
  6. openvpn-2.1.4源代码
  7. openvpn-gui-1.0.3源代码

配置编译环境

下载述1-4四个软件,进行缺省安装。

下载5-7三个软件的源代码。创建一个文件夹存放待编译的源代码,如:D:/OpenVPN,并把解压缩的源代码中对应的文件夹复制到这个文件夹中,配置完毕后该文件夹应包含如下子文件夹:

gen-prebuilt — OpenVPN预编译文件夹

lzo-2.02 — 压缩组件

openssl-0.9.8l — OpenSSL源码

openvpn-2.1.4 — OpenVPN源代码

openvpn-gui — 存放openvpn-gui-1.0.3.exe

openvpn-gui-1.0.3 — openvpn-gui源代码

pkcs11-helper — PKCS #11标准实现源码

tap_dist — 生成的tap驱动及安装程序,分别放在i386和amd64两个文件夹中

定制并编译OpenVPN GUI for Windows

OpenVPN-GUI for Windows,用户界面程序,源代码位于openvpn-gui-1.0.3文件夹下,如果官方有新版本发布,可以下载并放置到openvpn-gui-%version number%格式命名的文件夹下。

可以定制的内容:

  1. Makefile文件:修改其中的RES_LANG可以生成指定语言版本的gui,如cn
  2. openvpn-gui-%lan%.rc文件,Makefile中RES_LANG指定语言后,必须在同目录下存在对应的rc文件,如openvpn-gui-cn.rc。该文件可以从源代码中自带的openvpn-gui-en.rc复制而成,用UltraEdit或其他高级文本编辑器打开,编辑其中的英文字符串,改为中文即可,窗体的字体在每个窗体对应资源的FONT部分修改,如修改为FONT 9, “宋体”。

编译:从C:/MSYS/1.0文件夹下打开并运行msys.bat,然后定位到gui的源代码文件夹下,运行make即可生成exe文件到当前目录下。

如果需要编译OpenVPN安装程序时使用最新生成的gui程序,需要把生成的exe程序复制到openvpn-gui文件夹下,重命名为“openvpn-gui-1.0.3.exe”

定制并编译OpenVPN

本目录下的文件可以已经包含所有编译openvpn需要的文件,如果官方有新版本发布,需要下载OpenVPN的源代码,并放置在该文件夹内,以openvpn-%version number%格式命名(避免覆盖掉上一版本的定制过的文件)。

如果需要对OpenVPN程序本身的功能或BUG进行修改,需要看懂相应的C语言代码,修改完成后重新使用下面的方法编译。

使用msys.bat执行源文件根目录下的domake-win可以完全编译生成所有的组件,包括安装程序,安装程序会生成在源文件的gen目录下,gen目录里同时有其他生成安装程序所需的文件。完全编译很慢,需要5-10分钟的时间。

但如果仅需编译部分文件,如OpenVPN主程序,则仅需使用msys.bat在源文件根目录下执行install-win32/makeopenvpn即可(重新编译所有组件需要的时间太长,也不是很有必要,单独编译OpenVPN的话仅需半分钟);如需单独编译其他组件执行对应的makeXXX即可。

定制并编译OpenVPN安装程序

安装程序由nsis软件使用nsi脚本生成,定制安装程序主要就是定制nsi脚本,修改完成后,右击脚本文件,选择Compile NSIS script即可生成安装程序。脚本文件存放在OpenVPN源文件的gen/nsi文件夹下。

可以定制的内容:

  1. 版本号:打开defs.nsi,找到!define PRODUCT_VERSION,可以把“2.1.4”改为“2.1.4-shangsi”等自己喜欢的名称。该文件中的其他信息如果看懂了也可以根据自己的需要进行修改。进行完全编译时,会删除gen文件夹下的全部文件并重新生成,重新生成的文件中版本号是标准的版本号,如果需要彻底修改版本号,需要修改源文件根目录下的文件version.m4中的版本信息。
  2. 安装过程的语言:打开openvpn.nsi,找到;Languages部分,以!insertmacro开头的指令为添加语言的指令,且放在第一位的语言是安装程序的默认语言。如需中文版的安装程序,在!insertmacro MUI_LANGUAGE “English”之前加上中文语言支持:!insertmacro MUI_LANGUAGE “SimpChinese”。然后在所有英文语言的LangString指令后分别添加对应的中文LangString指令即可。非LangString的语言是不支持多语言的,如果要中文的,直接把英文的改为中文即可。
  3. 添加自定义的文件到安装包中::打开openvpn.nsi,找到Section “${PRODUCT_NAME} Service” SecService一节(也可放到别的Section中,根据自己的喜好决定),在  SetOutPath “$INSTDIR/config”之后添加:

File “${GEN}/config/SHANGSI.ovpn”

File “${GEN}/config/ca.crt”

File “${GEN}/config/ta.key”

即可把gen/config目录下的证书文件和客户端配置文件打包的安装程序中,如果需要安装到其他目录中,加上SetOutPath “$INSTDIR/%other folder%“即可,同时别忘了在Section “Uninstall”一节中添加如下内容:

Delete “$INSTDIR/config/ca.crt”

Delete “$INSTDIR/config/ta.key”

Delete “$INSTDIR/config/SHANGSI.ovpn”

以便在卸载程序时删除自定义安装的文件。

同样,进行完全编译时,会删除gen文件夹下的全部文件并重新生成,包括文件openvpn.nsi本身都会重新生成,如何保住自定义的内容呢?只需修改源文件的install-win32文件夹下的openvpn.nsi即可。由于gen文件夹重新生成时自定义的文件也会丢失,如何同时保住这些文件呢?打开install-win32文件夹下的getgui文件,在:

    mkdir -p $GENOUT/bin &>/dev/null   

    cp $GUI $GENOUT/bin

之后添加如下内容:

    mkdir -p $GENOUT/config &>/dev/null   

    cp $OPENVPN_GUI_DIR/config/ca.crt $GENOUT/config

    cp $OPENVPN_GUI_DIR/config/SHANGSI.ovpn $GENOUT/config

    cp $OPENVPN_GUI_DIR/config/ta.key $GENOUT/config

即可。当然也可以放到其他的批处理文件中,甚至自己仿照这个新建一个批处理文件也行,只不过要把新建的批处理在domake-win中添加上对应的调用脚本。

OpenVPN源代码中发现的BUG及修改方法:

  1. 如果操作系统目录不是C:/Windows,无法正常调用route.exe添加路由。

a)      原因:openvpn.c中大约133行处,获取系统路径时调用了获取缺省Windows安装路径的方法env_set_add_win32,固定返回C:/Windows。

b)      修改方法:注释掉调用“env_set_add_win32 (c.es);”添加一行:set_win_sys_path_via_env(c.es);该函数能根据系统的环境变量获得真实的系统路径。

后记

对于没有用C开发过项目的程序员来说,摸索出上面的一点点经验的过程非常痛苦。如果有的朋友在这方面遇到了相同的问题,恰巧这篇小文章能帮得上您,那我就无比荣幸了。