2x HOW TO

翻译中……

概述

OpenVPN是一个功能齐全的SSL VPN,它使用了行业标准的SSL/TLS协议,实现了OSI二层或三层安全网络拓展,支持基于证书、智能卡、用户名或密码凭证的灵活的客户端身份验证方法,并且允许用户或者特定组访问控制策略(使用应用于VPN虚拟接口的防火墙规则)。OpenVPN不是一个Web应用程序代理,并且不能通过Web浏览器进行操作。

通过提供可拓展的client/server模式,OpenVPN 2.0在OpenVPN 1.x的功能上进行了拓展,从而允许多个客户端通过单个TCP或UDP端口连接到单个OpenVPN服务器进程。OpenVPN 2.3包含大量改进,包括完整的IPv6支持和PolarSSL支持。

本文档提供了配置OpenVPN 2.x服务端或者客户端的步骤说明,包括:

如果迫不及待的话,可以直接跳到示例配置文件:

目标受众/阅读对象

本指南假定读者对基础的网络概念事先具有一定的了解,例如IP地址,DNS名称,网络掩码,子网,IP路由,路由器,网络接口,LAN,网关和防火墙规则。

附加文档

OpenVPN 书籍

请看 OpenVPN books page

OpenVPN 1.x 指南

原来的 OpenVPN 1.x 指南 仍然可用, 并且保留点对点和静态秘钥相关的配置。

OpenVPN 文章

有关其他的文档, 查看 articles pageOpenVPN wiki

OpenVPN 快速开始

尽管本HOWTO会指导你使用X509 PKI (public key infrastruction using certificates and private keys)设置一个可拓展的VPN client/server服务,但是如果你只想寻找一个能处理单个客户端的简单的VPN设置,本文档可能会过于复杂。

如果你想以最小化的配置快速运行一个VPN,你可以查看静态秘钥-最小化指南

静态秘钥的优点

  • 配置简单
  • 不需要维护的X509 PKI (Public Key Infrastructure)

静态秘钥的缺点

  • 拓展性有限 — 一台客户端,一台服务器
  • 缺乏完美正向加密 — 密钥泄露将导致之前的远程连接信息完全暴露
  • 秘钥必须以纯文本格式存放在每个对等的VPN上
  • 秘钥必须使用预先存在的安全通道进行交换

安装 OpenVPN

OpenVPN源码和Windows安装包可以在这里下载downloaded here。最新发布的版本(2.2或以上)也有Debian和RPM软件包可用;查看OpenVPN wiki获取详细信息。

为了安全,最好下载之后检查一下 file release signature

OpenVPN可执行文件应该同时安装在服务端和客户端机器上,因为单个可执行文件同时提供了客户端和服务端的功能。

Linux 笔记(使用RPM包)

如果你使用一个支持RPM包的Linux发行版,最好使用这个机制安装。最简单的方法是找一个当前发行版已有的RPM包,或者你也可以自己编译一个RPM包。

rpmbuild -tb openvpn-[version].tar.gz

有了.rpm文件后,你就可以通过常规方法安装。

rpm -ivh openvpn-[details].rpm

或者使用以下命令升级现有的安装版本。

rpm -Uvh openvpn-[details].rpm

通过RPM包安装OpenVPN需要下面这些依赖:

  • openssl
  • lzo
  • pam

此外,如果你是自己编译RPM包,还需要几个额外的依赖:

  • openssl-devel
  • lzo-devel
  • pam-devel

查看openvpn.spec文件,获取更多有关为Red Hat Linux 9构建RPM软件包或减少依赖关系进行构建的其他注意事项。

Linux 笔记(不使用RPM)

如果你使用Debian,Gentoo,或者其他非基于RPM机制的Linux发行版,请使用你的发行版指定的包管理机制,例如Debian上的apt-get或者Gentoo上的emerge

也可以使用通用的./configure方法在Linux上安装OpenVPN。首先解压.tar.gz文件:

tar xfz openvpn-[version].tar.gz

然后进入顶层目录,输入下面的命令:

./configure
make
make install

Windows 笔记

Windows版本的OpenVPN可以在OpenVPN download page页面下载自动安装文件进行安装。请记住,OpenVPN只能在Windows XP或更高的版本上运行。同样要注意,OpenVPN必须由具有管理员权限的用户安装和运行 (这个限制来自Windows,而不是OpenVPN)。

这个限制可以通过将OpenVPN以服务的形式运行在后台来规避,这样的话,一旦安装好了,非管理员用户也能访问VPN。More discussion on OpenVPN + Windows privilege issues

官方的OpenVPN Windows安装包带有OpenVPN-GUI,允许通过系统任务栏图标管理OpenVPN连接。其他GUI应用程序也可以使用。

运行完Windows安装程序后,OpenVPN已经可以使用了,并且建立了.ovpn拓展名关联。你可以通过下面的方式运行OpenVPN:

  • 在OpenVPN配置文件(.ovpn)上右击,选择Start OpenVPN on this configuration file,运行之后,可以通过按F4键来退出。
  • 使用下面的命令从命令提示符运行OpenVPN:
openvpn myconfig.ovpn

一旦在命令提出符窗口运行后,可以通过F4键退出OpenVPN。

  • 通过将一个或多个.ovpn配置文件放入\Program Files\OpenVPN\config,以服务形式运行OpenVPN,并且启动OpenVPN服务,可使用开始 -> 控制面板 -> 管理工具 -> 服务进行管理。

Additional Windows install notes.

Mac OS X 笔记

Angelo Laub和Dirk Theisen开发了OpenVPN GUI for OS X

其他操作系统

一些特定的系统的INSTALL文件提供了一些说明,通常而言,可以通过这样的方法安装,或者你可以搜索用于特定于你的操作系统或者发行版的OpenVPN软件包。

./configure
make
make install

确定使用基于路由还是桥接的VPN

有关路由和网桥的概念可以参照FAQ。See also the OpenVPN Ethernet Bridging page for more notes and details on bridging.

总的来说,对于大多数人而言,路由可能是一个更好的选择。因为相比桥接,它更高效并且更容易配置。(就OpenVPN配置本身而言) 路由也提供了更好的强大的能力,可以根据特定于客户端的方式选择性地控制访问权限。

我推荐使用路由,除非你需要一些特殊的功能,必须使用桥接,比如:

  • VPN要能够处理non-IP协议,例如IPX
  • 你正在通过VPN运行依赖于网络广播的应用程序,例如游戏
  • 你希望在不配置Samba或者WINS服务器的情况下,浏览Windows共享文件

专用子网划分

设置VPN通常需要将来自不同位置的专用子网链接在一起。

互联网号码分配局 (IANA) 已经为私有网络保留了下面三类地址块。(编撰自RFC 1918):

10.0.0.010.255.255.255(10/8 prefix)
172.16.0.0172.31.255.255(172.16/12 prefix)
192.168.0.0192.168.255.255(192.168/16 prefix)

尽管这些地址块中的地址可以正常的在VPN配置里使用,但是重要的是,选择的地址应该最大程度的减少IP地址冲突或者子网冲突的可能性。需要避免的冲突类型有:

  • 来自VPN上的不同的站点使用相同的子网编号导致的冲突
  • 来在使用和VPN子网冲突的私有子网的站点的访问连接

例如,假设你使用流行的192.168.0.0/24子网作为专用LAN子网。现在,你尝试从网吧连接到VPN,该网吧的WiFi LAN使用相同的子网。你将遇到路由冲突,因为你的计算机将不知道192.168.0.1是指本地WiFi网关还是VPN上的相同地址。

再举一个例子,假设你想通过VPN将多个站点链接在一起,但是每个站点都使用192.168.0.0/24作为其LAN子网。 如果不添加复杂的NAT转换层,这将无法工作,因为如果这些站点不使用唯一标识它们的子网,则VPN将不知道如何在多个站点之间路由数据包。

最佳解决方案是避免使用10.0.0.0/24或192.168.0.0/24作为专用LAN网络地址。相反,请使用那么你可能远程连接的地点,比如WiFi咖啡馆,机场或酒店等,这些地点中使用的可能性较低的网络地址。最佳候选者是巨大的10.0.0.0/8网络块中间的子网(例如10.66.77.0/24)。

为避免跨站点IP划分冲突,请始终对你的LAN子网使用唯一子网划分


创建自己的证书颁发机构(CA)并且为一个VPN服务器和多个客户端生成证书和秘钥

概述

建立OpenVPN 2.x配置的第一步是建立PKI(公钥基础结构)。PKI包括:

  • 服务器和每个客户端的单独的证书(也称为公钥)和私钥
  • 主证书颁发机构(CA)证书和密钥,用于对每个服务器证书和客户端证书进行签名。

OpenVPN支持基于证书的双向身份验证,这意味着在建立相互信任之前,客户端必须对服务器证书进行身份验证,并且服务器必须对客户端证书进行身份验证。

服务器和客户端都将通过首先验证所提供的证书已由主证书颁发机构(CA)签名,然后通过测试现在已认证的证书头中的信息,例如证书通用名或证书类型来对彼此进行身份验证(客户端或服务器)。

从VPN角度来看,此安全模型具有许多理想的功能:

  • 服务器仅需要自己的证书/密钥 - 不需要知道可能与之连接的每个客户端的单独证书。
  • 服务器将仅接受其证书由主CA证书(我们将在下面生成)签名的客户端。并且由于服务器可以执行此签名验证而无需访问CA私钥本身,因此CA密钥(整个PKI中最敏感的密钥)有可能驻留在完全不同的计算机上,甚至没有网络连接的计算机也可以驻留。
  • 如果私钥遭到破坏,可以通过将其证书添加到CRL(证书吊销列表)来禁用它。 CRL允许有选择地拒绝受到破坏的证书,而无需重建整个PKI。
  • 服务器可以基于嵌入式证书字段(例如“通用名称”)强制实施特定于客户端的访问权限。

请注意,服务器和客户端时钟需要大致同步,否则证书可能无法正常工作。

生成主证书颁发机构(CA)证书和密钥

在本部分中,我们将生成一个主CA证书/密钥,一个服务器证书/密钥以及3个单独的客户端证书/密钥。

对于PKI管理,我们将使用easy-rsa 2,这是与OpenVPN 2.2.x和更早版本捆绑在一起的一组脚本。 如果您使用的是OpenVPN 2.3.x,则需要从此处单独下载easy-rsa 2。

另外在OpenVPN软件仓库中有为Debian和Ubuntu准备的easy-rsa 2软件包。在*NIX平台上,你应该考虑使用easy-rsa 3代替;有关详细信息,请参阅其自己的文档。

如果您使用的是Linux,BSD或类似Unix的操作系统,请打开一个shell并使用cd进入easy-rsa子目录。如果您是从RPM或DEB文件安装OpenVPN的,则easy-rsa目录通常可以在/usr/share/doc/packages/openvpn/usr/share/doc/openvpn中找到(最好在进行任何编辑之前将此目录复制到其他位置,例如/etc/openvpn,这样以后的OpenVPN软件包升级将不会覆盖n你的修改)。如果从.tar.gz文件安装,则easy-rsa目录将位于展开源码的的顶级目录中。

如果您使用的是Windows,请打开“命令提示符”窗口,并CD到\Program Files\OpenVPN\easy-rsa。运行以下批处理文件以将配置文件复制到位(这将覆盖所有先前存在的vars.bat和openssl.cnf文件):

init-config

现在,编辑vars文件(在Windows上称为vars.bat)并设置KEY_COUNTRY,KEY_PROVINCE,KEY_CITY,KEY_ORG和KEY_EMAIL参数。请勿将这些参数中的任何一个留空。

接下来,初始化PKI,在Linux/BSD/Unix上:

. ./vars
./clean-all
./build-ca

在Windows上:

vars
clean-all
build-ca

最后的命令(build-ca)将通过调用交互式openssl命令来构建证书颁发机构(CA)证书和秘钥:

ai:easy-rsa # ./build-ca
Generating a 1024 bit RSA private key
............++++++
...........++++++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [KG]:
State or Province Name (full name) [NA]:
Locality Name (eg, city) [BISHKEK]:
Organization Name (eg, company) [OpenVPN-TEST]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:OpenVPN-CA
Email Address [me@myhost.mydomain]:

请注意,在上述顺序中,大多数询问的参数默认为在varsvars.bat文件中设置的值。必须明确输入的唯一参数是“通用名称”。在上面的示例中,我使用了“OpenVPN-CA”。

生成服务器的证书和密钥

接下来,我们将为服务器生成证书和私钥。在Linux/BSD/Unix上:

./build-key-server server

在Windows上:

build-key-server server

与上一步一样,大多数参数可以使用默认值。当询问“公用名”时,输入“server”。另外两个询问需要肯定的答复:“Sign the certificate? [y/n]”和“1 out of 1 certificate requests certified, commit? [y/n]”。

为3个客户端生成证书和密钥

生成客户端证书与上一步非常相似。在Linux/BSD/Unix上:

./build-key client1
./build-key client2
./build-key client3

在Windows上:

build-key client1
build-key client2
build-key client3

如果您想用密码保护客户端密钥,请使用build-key-pass脚本替换。

请记住,对于每个客户端,请确保在出现提示时键入相应的“通用名称”,即“client1”,“client2”或“client3”。始终为每个客户端使用唯一的通用名称。

生成Diffie Hellman参数

必须为OpenVPN创建[Diffie Hellman参数。在Linux/BSD/Unix系统上可以这样操作:

/build-dh

在Windows系统上:

build-dh

输出信息:

ai:easy-rsa # ./build-dh
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
.................+...........................................
...................+.............+.................+.........
......................................

秘钥文件

现在我们可以在keys子目录里找到新创建的证书和秘钥,这是对相关文件的解释:

文件名被需要目的是否秘钥
ca.crt服务端 + 所有客户端Root CA certificateNO
ca.key仅对秘钥进行签名的机器Root CA keyYES
dh{n}.pem仅服务端Diffie Hellman parametersNO
server.crt仅服务端Server CertificateNO
server.key仅服务端Server KeyYES
client1.crt仅客户端client1Client1 CertificateNO
client1.key仅客户端client1Client1 KeyYES
client2.crt仅客户端client2Client2 CertificateNO
client2.key仅客户端client2Client2 KeyYES
client3.crt仅客户端client3Client3 CertificateNO
client3.key仅客户端client3Client3 KeyYES

生成证书的操作的最后一步是复制所有的文件需要它们的机器上,需要注意通过安全通道拷贝秘钥文件。

等等,你可能会说,在没有预先存在的安全通道的情况下,能否创建PKI?

很显然答案是肯定的。在上面的示例中,为了简洁起见,我们在同一位置生成了所有私钥。如果再付出更多努力,我们本可以以不同的方式做到这一点。 例如,我们可以让客户端在本地生成自己的私钥,而不是在服务器上生成客户端证书和密钥,然后将证书签名请求(CSR)提交给密钥签名机。 反过来,密钥签名机可能已经处理了CSR,并向客户端返回了已签名的证书。 可以完成此操作,而无需将任何秘密的.key文件留给生成该文件的计算机的硬盘驱动器。


为服务端和客户端创建配置文件

获取示例配置文件

最好使用OpenVPN的示例配置文件作为你自己配置文件的起点。这些文件也可在这里找到:

  • OpenVPN源码的sample-config-files目录
  • 如果是使用RPM或者DEB包的方式安装的,sample-config-files目录通常在/usr/share/doc/packages/openvpn或者/usr/share/doc/openvpn
  • Windows上在开始 -> 所有程序 -> OpenVPN -> OpenVPN Sample Configuration Files

注意在Linux,BSD,或者类unix系统上,示例配置文件名为server.confclient.conf。在Windows系统上名为server.ovpnclient.ovpn

编辑服务端配置文件

服务端配置文件样本文件是一个理想的OpenVPN服务端配置起点,它将使用一个虚拟的TUN网卡(为了路由),并且在UDP端口1194上监听客户端的连接(OpenVPN的默认端口),给连接的客户端分配子网10.8.0.0/24中的虚拟地址。

在你使用示例配置文件之前,你需要先编辑cacertkey,和dh参数,指定之前在PKI中创建的文件。

到了这里,服务端配置文件已经可以使用了,但是你可能仍然想进一步定制它。

  • 如果你使用Ethernet bridging,你必须使用server-bridgedev tap替代serverdev tun
  • 如果你想要你的OpenVPN服务器使用TCP替代UDP监听端口,使用proto tcp替代proto udp(如果你想你的OpenVPN同时监听TCP和UDP端口,你必须运行两个独立的OpenVPN实例)。
  • 如果你想使用10.8.0.0/24范围以外的IP地址,你可以修改server指令。要记住,虚拟IP范围必须是私有地址,并且没有在你的网络中被使用。
  • 如果你想通过VPN连接的客户端之间能够互相访问,取消注释client-to-client,默认情况下,客户端只能访问服务端。
  • 如果你使用的是Linux,BSD,或者类Unix系统,你可是取消注释user nobodygroup nobody来提高安全性。

如果你想在同一台机器上运行多个OpenVPN实例,每个实例使用不同的配置文件,it is possible if you:

  • 为每个实例使用不同的port号(UDP和TCP协议使用不同的端口空间,所以你可以运行一个守护进程监听在UDP的1194端口上,另一个守护进程监听在TCP的1194端口上)。
  • 如果你使用的是Windows, 每个OpenVPN配置文件需要有它自己的TAP-Windows适配器。你可是通过开始 -> 所有程序 -> TAP-Windows -> Add a new TAP-Windows virtual ethernet adapter添加额外的适配器。
  • 如果你在同一目录外运行多个OpenVPN实例,需要编辑创建输出文件的指令以确保不同的实例不会相互覆盖输出文件。涉及到的指令包括loglog-appendstatusifconfig-pool-persist

编辑客户端配置文件

客户端配置样本文件(Linux/BSD/Unix上为client.conf,Windows上为client.ovpn)对应于服务端样本文件中的默认指令配置。

  • 和服务端配置文件一样,首先编辑cacertkey参数指定在PKI步骤中创建的文件。注意每个客户端需要有它自己的cert/key。只有ca文件是所有OpenVPN服务端和客户端通用的。
  • 接下载,编辑remote指令,指定远程OpenVPN服务器的主机名/IP地址和端口号。(如果你的OpenVPN服务器将运行在防火墙/NAT网关下的一个单网卡机器上,使用网关的公网IP地址,和已经配置了端口转发到OpenVPN服务的端口号)。
  • 最后,确保客户端配置文件中的指令和服务端配置文件的指令一致。最重要是检查dev(tun or tap)和proto(udp or tcp)指令要一致。同样确保comp-lzofragment如果使用了,需要同时出现在服务端和客户端配置文件里。

启动VPN并且测试初始化连接

启动服务端

首先,确保OpenVPN服务器可以通过网络访问,意味着:

  • 开放防火墙UDP端口1194(或者你配置的其他任何的TCP/UDP端口)
  • 防火墙/网关上配置端口转发规则,转发到UDP端口1194到运行OpenVPN服务的机器上。

接下来, 确保TUN/TAP接口没有防火墙.

我在简化故障排除,最好先从命令行启动OpenVPN服务,而不是使用守护进程或者服务。(或者在Windows上,可以在.ovpn文件上右击):

openvpn [服务端配置文件] 

一个正常的服务启动应该像下面这样(不同平台可能输出会有不同):

Sun Feb  6 20:46:38 2005 OpenVPN 2.0_rc12 i686-suse-linux [SSL] [LZO] [EPOLL] built on Feb  5 2005
Sun Feb  6 20:46:38 2005 Diffie-Hellman initialized with 1024 bit key
Sun Feb  6 20:46:38 2005 TLS-Auth MTU parms [ L:1542 D:138 EF:38 EB:0 ET:0 EL:0 ]
Sun Feb  6 20:46:38 2005 TUN/TAP device tun1 opened
Sun Feb  6 20:46:38 2005 /sbin/ifconfig tun1 10.8.0.1 pointopoint 10.8.0.2 mtu 1500
Sun Feb  6 20:46:38 2005 /sbin/route add -net 10.8.0.0 netmask 255.255.255.0 gw 10.8.0.2
Sun Feb  6 20:46:38 2005 Data Channel MTU parms [ L:1542 D:1450 EF:42 EB:23 ET:0 EL:0 AF:3/1 ]
Sun Feb  6 20:46:38 2005 UDPv4 link local (bound): [undef]:1194
Sun Feb  6 20:46:38 2005 UDPv4 link remote: [undef]
Sun Feb  6 20:46:38 2005 MULTI: multi_init called, r=256 v=256
Sun Feb  6 20:46:38 2005 IFCONFIG POOL: base=10.8.0.4 size=62
Sun Feb  6 20:46:38 2005 IFCONFIG POOL LIST
Sun Feb  6 20:46:38 2005 Initialization Sequence Completed

启动客户端

和服务端一样,也是最好在命令行启动OpenVPN客户端,(或者在Windows上,通过在client.ovpn文件上右击),而不是使用守护进程或者服务方式运行:

openvpn [客户端配置文件] 

一个正常启动的客户端输出文件和上面的服务端输出文件类似,并且应该以Initialization Sequence Completed信息作为结尾。

现在,尝试从客户端对VPN进行ping操作。如果你使用路由(例如服务端配置文件中有dev tun),运行:

ping 10.8.0.1

如果你使用的是桥接(例如服务端配置文件中有dev tap),尝试ping一个服务器子网上的一台机器的IP地址。

如果ping成功了,恭喜你,你拥有了一个正常运行的的VPN。

故障排除

如果ping失败了,或者OPenVPN客户端初始化失败了,这里有个常见故障症状和解决方式的清单:

  • 如果你看到这样的错误信息:

    TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)

    这个错误处表明客户端无法建立到服务器的网络连接

    解决方案:确保客户端配置了正确的主机名/IP地址和端口好,并且允许访问到OPenVPN服务器。

  • 如果OPenVPN服务器使用单网卡并且在受保护的LAN中,确保你在服务器的网关或者防火墙上使用了正确的端口转发规则。例如,假设你的OpenVPN盒子在192.168.4.4在防火墙内, 使用UDP端口1194监听客户端连接,服务于192.168.4.x子网的NAT网关应该配置一条端口转发规则,将UDP端口1194从公网地址转发到192.168.4.4

    解决方案:打开服务器的防火墙允许UDP端口1194进来的连接(或者其它在服务端配置文件中使用的TCP/UDP端口)。

  • 如果你看到这样的错误信息: Initialization Sequence Completed with errors

    如果(a)你没有运行DHCP客户端服务,或者(b)您在XP SP2上使用某些第三方个人防火墙,则可能在Windows上发生此错误。

    解决方案:启动DHCP客户端服务器,并确保您使用的是已知在XP SP2上可以正常工作的个人防火墙。

  • 如果你得到Initialization Sequence Completed信息,但是ping测试失败了。

    这通常表示服务器或客户端上的防火墙通过在TUN/TAP接口上进行过滤来阻止VPN网络流量。

    解决方式:禁用客户端防火墙(如果存在的话)过滤客户端上的TUN/TAP接口。例如,在Windows XP SP2上,您可以通过以下方法执行此操作:转到“Windows安全中心”->“Windows防火墙”->“高级”,然后取消选中与TAP-Windows适配器相对应的复选框(禁止客户端防火墙过滤TUN/TAP适配器从安全的角度来看通常是合理的,因为你实际上是在告诉防火墙不要阻止经过身份验证的VPN流量)。还要确保服务器上的TUN/TAP接口没有被防火墙过滤(尽管如此,请注意,服务器端TUN/TAP接口的选择性防火墙可以带来一定的安全优势。请参阅访问策略部分)。

  • 当使用proto udp配置启动时连接会假死。服务端日志文件显示下面这行信息:TLS: Initial packet from x.x.x.x:x, sid=xxxxxxxx xxxxxxxx,但是客户端并没有显示同样的信息。

    解决方案: 你具有从客户端到服务器的单向连接。服务器到客户端的方向通常在客户端被防火墙阻止。防火墙可能是(a)在客户端上运行的个人软件防火墙,也可能是(b)客户端的NAT路由器网关。修改防火墙,以允许从服务器返回的UDP数据包到达客户端。

有关其他疑难解答信息,请参见FAQ


配置OpenVPN在系统启动时自动运行

这个地方缺乏统一的标准,因为大多数操作系统都有不同的方式配置守护进程或服务,以在系统启动时自动运行。实现这个功能最好的方式是使用包方式安装OPenVPN,例如在Linux上通过RPM包,或者在Windows上使用安装程序。

Linux

如果你通过RPM包或者DEB包在Linux上安装的OpenVPN,安装程序会配置一个initscript,当被执行的时候,初始化脚本会扫描目录/etc/openvpn下的.conf配置文件,如果找到了,将会为每个配置文件启动独立的OPenVPN守护进程。

Windows

Windows安装程序会配置一个服务,但是默认是关闭的,要想激活它,需要到控制面板 / 管理工具 / 服务中,选中OpenVPN服务,右击打开属性,设置启动方式为自动,这样在下次系统启动的时候就会自动运行服务。

服务启动会,OPenVPN服务会扫描\Program Files\OpenVPN\config目录下的.ovpn配置文件,每个配置文件启动独立的OpenVPN进程。


控制一个运行中的OpenVPN进程

运行在Linux/BSD/Unix

OpenVPN接受几种信号:

  • SIGUSR1 — 有条件的重新启动,旨在在没有root权限的情况下重新启动
  • SIGHUP — 硬重启
  • SIGUSR2 — 输出连接统计信息到日志文件或者syslog
  • SIGTERM, SIGINT — 退出

使用writepid指令将OpenVPN守护进程的PID写入到文件,这样你就知道向哪里发送信号。(如果你通过initscript启动OpenVPN服务,脚本可能已经通过openvpn命令行传递了–writepid指令)。

以GUI方式运行在Windows

查看OpenVPN GUI page

以命令提示符窗口运行在Windows

在Windows上,可以通过右键单击OpenVPN配置文件(.ovpn文件)并选择“Start OpenVPN on this config file”来启动OpenVPN。

以这种方式运行后,可以使用几个键盘命令:

  • F1 — 有条件的重启 (不关闭/重新打开TAP适配器)
  • F2 — 显示连接统计
  • F3 — 硬重启
  • F4 — 退出

以Windows服务方式运行

在Windows上将OpenVPN作为服务启动时,控制它的唯一方法是:

  • 通过服务控制管理器(“控制面板”/“管理工具”/“服务”)进行启动/停止控制。
  • 通过管理界面(见下文)。

修改实时服务器配置

尽管大多数配置更改都需要您重新启动服务器,但是有两个特别的指令,它们指向可以实时动态更新的文件,它们将在服务器上立即生效,而无需重新启动服务器进程。

client-config-dir — 该指令设置客户端配置目录,OpenVPN服务器将在每个传入连接上扫描该目录,以搜索特定于客户端的配置文件 (更多信息参见the manual page)。
此目录中的文件可以即时更新,而无需重新启动服务器。 请注意,此目录中的更改仅对新连接有效,而对现有连接无效。 如果您希望更改特定于客户端的配置文件对当前连接的客户端(或已断开连接但服务器尚未使其实例对象超时的客户端)立即生效,请使用管理接口来终止该客户端实例对象(如下所述)。这将导致客户端重新连接并使用新的client-config-dir文件。

crl-verify — 该指令指向一个证书吊销列表文件,如下面吊销证书部分所述。可以即时修改CRL文件,并且更改将立即对新连接或正在重新协商其SSL/TLS通道的现有连接生效(默认情况下每小时发生一次)。如果要终止其证书刚刚添加到CRL的当前连接的客户端,请使用管理界面(如下所述)。

状态文件

默认的server.conf文件有一行:

status openvpn-status.log

这将会每分钟输出一次当前连接的客户端列表到文件openvpn-status.log

使用管理接口

The OpenVPN management interface allows a great deal of control over a running OpenVPN process. You can use the management interface directly, by telneting to the management interface port, or indirectly by using an OpenVPN GUI which itself connects to the management interface.

OpenVPN管理接口可以对正在运行的OpenVPN进程进行大量控制。你可以通过远程登录到管理接口端口直接使用管理接口,也可以使用本身连接到管理接口的OpenVPN GUI间接使用管理接口。

要在OpenVPN服务器或客户端上启用管理接口,请将其添加到配置文件中:

management localhost 7505

这告诉OpenVPN在TCP端口7505上侦听管理接口客户端(端口7505是任意选择 - 你可以使用任何可用端口)。

OpenVPN运行之后,您可以使用telnet客户端连接到管理界面。例如:

ai:~ # telnet localhost 7505
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
>INFO:OpenVPN Management Interface Version 1 -- type 'help' for more info
help
Management Interface for OpenVPN 2.0_rc14 i686-suse-linux [SSL] [LZO] [EPOLL] built on Feb 15 2005
Commands:
echo [on|off] [N|all]  : Like log, but only show messages in echo buffer.
exit|quit              : Close management session.
help                   : Print this message.
hold [on|off|release]  : Set/show hold flag to on/off state, or
                         release current hold and start tunnel.
kill cn                : Kill the client instance(s) having common name cn.
kill IP:port           : Kill the client instance connecting from IP:port.
log [on|off] [N|all]   : Turn on/off realtime log display
                         + show last N lines or 'all' for entire history.
mute [n]               : Set log mute level to n, or show level if n is absent.
net                    : (Windows only) Show network info and routing table.
password type p        : Enter password p for a queried OpenVPN password.
signal s               : Send signal s to daemon,
                         s = SIGHUP|SIGTERM|SIGUSR1|SIGUSR2.
state [on|off] [N|all] : Like log, but show state history.
status [n]             : Show current daemon status info using format #n.
test n                 : Produce n lines of output for testing/debugging.
username type u        : Enter username u for a queried OpenVPN username.
verb [n]               : Set log verbosity level to n, or show if n is absent.
version                : Show current version number.
END
exit
Connection closed by foreign host.
ai:~ #

想要获取更多信息,可以查看OpenVPN 管理接口文档


拓展VPN的范围,包括服务端或客户端子网上的其他机器

使用路由VPN(dev tun)的情况下在服务端包含多台机器

一旦VPN在服务端和客户端之间可以通过点对点功能运行的时候,可能就需要拓展VPN的范围,这样客户端可以访问服务端网络上的多台机器,而不仅仅是服务端机器本身。

在这个例子中,我们假设服务端的LAN使用的子网为10.66.0.0/24,VPN地址池引用OpenVPN服务端配置文件中server指令配置的10.8.0.0/24

首先,你必须将子网10.66.0.0/24公布给客户端,使其可以通过VPN访问。这很容易通过下面的服务端配置文件指令完成。

push "route 10.66.0.0 255.255.255.0"

接下来,你必须在服务端LAN网关上设置一条路由规则,将VPN客户端子网路由到OpenVPN服务器(只有OpenVPN服务器和LAN网关不是同一台机器的时候才需要设置)。

确保你已经在OpenVPN服务端机器上启用了IPTUN/TAP转发。

使用桥接VPN(dev tap)的情况下在服务端包含多台机器

使用网卡桥接的一个好处就是可以直接实现这功能而不需要额外的配置。

使用路由VPN(dev tun)的情况下在客户端包含多台机器

在典型的出差达人或远程访问方案中,客户端机器作为单台计算机连接到VPN。但是,假设客户端机器是本地LAN(例如家庭办公室)的网关,并且您希望客户端LAN上的每台计算机都能够通过VPN进行路由。

对于此示例,我们假设客户端LAN使用的是192.168.4.0/24子网,并且VPN客户端使用的是通用名称为client2的证书。我们的目标是建立VPN,以便客户端LAN上的任何计算机都可以通过VPN与服务器LAN上的任何计算机通信。

设置之前,必须满足一些基本先决条件:

  • 服务器或使用同一子网的任何其他客户端站点不得将客户端LAN子网(在我们的示例中为192.168.4.0/24)导出到VPN。通过路由连接到VPN的每个子网都必须是唯一的。
  • 客户端的证书中必须具有唯一的公用名(在我们的示例中为“client2”),并且OpenVPN服务器配置文件中不得使用duplicate-cn指令。

确保你已经在OpenVPN服务端机器上启用了IPTUN/TAP转发。

接下来,我们将在服务器端进行必要的配置更改。如果服务器配置文件当前未引用客户端配置目录,请立即添加一个:

client-config-dir ccd

上面指令中的ccd应该是在运行OpenVPN服务端守护程序的默认目录中预先创建的目录的名称。在Linux上,它通常是/etc/openvpn;在Windows上,通常是\Program Files\OpenVPN\config。当新客户端连接到OpenVPN服务器时,守护程序将在此目录中检查与连接客户端的通用名称匹配的文件。如果找到匹配的文件,将对其进行读取和处理,以将其他配置文件指令应用于命名的客户端。

下一步是在ccd目录中创建一个名为client2的文件。该文件应包含以下行:

iroute 192.168.4.0 255.255.255.0

这将告诉OpenVPN服务器192.168.4.0/24子网应路由到client2

接下来,将以下行添加到主服务器配置文件(而不是ccd/client2文件)中:

route 192.168.4.0 255.255.255.0

你可能会问,为什么要使用冗余的routeiroute语句?原因是route控制从内核到OpenVPN服务器的路由(通过TUN接口),而iroute控制从OpenVPN服务器到远程客户端的路由。两者都是必要的。

接下来,问问自己是否要允许client2的子网(192.168.4.0/24)与OpenVPN服务器的其他客户端之间的网络通信。如果是这样,请将以下内容添加到服务器配置文件中。

client-to-client
push "route 192.168.4.0 255.255.255.0"

这将导致OpenVPN服务器将client2的子网发布给其他连接的客户端。

最后一步,也是通常被遗忘的一步,是向服务器的LAN网关添加一条路由,该路由将192.168.4.0/24定向到OpenVPN服务器框(如果OpenVPN服务器框网关,则不需要此路由) 用于服务器LAN)。假设你漏掉了此步骤,并且尝试从192.168.4.8 ping服务器LAN上的计算机(不是OpenVPN服务器本身)?传出的ping可能到达了计算机,但随后它不知道如何路由ping答复,因为它不知道如何到达192.168.4.0/24。使用的经验法则是,当通过VPN路由整个LAN时(当VPN服务器与LAN网关不在同一台计算机上时),请确保LAN的网关将所有VPN子网路由到VPN服务器计算机。

同样,如果运行OpenVPN的客户端计算机也不是客户端侧LAN的网关,则客户端LAN的网关必须具有一条路由,该路由会将可以通过VPN访问的所有子网都定向到OpenVPN客户端计算机。

使用桥接VPN(dev tap)的情况下在客户端包含多台机器

这需要更复杂的设置(实际上可能不会更复杂,但要进行详细解释则更加复杂):

  • 你必须将客户端TAP接口与客户端上连接LAN的NIC桥接。
  • 你必须在客户端上手动设置TAP接口的IP/网络掩码。
  • 你必须配置客户端计算机以使用桥接子网内部的IP/网络掩码,或者通过查询OpenVPN服务器端的DHCP服务器来实现。

推送DHCP选项到客户端

OpenVPN服务器可以将DHCP选项(例如DNS和WINS服务器地址)推送到客户端(要知道的一些注意事项)。Windows客户端可以本地接受推送的DHCP选项,非Windows客户端可以通过使用客户端up脚本来接受它们,该脚本分析foreign_option_*n*环境变量列表。有关非Windowsforeign_option_*n*文档和脚本示例,请参见手册页

例如,假设你希望连接的客户端使用内网的DNS服务器(位于10.66.0.4或10.66.0.5)和WINS服务器(位于10.66.0.8)。将这些添加到OpenVPN服务端配置中:

push "dhcp-option DNS 10.66.0.4"
push "dhcp-option DNS 10.66.0.5"
push "dhcp-option WINS 10.66.0.8"

要在Windows上测试此功能,请在计算机连接到OpenVPN服务器后从命令提示符窗口运行以下命令:

ipconfig /all

TAP-Windows适配器的条目中应该会显示服务器推送的DHCP选项。


配置特定客户端的规则和访问策略

假设我们现在要创建一个公司VPN,我们想要为三个不同类别的用户创建独立的访问策略。

  • 系统管理员 — 完全访问网络上所有的机器
  • 雇员 — 只能访问Samba/email服务器
  • 承建商 — 只能访问特定的服务器

我们采取的基本方法是,(a) 将每个用户类别划分到它自己的虚拟IP地址范围内。(b) 通过设置防火墙规则来关闭客户端的虚拟IP地址,实现对机器的访问控制。

在我们例子中,假设我们有数量可变的雇员,但只有一名系统管理员,两个承建商,我们的IP地址分配方法将把所有员工放入一个IP地址池。然后给系统管理员和承建商分配固定的IP地址。

注意这个例子的一个先决条件是,OpenVPN服务端机器上必须运行一个软件防火墙,使你能够定义特定的防火墙规则。在我们的例子中,我们假定使用的是Linuxiptables防火墙。

首先,让我们根据不同用户类型创建IP地址分配表:

类别虚拟IP范围允许访问的LAN通用名
雇员10.8.0.0/24Samba/email服务器位于10.66.4.4[variable]
系统管理员10.8.1.0/24整个10.66.4.0/24子网sysadmin1
承建商10.8.2.0/24承建商服务器位于10.66.4.12contractor1, contracter2

接下来,让我们把这个分配表转换成OpenVPN服务端配置。首先,确保已经按照上述步骤将子网10.66.4.0/24提供给所有客户端使用(当我们配置路由允许所有客户端访问整个10.66.4.0/24子网,然后我们再使用防火墙规则强制访问限制来实现上面的策略表)。

首先,给我们的tun接口定义一个静态的单元号,以便我们稍后在防火墙规则中引用它:

dev tun0

在服务端配置文件中,定义雇员IP地址池:

server 10.8.0.0 255.255.255.0

给系统管理员和承建商的IP地址范围添加路由:

route 10.8.1.0 255.255.255.0
route 10.8.2.0 255.255.255.0

因为我们将分配固定的IP地址给特定的系统管理员和承建商,我们将使用一个客户端配置目录:

client-config-dir ccd

现在将特定的配置文件放进ccd子目录来给每个非雇员客户端分配固定的IP地址。

ccd/sysadmin1

ifconfig-push 10.8.1.1 10.8.1.2

ccd/contractor1

ifconfig-push 10.8.2.1 10.8.2.2

ccd/contractor2

ifconfig-push 10.8.2.5 10.8.2.6

每一对ifconfig-push地址代表虚拟客户端和服务端IP端点。必须从连续的/30子网中获取他们,以便与Windows客户端和TAP-Windows驱动兼容。特别的,每个端点对的随后8位必须从下面的集合中获取:

[  1,  2] [  5,  6] [  9, 10] [ 13, 14] [ 17, 18]
[ 21, 22] [ 25, 26] [ 29, 30] [ 33, 34] [ 37, 38]
[ 41, 42] [ 45, 46] [ 49, 50] [ 53, 54] [ 57, 58]
[ 61, 62] [ 65, 66] [ 69, 70] [ 73, 74] [ 77, 78]
[ 81, 82] [ 85, 86] [ 89, 90] [ 93, 94] [ 97, 98]
[101,102] [105,106] [109,110] [113,114] [117,118]
[121,122] [125,126] [129,130] [133,134] [137,138]
[141,142] [145,146] [149,150] [153,154] [157,158]
[161,162] [165,166] [169,170] [173,174] [177,178]
[181,182] [185,186] [189,190] [193,194] [197,198]
[201,202] [205,206] [209,210] [213,214] [217,218]
[221,222] [225,226] [229,230] [233,234] [237,238]
[241,242] [245,246] [249,250] [253,254]

这样就完成了OpenVPN的配置,最后一步是添加防火墙规则来最终确定访问策略,在这个例子中,我们将使用Linuxiptables语法中的防火墙规则:

# 雇员规则
iptables -A FORWARD -i tun0 -s 10.8.0.0/24 -d 10.66.4.4 -j ACCEPT

# 系统管理员规则
iptables -A FORWARD -i tun0 -s 10.8.1.0/24 -d 10.66.4.0/24 -j ACCEPT

# 承建商规则
iptables -A FORWARD -i tun0 -s 10.8.2.0/24 -d 10.66.4.12 -j ACCEPT

使用可选的身份验证方法

OpenVPN 2.0或者更新的版本包含了一个特性,允许OpenVPN服务端从已经连接的客户端安全地获取用户名和密码,并使用这些信息作为客户端身份验证的基础。

为了使用身份验证方法,首先在客户端配置文件中添加auth-user-pass指令。它将指导OpenVPN客户端查询用户名和密码,并通过安全的TLS通道传送给服务端。

接下来,配置服务端使用一个身份验证插件,可能是脚本,共享对象或者DLL。OpenVPN服务端将在每次客户端连接的时候调用该插件,给它传递客户端上输入的用户名和密码,身份验证插件将通过返回失败(1)或成功(0)值来控制OpenVPN服务端是否允许客户端连接。

使用脚本插件

脚本插件可以通过在服务端配置文件添加auth-user-pass-verify指令来使用,例如:

auth-user-pass-verify auth-pam.pl via-file

将使用auth-pam.plperl脚本来验证连接客户端的用户名/密码。 在manual page查看更多关于auth-user-pass-verify的介绍。

auth-pam.pl脚本包含在OpenVPN源码发行包的sample-scripts目录下。它将使用PAM身份验证模块对Linux服务器上的用户进行身份验证。该模块也可以实现影子密码,RADIUS或者LDAP身份验证。auth-pam.pl主要用于演示目的,对于真实的PAM身份验证,请使用下面介绍的openvpn-auth-pam共享对象插件。

使用共享对象或者DLL插件

共享对象或者DLL插件通常是编译好的C模块,由OpenVPN在运行时加载。例如,你使用基于RPM包安装的OpenVPN,openvpn-auth-pam应该已经编译好了。想要使用它,只需要在服务端配置文件中添加:

plugin /usr/share/openvpn/plugin/lib/openvpn-auth-pam.so login

这将告诉OpenVPN服务端使用loginPAM模块来验证客户端输入的用户名/密码。

在真实的生产环境中使用,最好使用openvpn-auth-pam插件,因为它相比auth-pam.pl脚本有几个好处:

  • 共享对象openvpn-auth-pam插件使用拆分权限执行模型以提高安全性。这意味着OpenVPN服务器可以通过使用指令user nobodygroup nobodychroot来以降低的权限运行,并且仍然能够通过仅root可读的影子密码文件进行身份验证。
  • OpenVPN可以通过虚拟内存(而不是通过文件或环境)将用户名/密码传递给插件,这对于服务器计算机上的本地安全性更好。
  • C编译的插件模块通常比脚本运行得更快。

如果你想了解有关开发自己的OpenVPN插件,可以查看OpenVPN源码发型包plugin目录下的README文件。

要在Linux上编译openvpn-auth-pam插件,进入OpenVPN源码包的plugin/auth-pam目录下执行make

使用用户名/密码身份验证作为客户端唯一验证方式

默认情况下,在服务端使用auth-user-pass-verify或者用户名/密码检查plugin将启用两步验证,同时要求客户端证书和用户名/密码验证都成功。

尽管从安全角度考率不推荐这么做,其实也可以禁用客户端证书,强制只使用用户名/密码身份验证。在服务端上:

client-cert-not-required

通常还应该设置一下配置:

username-as-common-name

这将告诉服务端使用用户名进行索引,因为它将使用经过客户端证书验证过的通用名。

请注意,client-cert-not-required不会消除对服务器证书的依赖,因此,连接到使用client-cert-not-required的服务器的客户端,可以删除客户端配置文件中的certkey指令,而不是ca指令,因为客户端必须验证服务器证书。


如何使用客户端智能卡,配置OpenVPN双重身份验证

同样参考文章: The OpenVPN Smartcard HOWTO

关于双重身份验证

Dual-factor authentication is a method of authentication that combines two elements: something you have and something you know.

Something you have should be a device that cannot be duplicated; such a device can be a cryptographic token that contains a private secret key. This private key is generated inside the device and never leaves it. If a user possessing this token attempts to access protected services on a remote network, the authorization process which grants or denies network access can establish, with a high degree of certainty, that the user seeking access is in physical possession of a known, certified token.

Something you know can be a password presented to the cryptographic device. Without presenting the proper password you cannot access the private secret key. Another feature of cryptographic devices is to prohibit the use of the private secret key if the wrong password had been presented more than an allowed number of times. This behavior ensures that if a user lost his device, it would be infeasible for another person to use it.

Cryptographic devices are commonly called “smart cards” or “tokens”, and are used in conjunction with a PKI (Public Key Infrastructure). The VPN server can examine a X.509 certificate and verify that the user holds the corresponding private secret key. Since the device cannot be duplicated and requires a valid password, the server is able to authenticate the user with a high degree of confidence.

Dual-factor authentication is much stronger than password-based authentication, because in the worst-case scenario, only one person at a time can use the cryptographic token. Passwords can be guessed and can be exposed to other users, so in the worst-case scenario an infinite number of people could attempt to gain unauthorized access when resources are protected using password-only authentication.

If you store the secret private key in a file, the key is usually encrypted by a password. The problem with this approach is that the encrypted key is exposed to decryption attacks or spyware/malware running on the client machine. Unlike when using a cryptographic device, the file cannot erase itself automatically after several failed decryption attempts.

什么是PKCS#11?

This standard specifies an API, called Cryptoki, to devices which hold cryptographic information and perform cryptographic functions. Cryptoki, pronounced “crypto-key” and short for cryptographic token interface, follows a simple object-based approach, addressing the goals of technology independence (any kind of device) and resource sharing (multiple applications accessing multiple devices), presenting to applications a common, logical view of the device called a cryptographic token.

Source: RSA Security Inc. https://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-11-cryptographic-token-interface-standard.htm.

To summarize, PKCS#11 is a standard that can be used by application software to access cryptographic tokens such as smart cards and other devices. Most device vendors provide a library that implements the PKCS#11 provider interface — this library can be used by applications in order to access these devices. PKCS#11 is a cross-platform, vendor-independent free standard.

Finding PKCS#11 provider library

The first thing you need to do is to find the provider library, it should be installed with the device drivers. Each vendor has its own library. For example, the OpenSC PKCS#11 provider is located at /usr/lib/pkcs11/opensc-pkcs11.so on Unix or at opensc-pkcs11.dll on Windows.

如何配置加密令牌

You should follow an enrollment procedure:

  • Initialize the PKCS#11 token.
  • Generate RSA key pair on the PKCS#11 token.
  • Create a certificate request based on the key pair, you can use OpenSC and OpenSSL in order to do that.
  • Submit the certificate request to a certificate authority, and receive a certificate.
  • Load the certificate onto the token, while noting that the id and label attributes of the certificate must match those of the private key.

A configured token is a token that has a private key object and a certificate object, where both share the same id and label attributes.

A simple enrollment utility is Easy-RSA 2.0 which is part of OpenVPN 2.1 series. Follow the instructions specified in the README file, and then use the pkitool in order to enroll.

Initialize a token using the following command:

$ ./pkitool --pkcs11-slots /usr/lib/pkcs11/
$ ./pkitool --pkcs11-init /usr/lib/pkcs11/  

Enroll a certificate using the following command:

$ ./pkitool --pkcs11 /usr/lib/pkcs11/   client1

如何修改OpenVPN配置以使用加密令牌

You should have OpenVPN 2.1 or above in order to use the PKCS#11 features.

Determine the correct object

Each PKCS#11 provider can support multiple devices. In order to view the available object list you can use the following command:

$ openvpn --show-pkcs11-ids /usr/lib/pkcs11/

The following objects are available for use.
Each object shown below may be used as parameter to
--pkcs11-id option please remember to use single quote mark.

Certificate
       DN:             /CN=User1
       Serial:         490B82C4000000000075
       Serialized id:  aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600

Each certificate/private key pair have unique “Serialized id” string. The serialized id string of the requested certificate should be specified to the pkcs11-id option using single quote marks.

pkcs11-id 'aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600'

将OpenVPN和PKCS#11一起使用

A typical set of OpenVPN options for PKCS#11
pkcs11-providers /usr/lib/pkcs11/
pkcs11-id 'aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600'

This will select the object which matches the pkcs11-id string.

Advanced OpenVPN options for PKCS#11
pkcs11-providers /usr/lib/pkcs11/provider1.so /usr/lib/pkcs11/provider2.so
pkcs11-id 'aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600'
pkcs11-pin-cache 300
daemon
auth-retry nointeract
management-hold
management-signal
management 127.0.0.1 8888
management-query-passwords

This will load two providers into OpenVPN, use the certificate specified on pkcs11-id option, and use the management interface in order to query passwords. The daemon will resume into hold state on the event when token cannot be accessed. The token will be used for 300 seconds after which the password will be re-queried, session will disconnect if management session disconnects.

PKCS#11 implementation considerations

Many PKCS#11 providers make use of threads, in order to avoid problems caused by implementation of LinuxThreads (setuid, chroot), it is highly recommend to upgrade to Native POSIX Thread Library (NPTL) enabled glibc if you intend to use PKCS#11.

OpenSC PKCS#11 provider

OpenSC PKCS#11 provider is located at /usr/lib/pkcs11/opensc-pkcs11.so on Unix or at opensc-pkcs11.dll on Windows.

PKCS#11和Microsoft加密API(CryptoAPI)之间的区别

PKCS#11 is a free, cross-platform vendor independent standard. CryptoAPI is a Microsoft specific API. Most smart card vendors provide support for both interfaces. In the Windows environment, the user should select which interface to use.

The current implementation of OpenVPN that uses the MS CryptoAPI (cryptoapicert option) works well as long as you don’t run OpenVPN as a service. If you wish to run OpenVPN in an administrative environment using a service, the implementation will not work with most smart cards because of the following reasons:

  • Most smart card providers do not load certificates into the local machine store, so the implementation will be unable to access the user certificate.
  • If the OpenVPN client is running as a service without direct interaction with the end-user, the service cannot query the user to provide a password for the smart card, causing the password-verification process on the smart card to fail.

Using the PKCS#11 interface, you can use smart cards with OpenVPN in any implementation, since PKCS#11 does not access Microsoft stores and does not necessarily require direct interaction with the end-user.


通过VPN路由所有客户端流量(包括网络流量)

概述

默认情况下,当OpenVPN客户端处于活动状态时,仅往返于OpenVPN服务器站点的网络流量将通过VPN。例如,一般的Web浏览将通过绕过VPN的直接连接来完成。

在某些情况下,这种行为可能不是所希望的 - 你可能希望VPN客户端通过VPN隧道传输所有网络流量,包括常规的Web浏览。虽然这种类型的VPN配置会严重影响客户端的性能,但当客户端同时同时连接到公共Internet和VPN时,它使VPN管理员可以更好地控制安全策略。

实现

将以下指令添加到服务器配置文件:

push "redirect-gateway def1"

如果您的VPN设置是通过无线网络进行的,其中所有客户端和服务器都在同一无线子网中,请添加local标志:

push "redirect-gateway local def1"

向客户端推送redirect-gateway选项将导致源自客户端计算机的所有IP网络流量都通过OpenVPN服务器。服务器将需要配置为以某种方式处理此流量,例如通过将其NAT到Internet或通过服务器站点的HTTP代理进行路由。

在Linux上,您可以使用以下命令将VPN客户端流量NAT到互联网:

iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

此命令假定VPN子网为10.8.0.0/24(取自OpenVPN服务器配置中的server指令),并且本地以太网接口为eth0

使用redirect-gateway时,OpenVPN客户端将通过VPN路由DNS查询,而VPN服务器将需要处理它们。这可以通过将DNS服务器地址推送到连接的客户端来实现,该客户端将在VPN处于活动状态时替换其常规DNS服务器设置。例如:

push "dhcp-option DNS 10.8.0.1"

会将Windows客户端(或带有某些额外服务器端脚本的非Windows客户端)配置为使用10.8.0.1作为其DNS服务器。客户端可访问的任何地址都可以用作DNS服务器地址。

注意事项

通过VPN重定向所有网络流量并非完全没有问题。以下是一些需要注意的典型陷阱:

  • Many OpenVPN client machines connecting to the internet will periodically interact with a DHCP server to renew their IP address leases. The redirect-gateway option might prevent the client from reaching the local DHCP server (because DHCP messages would be routed over the VPN), causing it to lose its IP address lease.
  • 许多连接到Internet的OpenVPN客户端计算机将定期与DHCP服务器进行交互,以更新其IP地址租约。redirect-gateway选项可能会阻止客户端访问本地DHCP服务器(因为DHCP消息将通过VPN路由),从而导致其IP地址租约丢失。
  • 关于将DNS地址推送到Windows客户端存在的问题
  • 客户端上的Web浏览性能将明显变慢。

有关**redirect-gateway指令的机制的详细信息,请参见manual page


在动态IP地址上运行OpenVPN服务器

While OpenVPN clients can easily access the server via a dynamic IP address without any special configuration, things get more interesting when the server itself is on a dynamic address. While OpenVPN has no trouble handling the situation of a dynamic server, some extra configuration is required.

The first step is to get a dynamic DNS address which can be configured to “follow” the server every time the server’s IP address changes. There are several dynamic DNS service providers available, such as dyndns.org.

The next step is to set up a mechanism so that every time the server’s IP address changes, the dynamic DNS name will be quickly updated with the new IP address, allowing clients to find the server at its new IP address. There are two basic ways to accomplish this:

  • Use a NAT router appliance with dynamic DNS support (such as the Linksys BEFSR41). Most of the inexpensive NAT router appliances that are widely available have the capability to update a dynamic DNS name every time a new DHCP lease is obtained from the ISP. This setup is ideal when the OpenVPN server box is a single-NIC machine inside the firewall.
  • Use a dynamic DNS client application such as ddclient to update the dynamic DNS address whenever the server IP address changes. This setup is ideal when the machine running OpenVPN has multiple NICs and is acting as a site-wide firewall/gateway. To implement this setup, you need to set up a script to be run by your DHCP client software every time an IP address change occurs. This script should (a) run ddclientto notify your dynamic DNS provider of your new IP address and (b) restart the OpenVPN server daemon.

The OpenVPN client by default will sense when the server’s IP address has changed, if the client configuration is using a remote directive which references a dynamic DNS name. The usual chain of events is that (a) the OpenVPN client fails to receive timely keepalive messages from the server’s old IP address, triggering a restart, and (b) the restart causes the DNS name in the remote directive to be re-resolved, allowing the client to reconnect to the server at its new IP address.

More information can be found in the FAQ.


通过HTTP代理连接到OpenVPN服务器

OpenVPN supports connections through an HTTP proxy, with the following authentication modes:

  • 无代理身份验证
  • Basic 代理身份验证
  • NTLM 代理身份验证

First of all, HTTP proxy usage requires that you use TCP as the tunnel carrier protocol. So add the following to both client and server configurations:

proto tcp

Make sure that any proto udp lines in the config files are deleted.

Next, add the http-proxy directive to the client configuration file (see the manual page for a full description of this directive).

For example, suppose you have an HTTP proxy server on the client LAN at 192.168.4.1, which is listening for connections on port 1080. Add this to the client config:

http-proxy 192.168.4.1 1080

Suppose the HTTP proxy requires Basic authentication:

http-proxy 192.168.4.1 1080 stdin basic

Suppose the HTTP proxy requires NTLM authentication:

http-proxy 192.168.4.1 1080 stdin ntlm

The two authentication examples above will cause OpenVPN to prompt for a username/password from standard input. If you would instead like to place these credentials in a file, replace stdin with a filename, and place the username on line 1 of this file and the password on line 2.


通过OpenVPN连接到Samba共享

This example is intended show how OpenVPN clients can connect to a Samba share over a routed dev tun tunnel. If you are ethernet bridging (dev tap), you probably don’t need to follow these instructions, as OpenVPN clients should see server-side machines in their network neighborhood.

For this example, we will assume that:

  • the server-side LAN uses a subnet of 10.66.0.0/24,
  • the VPN IP address pool uses 10.8.0.0/24 (as cited in the server directive in the OpenVPN server configuration file),
  • the Samba server has an IP address of 10.66.0.4, and
  • the Samba server has already been configured and is reachable from the local LAN.

If the Samba and OpenVPN servers are running on different machines, make sure you’ve followed the section on expanding the scope of the VPN to include additional machines.

Next, edit your Samba configuration file (smb.conf). Make sure the hosts allow directive will permit OpenVPN clients coming from the 10.8.0.0/24 subnet to connect. For example:

hosts allow = 10.66.0.0/24 10.8.0.0/24 127.0.0.1

If you are running the Samba and OpenVPN servers on the same machine, you may want to edit the interfaces directive in the smb.conf file to also listen on the TUN interface subnet of 10.8.0.0/24:

interfaces  = 10.66.0.0/24 10.8.0.0/24

If you are running the Samba and OpenVPN servers on the same machine, connect from an OpenVPN client to a Samba share using the folder name:

\\10.8.0.1\\sharename

If the Samba and OpenVPN servers are on different machines, use folder name:

\\10.66.0.4\sharename

For example, from a command prompt window:

net use z: \\10.66.0.4\sharename /USER:myusername

实现负载平衡/故障转移配置

客户端

The OpenVPN client configuration can refer to multiple servers for load balancing and failover. For example:

remote server1.mydomain
remote server2.mydomain
remote server3.mydomain

will direct the OpenVPN client to attempt a connection with server1, server2, and server3 in that order. If an existing connection is broken, the OpenVPN client will retry the most recently connected server, and if that fails, will move on to the next server in the list. You can also direct the OpenVPN client to randomize its server list on startup, so that the client load will be probabilistically spread across the server pool.

remote-random

If you would also like DNS resolution failures to cause the OpenVPN client to move to the next server in the list, add the following:

resolv-retry 60

The 60 parameter tells the OpenVPN client to try resolving each remote DNS name for 60 seconds before moving on to the next server in the list.

The server list can also refer to multiple OpenVPN server daemons running on the same machine, each listening for connections on a different port, for example:

remote smp-server1.mydomain 8000
remote smp-server1.mydomain 8001
remote smp-server2.mydomain 8000
remote smp-server2.mydomain 8001

If your servers are multi-processor machines, running multiple OpenVPN daemons on each server can be advantageous from a performance standpoint.

OpenVPN also supports the remote directive referring to a DNS name which has multiple A records in the zone configuration for the domain. In this case, the OpenVPN client will randomly choose one of the A records every time the domain is resolved.

服务端

The simplest approach to a load-balanced/failover configuration on the server is to use equivalent configuration files on each server in the cluster, except use a different virtual IP address pool for each server. For example:

server1

server 10.8.0.0 255.255.255.0

server2

server 10.8.1.0 255.255.255.0

server3

server 10.8.2.0 255.255.255.0

加强OpenVPN安全性

One of the often-repeated maxims of network security is that one should never place so much trust in a single security component that its failure causes a catastrophic security breach. OpenVPN provides several mechanisms to add additional security layers to hedge against such an outcome.

tls-auth

The tls-auth directive adds an additional HMAC signature to all SSL/TLS handshake packets for integrity verification. Any UDP packet not bearing the correct HMAC signature can be dropped without further processing. The tls-auth HMAC signature provides an additional level of security above and beyond that provided by SSL/TLS. It can protect against:

  • DoS attacks or port flooding on the OpenVPN UDP port.
  • Port scanning to determine which server UDP ports are in a listening state.
  • Buffer overflow vulnerabilities in the SSL/TLS implementation.
  • SSL/TLS handshake initiations from unauthorized machines (while such handshakes would ultimately fail to authenticate, tls-auth can cut them off at a much earlier point).

Using tls-auth requires that you generate a shared-secret key that is used in addition to the standard RSA certificate/key:

openvpn --genkey --secret ta.key

This command will generate an OpenVPN static key and write it to the file ta.key. This key should be copied over a pre-existing secure channel to the server and all client machines. It can be placed in the same directory as the RSA .key and .crt files.

In the server configuration, add:

tls-auth ta.key 0

In the client configuration, add:

tls-auth ta.key 1

proto udp

While OpenVPN allows either the TCP or UDP protocol to be used as the VPN carrier connection, the UDP protocol will provide better protection against DoS attacks and port scanning than TCP:

proto udp

user/group (仅限非Windows)

OpenVPN has been very carefully designed to allow root privileges to be dropped after initialization, and this feature should always be used on Linux/BSD/Solaris. Without root privileges, a running OpenVPN server daemon provides a far less enticing target to an attacker.

user nobody
group nobody

非特权模式(仅限Linux)

On Linux OpenVPN can be run completely unprivileged. This configuration is a little more complex, but provides best security.

In order to work with this configuration, OpenVPN must be configured to use iproute interface, this is done by specifying –enable-iproute2 to configure script. sudo package should also be available on your system.

This configuration uses the Linux ability to change the permission of a tun device, so that unprivileged user may access it. It also uses sudo in order to execute iproute so that interface properties and routing table may be modified.

OpenVPN configuration:

    • Write the following script and place it at: /usr/local/sbin/unpriv-ip:
#!/bin/sh
sudo /sbin/ip $*
    • Execute visudo, and add the followings to allow user ‘user1’ to execute /sbin/ip:
user1 ALL=(ALL)  NOPASSWD: /sbin/ip
%users ALL=(ALL)  NOPASSWD: /sbin/ip
    • Add the following to your OpenVPN configuration:
dev tunX/tapX
iproute /usr/local/sbin/unpriv-ip
    • Please note that you must select constant X and specify tun or tap not both.
    • As root add persistant interface, and permit user and/or group to manage it, the following create tunX (replace with your own) and allow user1 and group users to access it.
openvpn --mktun --dev tunX --type tun --user user1 --group users
  • Run OpenVPN in the context of the unprivileged user.

Further security constraints may be added by examining the parameters at the /usr/local/sbin/unpriv-ip script.

chroot(仅限非Windows)

The chroot directive allows you to lock the OpenVPN daemon into a so-called chroot jail, where the daemon would not be able to access any part of the host system’s filesystem except for the specific directory given as a parameter to the directive. For example,

chroot jail

would cause the OpenVPN daemon to cd into the jail subdirectory on initialization, and would then reorient its root filesystem to this directory so that it would be impossible thereafter for the daemon to access any files outside of jail and its subdirectory tree. This is important from a security perspective, because even if an attacker were able to compromise the server with a code insertion exploit, the exploit would be locked out of most of the server’s filesystem.

Caveats: because chroot reorients the filesystem (from the perspective of the daemon only), it is necessary to place any files which OpenVPN might need after initialization in the jail directory, such as:

  • the crl-verify file, or
  • the client-config-dir directory.

更大的RSA秘钥

The RSA key size is controlled by the KEY_SIZE variable in the easy-rsa/vars file, which must be set before any keys are generated. Currently set to 1024 by default, this value can reasonably be increased to 2048 with no negative impact on VPN tunnel performance, except for a slightly slower SSL/TLS renegotiation handshake which occurs once per client per hour, and a much slower one-time Diffie Hellman parameters generation process using the easy-rsa/build-dh script.

更大的对称秘钥

By default OpenVPN uses Blowfish, a 128 bit symmetrical cipher.

OpenVPN automatically supports any cipher which is supported by the OpenSSL library, and as such can support ciphers which use large key sizes. For example, the 256-bit version of AES (Advanced Encryption Standard) can be used by adding the following to both server and client configuration files:

cipher AES-256-CBC

将根秘钥(ca.key)保存到一台没有网络连接的独立机器上

One of the security benefits of using an X509 PKI (as OpenVPN does) is that the root CA key (ca.key) need not be present on the OpenVPN server machine. In a high security environment, you might want to specially designate a machine for key signing purposes, keep the machine well-protected physically, and disconnect it from all networks. Floppy disks can be used to move key files back and forth, as necessary. Such measures make it extremely difficult for an attacker to steal the root key, short of physical theft of the key signing machine.


吊销证书

Revoking a certificate means to invalidate a previously signed certificate so that it can no longer be used for authentication purposes.

Typical reasons for wanting to revoke a certificate include:

  • The private key associated with the certificate is compromised or stolen.
  • The user of an encrypted private key forgets the password on the key.
  • You want to terminate a VPN user’s access.

示例

As an example, we will revoke the client2 certificate, which we generated above in the “key generation” section of the HOWTO.

First open up a shell or command prompt window and cd to the easy-rsa directory as you did in the “key generation” section above. On Linux/BSD/Unix:

. ./vars
./revoke-full client2

On Windows:

vars
revoke-full client2

You should see output similar to this:

Using configuration from /root/openvpn/20/openvpn/tmp/easy-rsa/openssl.cnf
DEBUG[load_index]: unique_subject = "yes"
Revoking Certificate 04.
Data Base Updated
Using configuration from /root/openvpn/20/openvpn/tmp/easy-rsa/openssl.cnf
DEBUG[load_index]: unique_subject = "yes"
client2.crt: /C=KG/ST=NA/O=OpenVPN-TEST/CN=client2/emailAddress=me@myhost.mydomain
error 23 at 0 depth lookup:certificate revoked

Note the “error 23” in the last line. That is what you want to see, as it indicates that a certificate verification of the revoked certificate failed.

The revoke-full script will generate a CRL (certificate revocation list) file called crl.pem in the keyssubdirectory. The file should be copied to a directory where the OpenVPN server can access it, then CRL verification should be enabled in the server configuration:

crl-verify crl.pem

Now all connecting clients will have their client certificates verified against the CRL, and any positive match will result in the connection being dropped.

CRL Notes

  • When the crl-verify option is used in OpenVPN, the CRL file will be re-read any time a new client connects or an existing client renegotiates the SSL/TLS connection (by default once per hour). This means that you can update the CRL file while the OpenVPN server daemon is running, and have the new CRL take effect immediately for newly connecting clients. If the client whose certificate you are revoking is already connected, you can restart the server via a signal (SIGUSR1 or SIGHUP) and flush all clients, or you can telnet to the management interfaceand explicitly kill the specific client instance object on the server without disturbing other clients.
  • While the crl-verify directive can be used on both the OpenVPN server and clients, it is generally unnecessary to distribute a CRL file to clients unless a server certificate has been revoked. Clients don’t need to know about other client certificates which have been revoked because clients shouldn’t be accepting direct connections from other clientsin the first place.
  • The CRL file is not secret, and should be made world-readable so that the OpenVPN daemon can read it after root privileges have been dropped.
  • If you are using the chrootdirective, make sure to put a copy of the CRL file in the chroot directory, since unlike most other files which OpenVPN reads, the CRL file will be read after the chroot call is executed, not before.
  • A common reason why certificates need to be revoked is that the user encrypts their private key with a password, then forgets the password. By revoking the original certificate, it is possible to generate a new certificate/key pair with the user’s original common name.

Important Note on possible “Man-in-the-Middle” attack if clients do not verify the certificate of the server they are connecting to.

To avoid a possible Man-in-the-Middle attack where an authorized client tries to connect to another client by impersonating the server, make sure to enforce some kind of server certificate verification by clients. There are currently five different ways of accomplishing this, listed in the order of preference:

  • [OpenVPN 2.1 and above]

    Build your server certificates with specific key usage and extended key usage. The RFC3280 determine that the following attributes should be provided for TLS connections:

    ModeKey usageExtended key usage
    ClientdigitalSignatureTLS Web Client Authentication
    keyAgreement
    digitalSignature, keyAgreement
    ServerdigitalSignature, keyEnciphermentTLS Web Server Authentication
    digitalSignature, keyAgreement

    You can build your server certificates with the build-key-server script (see the easy-rsadocumentation for more info). This will designate the certificate as a server-only certificate by setting the right attributes. Now add the following line to your client configuration:

    remote-cert-tls server
  • [OpenVPN 2.0 and below]

    Build your server certificates with the build-key-server script (see the easy-rsa documentation for more info). This will designate the certificate as a server-only certificate by setting nsCertType=server. Now add the following line to your client configuration:

    ns-cert-type server

    This will block clients from connecting to any server which lacks the nsCertType=server designation in its certificate, even if the certificate has been signed by the ca file in the OpenVPN configuration file.

  • Use the tls-remotedirective on the client to accept/reject the server connection based on the common name of the server certificate.
  • Use a tls-verifyscript or plugin to accept/reject the server connection based on a custom test of the server certificate’s embedded X509 subject details.
  • Sign server certificates with one CA and client certificates with a different CA. The client configuration ca directive should reference the server-signing CA file, while the server configuration cadirective should reference the client-signing CA file.
最后修改:2021 年 10 月 27 日
如果觉得我的文章对你有用,请随意赞赏