OpenVPN 是一个功能齐全的 SSL VPN,它使用行业标准 SSL/TLS 协议实现 OSI 第 2 层或第 3 层安全网络扩展,支持基于证书、智能卡和/或用户名/密码凭证的灵活客户端身份验证方法,并允许用户或使用应用于 VPN 虚拟接口的防火墙规则的组特定访问控制策略。OpenVPN 不是网络应用程序代理,不通过网络浏览器运行。
OpenVPN 2.0 通过提供可扩展的客户端/服务器模式扩展了 OpenVPN 1.x的功能 ,允许多个客户端通过单个 TCP 或 UDP 端口连接到单个 OpenVPN 服务器进程。OpenVPN 2.3 包含 大量改进,包括完整的 IPv6 支持和 PolarSSL 支持。
本文档提供了配置 OpenVPN 2.x 客户端/服务器 VPN 的分步说明,包括:
不耐烦的人可能希望直接跳转到示例配置文件:
本文档假设读者事先了解基本的网络概念,例如 IP 地址、DNS 名称、网络掩码、子网、IP 路由、路由器、网络接口、LAN、网关和防火墙规则。
请查看 OpenVPN 书籍页面。
原始的 OpenVPN 1.x HOWTO 仍然可用,并且仍然适用于点对点或静态密钥配置。
有关其他文档,请参阅 文章页面 和 OpenVPN wiki。
虽然本文档将指导您使用 X509 PKI(使用证书和私钥的公钥基础设施)设置可扩展的客户端/服务器 VPN,但如果您只是在寻找一个简单的 VPN 设置和一个可以处理的服务器,这可能是矫枉过正的。一个客户。
如果您想以最少的配置快速运行 VPN,您可以查看 静态密钥 Mini-HOWTO。
OpenVPN 源代码和 Windows 安装程序可以在 这里下载。最近的版本(2.2 和更高版本)也可以作为 Debian 和 RPM 软件包提供;有关详细信息,请参阅 OpenVPN wiki 。
为了安全起见,最好在下载后检查 文件发布签名 。
OpenVPN 可执行文件应安装在服务器和客户端机器上,因为单个可执行文件同时提供客户端和服务器功能。
如果您使用的是支持 RPM 软件包(SuSE、Fedora、Redhat 等)的 Linux 发行版,最好使用这种机制进行安装。最简单的方法是为您的发行版找到一个现有的二进制 RPM 文件。您还可以构建自己的二进制 RPM 文件:
rpmbuild -tb open-[version].tar.gz
一旦你有了 .rpm 文件,你可以用通常的方式安装它
rpm -ivh open-[details].rpm
或升级现有安装
rpm -Uvh open-[details].rpm
从二进制 RPM 包安装 OpenVPN 具有以下依赖项:
此外,如果您正在构建自己的二进制 RPM 包,还有几个额外的依赖项:
请参阅 open.spec 文件以获取有关为 Red Hat Linux 9 构建 RPM 包或减少依赖项的构建的其他说明。
如果您使用的是 Debian、Gentoo 或非基于 RPM 的 Linux 发行版,请使用发行版特定的打包机制,例如 Debian 上的apt-get或 Gentoo 上的Emerge 。
也可以使用通用的 ./configure 方法在 Linux 上安装 OpenVPN。首先展开 .tar.gz 文件:
tar xfz open-[version].tar.gz
然后 cd 到顶级目录并键入:
./configure
make
make install
可以从OpenVPN 下载页面上的自安装 exe 文件安装适用于 Windows 的 OpenVPN 。请记住,OpenVPN 只能在 Windows XP 或更高版本上运行。另请注意,OpenVPN 必须由具有管理权限的用户安装和运行(此限制是由 Windows 施加的,而不是 OpenVPN)。通过在后台运行 OpenVPN 作为服务可以避开限制,在这种情况下,即使是非管理员用户也可以在安装 VPN 后访问它。 更多关于 OpenVPN + Windows 权限问题的讨论。
官方 OpenVPN Windows 安装程序包括 OpenVPN-GUI,它允许从系统托盘小程序管理 OpenVPN 连接。其他 GUI 应用程序也可用。
运行 Windows 安装程序后,OpenVPN 就可以使用了,并将与具有 .o 扩展名的文件相关联。要运行 OpenVPN,您可以:
open myconfig.o
在命令提示符窗口中运行后,可以按 F4 键停止 OpenVPN。
其他 Windows 安装说明。
Angelo Laub 和 Dirk Theisen 为 OS X 开发了一个 OpenVPN GUI。
特定操作系统的安装 文件中提供了一些注释 。一般来说,
./configure
make
make install
可以使用方法,或者您可以搜索特定于您的操作系统/发行版的 OpenVPN 端口或包。
有关路由与以太网桥接的概述,请参阅 常见问题解答。另请参阅 OpenVPN 以太网桥接 页面以获取有关桥接的更多说明和详细信息。
总体而言,路由对于大多数人来说可能是更好的选择,因为它比桥接更有效且更容易设置(就 OpenVPN 配置本身而言)。路由还提供了更大的能力,可以在特定于客户端的基础上选择性地控制访问权限。
我建议使用路由,除非您需要需要桥接的特定功能,例如:
设置 VPN 通常需要将来自不同位置的私有子网链接在一起。
互联网号码分配机构 (IANA) 为私有互联网保留了以下三个 IP 地址空间块(编入 RFC 1918):
10.0.0.0 | 10.255.255.255 | (10/8 prefix) |
172.16.0.0 | 172.31.255.255 | (172.16/12 prefix) |
192.168.0.0 | 192.168.255.255 | (192.168/16 prefix) |
虽然这些网络块中的地址通常应在 VPN 配置中使用,但选择将 IP 地址或子网冲突概率降至最低的地址很重要。需要避免的冲突类型有:
例如,假设您使用流行的 192.168.0.0/24 子网作为您的私有 LAN 子网。现在,您正尝试从使用同一子网作为其 WiFi LAN 的网吧连接到 VPN。您将遇到路由冲突,因为您的机器不知道 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 子网使用唯一编号。
构建 OpenVPN 2.x 配置的第一步是建立 PKI(公钥基础设施)。PKI 包括:
OpenVPN支持基于证书的双向认证,即客户端必须认证服务器证书,服务器必须认证客户端证书才能建立互信。
服务器和客户端都将首先验证提供的证书是否由主证书颁发机构 (CA) 签名,然后通过测试现在已验证的证书标头中的信息,例如证书公用名或证书类型(客户端或服务器)。
从 VPN 的角度来看,这种安全模型具有许多理想的特性:
请注意,服务器和客户端时钟需要大致同步,否则证书可能无法正常工作。
在本节中,我们将为 3 个单独的客户端生成主 CA 证书/密钥、服务器证书/密钥和证书/密钥。
对于 PKI 管理,我们将使用 easy-rsa 2,这是一组与 OpenVPN 2.2.x 及更早版本捆绑在一起的脚本。如果您使用的是 OpenVPN 2.3.x,则需要从 此处单独下载 easy-rsa 2 。
对于 PKI 管理,我们将使用 easy-rsa 2,这是一组与 OpenVPN 2.2.x 及更早版本捆绑在一起的脚本。如果您使用的是 OpenVPN 2.3.x,您可能需要从 easy-rsa-old 项目页面单独下载 easy-rsa 2 。在 *NIX 平台上,您应该考虑使用 easy-rsa 3;有关详细信息,请参阅其自己的文档。
如果您使用的是 Linux、BSD 或类似 unix 的操作系统,请打开 shell 并 cd 到 easy-rsa 子目录。如果您从 RPM 或 DEB 文件安装 OpenVPN,easy-rsa 目录通常可以在 /usr/share/doc/packages/open 或 /usr/share/doc/open中找到(最好将此目录复制到另一个位置例如 /etc/open,在任何编辑之前,以便将来的 OpenVPN 软件包升级不会覆盖您的修改)。如果从 .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 [[email protected]]:
请注意,在上述序列中,大多数查询的参数都默认为 vars或 vars.bat 文件中设置的值。唯一必须明确输入的参数是 Common Name。在上面的示例中,我使用了“OpenVPN-CA”。
接下来,我们将为服务器生成证书和私钥。在 Linux/BSD/Unix 上:
./build-key-server server
在 Windows 上:
build-key-server server
与上一步一样,大多数参数都可以默认。查询Common Name时 ,输入“server”。另外两个查询需要积极响应,“签署证书?[y/n]”和“1 出的 1 个证书请求已通过认证,提交?[y/n]”。
生成客户端证书与上一步非常相似。在 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 脚本。
请记住,对于每个客户端,请确保在出现提示时键入适当的 Common Name ,即“client1”、“client2”或“client3”。始终为每个客户端使用唯一的通用名称。
必须为 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 子目录中找到我们新生成的密钥和证书 。以下是相关文件的解释:
Filename | Needed By | Purpose | Secret |
ca.crt | server + all clients | Root CA certificate | NO |
ca.key | key signing machine only | Root CA key | YES |
dh{n}.pem | server only | Diffie Hellman parameters | NO |
server.crt | server only | Server Certificate | NO |
server.key | server only | Server Key | YES |
client1.crt | client1 only | Client1 Certificate | NO |
client1.key | client1 only | Client1 Key | YES |
client2.crt | client2 only | Client2 Certificate | NO |
client2.key | client2 only | Client2 Key | YES |
client3.crt | client3 only | Client3 Certificate | NO |
client3.key | client3 only | Client3 Key | YES |
密钥生成过程的最后一步是将所有文件复制到需要它们的机器上,注意通过安全通道复制秘密文件。
现在等等,你可能会说。难道不应该在没有预先存在的安全通道的情况下设置 PKI 吗?
答案表面上是肯定的。在上面的例子中,为了简洁起见,我们在同一个地方生成了所有的私钥。再多一点努力,我们就可以做到这一点。例如,我们可以让客户端在本地生成自己的私钥,然后向密钥签名机器提交证书签名请求 (CSR),而不是在服务器上生成客户端证书和密钥。反过来,密钥签名机器可以处理 CSR 并将签名证书返回给客户端。这可以在不需要秘密 .key 文件离开生成它的机器的硬盘驱动器的情况下完成。
最好使用 OpenVPN 示例配置文件作为您自己配置的起点。这些文件也可以在
请注意,在 Linux、BSD 或类 unix 操作系统上,示例配置文件名为 server.conf 和 client.conf。在 Windows 上,它们被命名为 server.o 和 client.o。
示例服务器配置文件是 OpenVPN 服务器配置的理想起点。它将使用虚拟 TUN 网络接口(用于路由)创建 VPN,侦听 UDP 端口 1194 (OpenVPN 的官方端口号)上的客户端连接,并将虚拟地址分配给来自10.8.0.0/24 子网 的连接客户端 。
在使用示例配置文件之前,您应该首先编辑 ca、 cert、 key和 dh 参数以指向您在上面的 PKI 部分中生成的文件。
此时,服务器配置文件可用,但您仍可能需要进一步自定义它:
如果您想在同一台机器上运行多个 OpenVPN 实例,每个实例使用不同的配置文件,您可以:
示例客户端配置文件( Linux/BSD/Unix 上 的client.conf或 Windows 上的client.o )反映了示例服务器配置文件中设置的默认指令。
首先,确保可以从 Internet 访问 OpenVPN 服务器。这意味着:
接下来, 确保 TUN/TAP 接口没有防火墙。
为了简化故障排除,最好首先从命令行启动 OpenVPN 服务器(或在 Windows 上右键单击 .o 文件),而不是将其作为守护程序或服务启动:
open [server config file]
正常的服务器启动应该是这样的(输出会因平台而异):
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.o 文件),而不是将其作为守护程序或服务启动:
open [client config file]
Windows 上的正常客户端启动看起来类似于上面的服务器输出,并且应该以 Initialization Sequence Completed 消息结束。
现在,尝试从客户端对 VPN 执行 ping 操作。如果您正在使用路由(即 服务器配置文件中的dev tun ),请尝试:
ping 10.8.0.1
如果您正在使用桥接(即 服务器配置文件中的dev tap ),请尝试 ping 服务器以太网子网上的机器的 IP 地址。
如果 ping 成功,恭喜!您现在拥有一个正常运行的 VPN。
如果 ping 失败或 OpenVPN 客户端初始化未能完成,以下是常见症状及其解决方案的清单:
TLS: Initial packet from x.x.x.x:x, sid=xxxxxxxx xxxxxxxx
但是客户端日志没有显示等效的行。
解决方案:您有一个从客户端到服务器的单向连接。服务器到客户端的方向被防火墙阻止,通常在客户端。防火墙可以是 (a) 在客户端上运行的个人软件防火墙,或 (b) 客户端的 NAT 路由器网关。修改防火墙以允许从服务器返回的 UDP 数据包到达客户端。
有关其他故障排除信息,请参阅 常见问题解答。
这方面缺乏标准意味着大多数操作系统都有不同的方式来配置守护进程/服务以在启动时自动启动。默认情况下配置此功能的最佳方法是将 OpenVPN 安装为一个包,例如通过 Linux 上的 RPM 或使用 Windows 安装程序。
如果您在 Linux 上通过 RPM 或 DEB 包安装 OpenVPN,安装程序将设置一个 initscript。执行时,initscript 将扫描 /etc/open里的.conf 配置文件 ,如果找到,将为每个文件启动一个单独的 OpenVPN 守护程序。
Windows 安装程序将设置 Service Wrapper,但默认情况下将其关闭。要激活它,请转到控制面板/管理工具/服务,选择 OpenVPN 服务,右键单击属性,然后将启动类型设置为自动。这会将服务配置为在下次重新启动时自动启动。
启动后,OpenVPN Service Wrapper 将扫描 \Program Files\OpenVPN\config 文件夹中的 .o 配置文件,并在每个文件上启动一个单独的 OpenVPN 进程。
OpenVPN 接受几个信号:
使用 writepid 指令将 OpenVPN 守护进程的 PID 写入文件,以便您知道将信号发送到哪里(如果您使用 initscript启动 open ,则脚本可能已经 在open 命令行上传递了--writepid 指令 ) .
请参阅 OpenVPN GUI 页面。
在 Windows 上,您可以通过右键单击 OpenVPN 配置文件(.o 文件)并选择“在此配置文件上启动 OpenVPN”来启动 OpenVPN。
以这种方式运行后,可以使用几个键盘命令:
当 OpenVPN 在 Windows 上作为服务启动时,控制它的唯一方法是:
虽然大多数配置更改都需要您重新启动服务器,但有两个指令特别指向可以动态更新的文件,并且无需重新启动服务器进程即可立即在服务器上生效。
client-config-dir -- 该指令设置客户端配置目录,OpenVPN 服务器将扫描每个传入连接,搜索特定于客户端的配置文件(有关更多信息,请参阅 手册页 )。此目录中的文件可以即时更新,而无需重新启动服务器。请注意,此目录中的更改仅对新连接生效,对现有连接无效。如果您希望特定于客户端的配置文件更改对当前连接的客户端(或已断开连接,但服务器尚未使其实例对象超时的客户端)立即生效,请使用管理终止客户端实例对象接口(如下所述)。这将导致客户端重新连接并使用新的 客户端配置目录 文件。
crl-verify -- 该指令命名 证书吊销列表 文件,如下文 吊销证书 部分所述。CRL 文件可以即时修改,并且更改将立即对新连接或正在重新协商其 SSL/TLS 通道的现有连接生效(默认情况下每小时发生一次)。如果您想终止当前连接的客户端,其证书刚刚添加到 CRL,请使用管理界面(如下所述)。
默认的 server.conf 文件有一行
status open-status.log
它将每分钟输出一次到文件open-status.log的当前客户端连接列表 。
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 的范围,以便客户端可以访问服务器网络上的多台机器,而不仅仅是服务器机器本身。
出于本示例的目的,我们假设服务器端 LAN 使用子网 10.66.0.0/24,VPN IP 地址池使用 OpenVPN 服务器配置文件中的server指令中 引用的 10.8.0.0/24 。
首先,您必须 将 10.66.0.0/24子网通告 给 VPN 客户端,因为它可以通过 VPN 访问。这可以通过以下服务器端配置文件指令轻松完成:
push "route 10.66.0.0 255.255.255.0"
接下来,您必须在服务器端 LAN 网关上设置路由,以将 VPN 客户端子网 ( 10.8.0.0/24 ) 路由到 OpenVPN 服务器(仅当 OpenVPN 服务器和 LAN 网关是不同的机器时才需要这样做)。
确保您 在 OpenVPN 服务器机器上启用了IP 和 TUN/TAP转发。
使用以太网桥接的好处之一 是您无需任何额外配置即可免费获得此功能。
在典型的公路战士或远程访问场景中,客户端计算机作为单台计算机连接到 VPN。但是假设客户端机器是本地 LAN(例如家庭办公室)的网关,并且您希望客户端 LAN 上的每台机器都能够通过 VPN 进行路由。
对于此示例,我们将假设客户端 LAN 使用 192.168.4.0/24 子网,并且 VPN 客户端使用通用名称为 client2的证书。我们的目标是设置 VPN,以便客户端 LAN 上的任何机器都可以通过 VPN 与服务器 LAN 上的任何机器通信。
在设置之前,必须遵循一些基本的先决条件:
首先,确保 在客户端机器上启用了IP 和 TUN/TAP转发。
接下来,我们将在服务器端处理必要的配置更改。如果服务器配置文件当前没有引用客户端配置目录,现在添加一个:
client-config-dir ccd
在上述指令中, ccd 应该是在默认目录中预先创建的目录名称,该目录运行 OpenVPN 服务器守护程序。在 Linux 上,这往往是 /etc/open 而在 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
您可能会问,为什么会有多余的 route 和 iroute 语句?原因是 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 服务器框 是服务器局域网)。假设您错过了这一步,并且您尝试从 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 客户端机器。
这需要更复杂的设置(在实践中可能不会更复杂,但要详细解释更复杂):
OpenVPN 服务器可以将 DHCP 选项(例如 DNS 和 WINS 服务器地址)推送到客户端(需要注意的一些 警告 )。Windows 客户端可以本机接受推送的 DHCP 选项,而非 Windows 客户端可以通过使用解析 foreign_option_n 环境变量列表的客户端 向上 脚本 来接受它们。 有关非 Windows 的 foreign_option_n文档和 脚本示例,请参见 手册页。
例如,假设您希望连接客户端以使用位于 10.66.0.4 或 10.66.0.5 的内部 DNS 服务器和位于 10.66.0.8 的 WINS 服务器。将此添加到 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,我们想为 3 类不同的用户建立单独的访问策略:
我们将采用的基本方法是 (a) 将每个用户类别隔离到其自己的虚拟 IP 地址范围内,以及 (b) 通过设置关闭客户端虚拟 IP 地址的防火墙规则来控制对机器的访问。
在我们的示例中,假设我们有可变数量的员工,但只有一名系统管理员和两名承包商。我们的IP分配方式是将所有员工放入一个IP地址池中,然后为系统管理员和承包商分配固定的IP地址。
请注意,此示例的先决条件之一是您在 OpenVPN 服务器计算机上运行了软件防火墙,这使您能够定义特定的防火墙规则。对于我们的示例,我们将假设防火墙是 Linux iptables。
首先,让我们根据用户类创建一个虚拟IP地址映射:
班级 | 虚拟 IP 范围 | 允许的局域网访问 | 通用名称 |
Employees | 10.8.0.0/24 | 位于 10.66.4.4 的 Samba/电子邮件服务器 | [变量] |
System Administrators | 10.8.1.0/24 | 整个 10.66.4.0/24 子网 | sysadmin1 |
Contractors | 10.8.2.0/24 | 承包商服务器位于 10.66.4.12 | contractor1, 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 子目录中,为每个非员工 VPN 客户端定义固定 IP 地址。
ifconfig-push 10.8.1.1 10.8.1.2
ifconfig-push 10.8.2.1 10.8.2.2
ifconfig-push 10.8.2.5 10.8.2.6
每对 ifconfig-push 地址代表虚拟客户端和服务器 IP 端点。它们必须取自连续的 /30 子网,以便与 Windows 客户端和 TAP-Windows 驱动程序兼容。具体来说,每个端点对的 IP 地址中的最后一个八位字节必须取自该集合:
[ 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 配置。最后一步是添加防火墙规则以最终确定访问策略。对于此示例,我们将使用 Linux iptables 语法中的防火墙规则:
# Employee rule
iptables -A FORWARD -i tun0 -s 10.8.0.0/24 -d 10.66.4.4 -j ACCEPT
# Sysadmin rule
iptables -A FORWARD -i tun0 -s 10.8.1.0/24 -d 10.66.4.0/24 -j ACCEPT
# Contractor rule
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。每次 VPN 客户端尝试连接时,OpenVPN 服务器都会调用该插件,并将在客户端输入的用户名/密码传递给它。身份验证插件可以通过返回失败 (1) 或成功 (0) 值来控制 OpenVPN 服务器是否允许客户端连接。
可以通过将 auth-user-pass-verify 指令添加到服务器端配置文件来使用脚本插件。例如:
auth-user-pass-verify auth-pam.pl via-file
将使用 auth-pam.pl perl 脚本来验证连接客户端的用户名/密码。有关详细信息,请参阅 手册页中对auth-user-pass-verify 的 描述 。
auth-pam.pl 脚本包含在示例脚本子目录中的 OpenVPN 源文件 分发中。它将使用 PAM 身份验证模块对 Linux 服务器上的用户进行身份验证,该模块又可以实现影子密码、RADIUS 或 LDAP 身份验证。 auth-pam.pl 主要用于演示目的。对于真实世界的 PAM 身份验证,请使用下面描述的 open-auth-pam共享对象插件。
共享对象或 DLL 插件通常是由 OpenVPN 服务器在运行时加载的编译 C 模块。例如,如果您在 Linux 上使用基于 RPM 的 OpenVPN 软件包,则 应该已经构建了open-auth-pam插件。要使用它,请将其添加到服务器端配置文件中:
plugin /usr/share/open/plugin/lib/open-auth-pam.so login
这将告诉 OpenVPN 服务器验证客户端使用 登录PAM 模块输入的用户名/密码。
对于实际生产使用,最好使用 open-auth-pam插件,因为它比auth-pam.pl 脚本 有几个优点 :
如果您想了解更多关于开发自己的插件以用于 OpenVPN 的信息,请参阅 OpenVPN 源代码分发的插件 子目录中的自述 文件 。
要在 Linux 上 构建 open-auth-pam插件,请 cd 到 OpenVPN 源代码分发中 的plugin/auth-pam目录并运行make。
默认情况下,使用 auth-user-pass-verify 或服务器上的用户名/密码检查 插件 将启用双重身份验证,要求客户端证书和用户名/密码身份验证都成功才能对客户端进行身份验证。
虽然从安全角度不鼓励这样做,但也可以禁用客户端证书,并仅强制用户名/密码验证。在服务器上:
client-cert-not-required
此类配置通常还应设置:
username-as-common-name
这将告诉服务器将用户名用于索引目的,因为它将使用通过客户端证书进行身份验证的客户端的通用名称。
请注意, client-cert-not-required 不会消除对服务器证书的需要,因此连接到使用 client-cert-not-required的服务器的客户端 可能会从客户端配置文件中删除 cert 和 key 指令,但不会ca指令, 因为客户端需要验证服务器证书。
双因素身份验证是一种结合两个元素的身份验证方法:您拥有的东西和您知道的东西。
您拥有的东西应该是无法复制的设备;这样的设备可以是包含私有密钥的加密令牌。此私钥在设备内部生成并且永远不会离开它。如果拥有此令牌的用户试图访问远程网络上的受保护服务,则授予或拒绝网络访问的授权过程可以高度确定地确定寻求访问的用户实际拥有已知的、经过认证的令牌.
您知道的东西可能是提供给加密设备的密码。如果不提供正确的密码,您将无法访问私有密钥。密码设备的另一个特点是,如果错误密码的出现次数超过了允许的次数,则禁止使用私有密钥。这种行为确保如果用户丢失了他的设备,其他人将无法使用它。
加密设备通常被称为“智能卡”或“令牌”,并与 PKI(公钥基础设施)结合使用。VPN 服务器可以检查 X.509 证书并验证用户是否持有相应的私有密钥。由于设备无法复制并且需要有效密码,因此服务器能够以高度的可信度对用户进行身份验证。
双因素身份验证比基于密码的身份验证强得多,因为在最坏的情况下,一次只有一个人可以使用加密令牌。密码可以被猜到并且可以暴露给其他用户,因此在最坏的情况下,当资源使用仅密码身份验证保护时,无数人可能会尝试获得未经授权的访问。
如果您将秘密私钥存储在文件中,则该密钥通常由密码加密。这种方法的问题是加密的密钥暴露在客户端机器上运行的解密攻击或间谍软件/恶意软件中。与使用加密设备时不同,文件在多次解密尝试失败后无法自动擦除。
该标准为保存密码信息和执行密码功能的设备指定了一个 API,称为 Cryptoki。Cryptoki,发音为“crypto-key”,是密码令牌接口的缩写,遵循简单的基于对象的方法,解决技术独立性(任何类型的设备)和资源共享(多个应用程序访问多个设备)的目标,向应用程序呈现设备的通用逻辑视图称为加密令牌。
资料来源:RSA Security Inc. https://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-11-cryptographic-token-interface-standard.htm。
总而言之,PKCS#11 是一个标准,应用软件可以使用它来访问智能卡和其他设备等加密令牌。大多数设备供应商都提供了一个实现 PKCS#11 提供程序接口的库——应用程序可以使用该库来访问这些设备。PKCS#11 是一个跨平台、独立于供应商的免费标准。
您需要做的第一件事是找到提供程序库,它应该与设备驱动程序一起安装。每个供应商都有自己的库。例如,OpenSC PKCS#11 提供程序在 Unix 上位于 /usr/lib/pkcs11/opensc-pkcs11.so 或在 Windows 上位于 opensc-pkcs11.dll。
您应该遵循注册程序:
配置的令牌是具有私钥对象和证书对象的令牌,两者共享相同的 id 和 label 属性。
一个简单的注册实用程序是 Easy-RSA 2.0,它是 OpenVPN 2.1 系列的一部分。按照 README 文件中指定的说明进行操作,然后使用 pkitool 进行注册。
使用以下命令初始化令牌:
$ ./pkitool --pkcs11-slots /usr/lib/pkcs11/
$ ./pkitool --pkcs11-init /usr/lib/pkcs11/
使用以下命令注册证书:
$ ./pkitool --pkcs11 /usr/lib/pkcs11/ client1
您应该拥有 OpenVPN 2.1 或更高版本才能使用 PKCS#11 功能。
确定正确的对象
每个 PKCS#11 提供程序都可以支持多个设备。为了查看可用对象列表,您可以使用以下命令:
$ open --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
每个证书/私钥对都有唯一的“序列化 id”字符串。请求证书的序列化 id 字符串应 使用单引号指定给pkcs11-id选项。
pkcs11-id 'aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600'
将 OpenVPN 与 PKCS#11 一起使用
PKCS#11 的一组典型 OpenVPN 选项
pkcs11-providers /usr/lib/pkcs11/
pkcs11-id 'aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600'
这将选择与 pkcs11-id 字符串匹配的对象。
PKCS#11 的高级 OpenVPN 选项
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
这会将两个提供商加载到 OpenVPN 中,使用 pkcs11-id 选项中指定的证书,并使用管理界面来查询密码。当无法访问令牌时,守护程序将恢复到事件的保持状态。令牌将使用 300 秒,之后将重新查询密码,如果管理会话断开,会话将断开。
PKCS#11 实施注意事项
许多 PKCS#11 提供程序使用线程,为了避免由 LinuxThreads (setuid, chroot) 的实现引起的问题,如果您打算使用 PKCS#11,强烈建议升级到支持 Native POSIX 线程库 (NPTL) 的 glibc .
OpenSC PKCS#11 提供程序
OpenSC PKCS#11 提供程序位于 Unix 上的 /usr/lib/pkcs11/opensc-pkcs11.so 或 Windows 上的 opensc-pkcs11.dll 中。
PKCS#11 是一个免费的、跨平台的供应商独立标准。CryptoAPI 是 Microsoft 特定的 API。大多数智能卡供应商都支持这两种接口。在 Windows 环境下,用户应该选择使用哪个界面。
只要您不将 OpenVPN 作为服务运行,当前使用 MS CryptoAPI(cryptoapicert选项)的 OpenVPN 实现就可以正常工作。如果您希望使用服务在管理环境中运行 OpenVPN,由于以下原因,该实施将不适用于大多数智能卡:
使用 PKCS#11 接口,您可以在任何实现中将智能卡与 OpenVPN 一起使用,因为 PKCS#11 不访问 Microsoft 商店,也不一定需要与最终用户直接交互。
默认情况下,当 OpenVPN 客户端处于活动状态时,只有进出 OpenVPN 服务器站点的网络流量会通过 VPN。例如,一般的网页浏览将通过绕过 VPN 的直接连接来完成。
在某些情况下,这种行为可能是不可取的——您可能希望 VPN 客户端通过 VPN 传输所有网络流量,包括一般的互联网网页浏览。虽然这种类型的 VPN 配置会对客户端造成性能损失,但当客户端同时连接到公共互联网和 VPN 时,它使 VPN 管理员可以更好地控制安全策略。
将以下指令添加到服务器配置文件:
push "redirect-gateway def1"
如果您的 VPN 设置是通过无线网络进行的,其中所有客户端和服务器都在同一个无线子网上,请添加 本地 标志:
push "redirect-gateway local def1"
将重定向网关选项推 送到客户端将导致源自客户端计算机的所有 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。
当使用 重定向网关时 ,OpenVPN 客户端将通过 VPN 路由 DNS 查询,而 VPN 服务器将需要处理它们。这可以通过将 DNS 服务器地址推送到连接的客户端来完成,这将在 VPN 处于活动状态时替换其正常的 DNS 服务器设置。例如:
push "dhcp-option DNS 10.8.0.1"
将配置 Windows 客户端(或具有一些额外服务器端脚本的非 Windows 客户端)使用 10.8.0.1 作为其 DNS 服务器。可以从客户端访问的任何地址都可以用作 DNS 服务器地址。
通过 VPN 重定向所有网络流量并非完全没有问题。以下是一些需要注意的典型问题:
有关 redirect-gateway 指令机制的更多信息,请参阅 手册页。
虽然 OpenVPN 客户端无需任何特殊配置即可通过动态 IP 地址轻松访问服务器,但当服务器本身位于动态地址上时,事情会变得更加有趣。虽然 OpenVPN 可以轻松处理动态服务器的情况,但需要一些额外的配置。
第一步是获取一个动态 DNS 地址,可以将其配置为在每次服务器的 IP 地址更改时“跟踪”服务器。有几个可用的动态 DNS 服务提供商,例如 dyndns.org。
下一步是建立一种机制,使每次服务器的 IP 地址发生变化时,动态 DNS 名称都会快速更新为新的 IP 地址,让客户端可以在新的 IP 地址上找到服务器。有两种基本方法可以做到这一点:
如果客户端配置使用引用动态 DNS 名称的远程指令, OpenVPN 客户端默认会感知服务器的 IP 地址何时更改 。通常的事件链是(a)OpenVPN客户端未能及时从服务器的旧IP地址接收keepalive消息,触发重新启动,以及(b)重新启动导致 远程 指令中的DNS名称被重新解析,允许客户端使用其新 IP 地址重新连接到服务器。
更多信息可以在 常见问题解答中找到。
OpenVPN 支持通过 HTTP 代理进行连接,具有以下身份验证模式:
首先,HTTP 代理的使用要求您使用 TCP 作为隧道载体协议。因此,将以下内容添加到客户端和服务器配置中:
proto tcp
确保删除配置文件中的任何 proto udp 行。
接下来,将 http-proxy 指令添加到客户端配置文件中(有关此指令的完整描述,请参见 手册页 )。
例如,假设您在客户端 LAN 上的 192.168.4.1上有一个 HTTP 代理服务器,它正在侦听端口 1080上的连接。将此添加到客户端配置中:
http-proxy 192.168.4.1 1080
假设 HTTP 代理需要基本身份验证:
http-proxy 192.168.4.1 1080 stdin basic
假设 HTTP 代理需要 NTLM 身份验证:
http-proxy 192.168.4.1 1080 stdin ntlm
上面的两个身份验证示例将导致 OpenVPN 从标准输入中提示输入用户名/密码。如果您想将这些凭据放在文件中,请将 stdin替换 为文件名,并将用户名放在该文件的第 1 行,将密码放在第 2 行。
此示例旨在展示 OpenVPN 客户端如何通过路由的 dev tun 隧道连接到 Samba 共享。如果您是以太网桥接 ( dev tap ),您可能不需要遵循这些说明,因为 OpenVPN 客户端应该在其网络附近看到服务器端机器。
对于此示例,我们将假设:
如果 Samba 和 OpenVPN 服务器在不同的机器上运行,请确保您已按照 扩展 VPN 的范围以包括其他机器的部分进行操作。
接下来,编辑您的 Samba 配置文件 ( smb.conf )。确保 hosts allow 指令将允许来自 10.8.0.0/24 子网的 OpenVPN 客户端进行连接。例如:
hosts allow = 10.66.0.0/24 10.8.0.0/24 127.0.0.1
如果您在同一台机器上运行 Samba 和 OpenVPN 服务器,您可能需要编辑 smb.conf文件中的interfaces 指令 以同时监听10.8.0.0/24 的 TUN 接口子网 :
interfaces = 10.66.0.0/24 10.8.0.0/24
如果您在同一台机器上运行 Samba 和 OpenVPN 服务器,请使用文件夹名称从 OpenVPN 客户端连接到 Samba 共享:
\\10.8.0.1\\sharename
如果 Samba 和 OpenVPN 服务器位于不同的机器上,请使用文件夹名称:
\\10.66.0.4\sharename
例如,从命令提示符窗口:
net use z: \\10.66.0.4\sharename /USER:myusername
OpenVPN 客户端配置可以参考多台服务器进行负载平衡和故障转移。例如:
remote server1.mydomain
remote server2.mydomain
remote server3.mydomain
将指示 OpenVPN 客户端按该顺序尝试与 server1、server2 和 server3 的连接。如果现有连接中断,OpenVPN 客户端将重试最近连接的服务器,如果失败,将转到列表中的下一个服务器。您还可以指示 OpenVPN 客户端在启动时随机化其服务器列表,以便客户端负载将概率性地分布在服务器池中。
remote-random
如果您还希望 DNS 解析失败导致 OpenVPN 客户端移动到列表中的下一个服务器,请添加以下内容:
resolv-retry 60
60 参数告诉 OpenVPN 客户端尝试解析每个 远程DNS 名称 60 秒,然后 再转到列表中的下一个服务器。
服务器列表还可以引用在同一台机器上运行的多个 OpenVPN 服务器守护进程,每个守护进程侦听不同端口上的连接,例如:
remote smp-server1.mydomain 8000
remote smp-server1.mydomain 8001
remote smp-server2.mydomain 8000
remote smp-server2.mydomain 8001
如果您的服务器是多处理器机器,从性能的角度来看,在每台服务器上运行多个 OpenVPN 守护程序可能是有利的。
OpenVPN 还支持 引用 DNS 名称 的远程指令,该名称在域的区域配置中具有多个A 记录。 在这种情况下,每次解析域时,OpenVPN 客户端都会随机选择一条 A记录。
在服务器上进行负载平衡/故障转移配置的最简单方法是在集群中的每台服务器上使用等效的配置文件,除了为每台服务器使用不同的虚拟 IP 地址池。例如:
服务器1
server 10.8.0.0 255.255.255.0
服务器2
server 10.8.1.0 255.255.255.0
服务器3
server 10.8.2.0 255.255.255.0
经常重复的网络安全准则之一是,人们永远不应过于信任单个安全组件,以至于其故障会导致灾难性的安全漏洞。OpenVPN 提供了几种机制来添加额外的安全层来对冲这种结果。
tls-auth 指令为所有 SSL/TLS 握手数据包添加额外的 HMAC 签名以进行完整性验证。 任何不带有正确 HMAC 签名的 UDP 数据包都可以被丢弃而无需进一步处理。tls-auth HMAC 签名提供了比 SSL/TLS 提供的安全级别更高的安全级别。它可以防止:
使用 tls-auth 需要您生成一个共享密钥,除了标准 RSA 证书/密钥之外还要使用该密钥:
open --genkey --secret ta.key
此命令将生成一个 OpenVPN 静态密钥并将其写入文件 ta.key。此密钥应通过预先存在的安全通道复制到服务器和所有客户端计算机。它可以与 RSA .key 和 .crt 文件放在同一目录中。
在服务器配置中,添加:
tls-auth ta.key 0
在客户端配置中,添加:
tls-auth ta.key 1
虽然 OpenVPN 允许将 TCP 或 UDP 协议用作 VPN 运营商连接,但 UDP 协议将提供比 TCP 更好的针对 DoS 攻击和端口扫描的保护:
proto udp
OpenVPN 经过精心设计,允许在初始化后删除 root 权限,并且此功能应始终在 Linux/BSD/Solaris 上使用。如果没有 root 权限,正在运行的 OpenVPN 服务器守护程序对攻击者的吸引力要小得多。
user nobody
group nobody
在 Linux 上,OpenVPN 可以完全无特权运行。这种配置稍微复杂一些,但提供了最好的安全性。
为了使用此配置,必须将 OpenVPN 配置为使用 iproute 接口,这是通过指定 --enable-iproute2 来配置脚本来完成的。sudo 包也应该在您的系统上可用。
此配置使用 Linux 功能更改 tun 设备的权限,以便非特权用户可以访问它。它还使用 sudo 来执行 iproute,以便可以修改接口属性和路由表。
OpenVPN 配置:
#!/bin/sh
sudo /sbin/ip $*
user1 ALL=(ALL) NOPASSWD: /sbin/ip
%users ALL=(ALL) NOPASSWD: /sbin/ip
dev tunX/tapX
iproute /usr/local/sbin/unpriv-ip
open --mktun --dev tunX --type tun --user user1 --group users
通过检查 /usr/local/sbin/unpriv-ip 脚本中的参数,可以添加进一步的安全约束。
chroot指令允许您将 OpenVPN 守护程序锁定到所谓的 chroot jail中,该守护程序将无法访问主机系统文件系统的任何部分,除了作为指令参数给出的特定目录。例如,
chroot jail
将导致 OpenVPN 守护程序在初始化时 cd 进入 jail 子目录,然后将其根文件系统重新定向到该目录,以便守护程序此后无法访问 jail 及其子目录树之外的任何文件。从安全的角度来看,这很重要,因为即使攻击者能够通过代码插入漏洞破坏服务器,该漏洞也会被锁定在服务器的大部分文件系统之外。
注意事项:因为 chroot 重新定向文件系统(仅从守护进程的角度来看),所以有必要将 OpenVPN 在初始化后可能需要的任何文件放在 jail 目录中,例如:
RSA 密钥大小由 easy-rsa/vars文件中的KEY_SIZE 变量 控制 ,必须在生成任何密钥之前设置该变量。目前默认设置为 1024,这个值可以合理地增加到 2048,而不会对 VPN 隧道性能产生负面影响,除了 SSL/TLS 重新协商握手稍慢,每个客户端每小时发生一次,以及更慢的一次性 Diffie Hellman 参数生成过程使用 easy-rsa/build-dh 脚本。
默认情况下,OpenVPN 使用 Blowfish,一种 128 位对称密码。
OpenVPN 自动支持 OpenSSL 库支持的任何密码,因此可以支持使用大密钥大小的密码。例如,可以通过将以下内容添加到服务器和客户端配置文件来使用 256 位版本的 AES(高级加密标准):
cipher AES-256-CBC
使用 X509 PKI(与 OpenVPN 一样)的安全优势之一是根 CA 密钥(ca.key)不需要出现在 OpenVPN 服务器机器上。在高安全性环境中,您可能希望专门指定一台机器用于密钥签名,保持机器良好的物理保护,并断开它与所有网络的连接。必要时可以使用软盘来回移动密钥文件。这些措施使得攻击者很难窃取根密钥,除非是物理盗窃密钥签名机。
撤销证书 意味着使以前签署的证书无效,使其不能再用于身份验证目的。
想要撤销证书的典型原因包括:
例如,我们将吊销 client2 证书,该证书是我们在上面 HOWTO 的“密钥生成”部分生成的。
首先打开一个 shell 或命令提示符窗口,然后 cd 到 easy-rsa 目录,就像您在上面的“密钥生成”部分中所做的那样。在 Linux/BSD/Unix 上:
. ./vars
./revoke-full client2
在 Windows 上:
vars
revoke-full client2
您应该会看到与此类似的输出:
Using configuration from /root/open/20/open/tmp/easy-rsa/openssl.cnf
DEBUG[load_index]: unique_subject = "yes"
Revoking Certificate 04.
Data Base Updated
Using configuration from /root/open/20/open/tmp/easy-rsa/openssl.cnf
DEBUG[load_index]: unique_subject = "yes"
client2.crt: /C=KG/ST=NA/O=OpenVPN-TEST/CN=client2/[email protected]
error 23 at 0 depth lookup:certificate revoked
请注意最后一行中的“错误 23”。这就是您希望看到的,因为它表明已撤销证书的证书验证失败。
revoke-full脚本将 在 keys子目录中生成一个名为crl.pem 的 CRL(证书撤销列表)文件 。该文件应复制到 OpenVPN 服务器可以访问的目录,然后应在服务器配置中启用 CRL 验证:
crl-verify crl.pem
现在,所有连接的客户端都将根据 CRL 验证其客户端证书,并且任何正匹配都将导致连接被丢弃。
为了避免可能的中间人攻击,授权客户端尝试通过模拟服务器连接到另一个客户端,请确保客户端强制执行某种服务器证书验证。目前有五种不同的方式来实现这一点,按优先顺序列出:
模式 | 密钥用法 | 扩展密钥使用 |
---|---|---|
Client | digitalSignature 电子签名 | TLS Web 客户端身份验证 |
keyAgreement 关键协议 | ||
digitalSignature, keyAgreement 数字签名,密钥协议 | ||
Server | digitalSignature, keyEncipherment 数字签名,密钥加密 | TLS Web 服务器身份验证 |
digitalSignature, keyAgreement 数字签名,密钥协议 |
您可以使用 build-key-server 脚本构建您的服务器证书(有关详细信息,请参阅 easy-rsa文档)。这将通过设置正确的属性将证书指定为仅服务器证书。现在将以下行添加到您的客户端配置中:
remote-cert-tls server
ns-cert-type server
这将阻止客户端连接到其证书中缺少 nsCertType =server 指定的任何服务器,即使该证书已由 OpenVPN 配置文件中的ca文件签名。