从概念上说,openvpn类似于一根网线,或者一台交换机。你拨上vpn,差不多相当于给自己的机器装一个虚拟的网卡,从上面拉一根线到服务器的虚拟网卡上。所以,vpn的配置大概和网络配置差不多,分为几个大类。

一类是第二层交换,即虚拟网卡和真实网卡组成网桥。这样可以把虚拟网络上的设备引入真实网络,让虚拟网卡获得真实网络的地址,或者反之。坏处是配置复杂,稳定性差。

例如你家里是192.168.0.0/24网络段,你决定用tap配置一个网桥,就需要新建一个br0设备,将eth0和tap0设备加入网桥。这样,一台IP为192.168.0.10的家庭机器,在访问IP为192.168.0.110的远程机器的时候,所发出的ARP请求会被转发到远端,然后ARP响应转发到本地。通过这种方式,10就会直接把MAC报文发送到中转机上,然后再转发远端。可以看出,由于ARP请求往来非常费时,在子网内机器多的时候,会消耗不少时间和带宽进行ARP转包,以及各种链路级开销。所以通常除了两个安全封闭子网因为管理理由必须这么玩,并且两者间又都有服务器和高速链接的时候,其他时候我不推荐这种玩法。

更何况,在debian系统下配置网桥需要额外脚本,不如路由那样,可以使用默认脚本启动,然后动态修改路由表。

大部分是三层交换,即将服务器作为路由器使用。这又分为两种情况,网络地址转换,和网关互通。

网络地址转换是最常见的情况,这个又叫做NAT。网关在转发你的包的同时,会将地址转换成自己的地址。从而避免修改路由的行为。

同样是192.168.0.0/24举例,远程网络假如叫做192.168.1.0/24。当你拨号上远程网络时,你就拥有了一个远程IP和一个本地IP。你可以配置路由表,让哪些IP从远程走(这就是地址段选择翻墙的原理)。大多数情况下,会被配置为默认都从远程IP走,除了几个特定地址(例如VPN服务器地址,这个也走虚拟网络会引起循环的)。而远程的网关,假定是192.168.1.1,开启了NAT。这时候你的所有网络流量就都从远程的VPN服务器上发出和接收了,如同你正坐在远程服务器后面的小网络内一样。

网关互通是更复杂的一类情况,通常是小型企业为了多个连通多个地点办公子网而设计的。理论上说大型企业也适用,但是大型企业有钱,IT部为了防范责任问题,通常会直接采购Cisco之类大公司的产品直接使用。基本概念是将虚拟网络和真实网络配置成两个子网,两个子网可以互相访问。

还是192.168.0.0的例子,我们假定另外有一个子网叫做192.168.1.0/24。现在我们需要连通两个子网,或者,更进一步,多个子网。

我们首先配置一个虚拟子网叫做192.168.254.0,然后架设一台共用服务器。这是比较简单的模型。更复杂的可以将其中一个子网的某个服务器映射出去作为核心,配置就更加复杂,不过可以依照同样原理推导。架设好共用服务器后,我们需要在每个子网的网关上下手,否则就无法做到透明路由。修改这个网关的路由表,将192.168.0.0/16全部转发到虚拟网关(即共用服务器的虚拟IP)上去(当然,除去本网段不转发)。在OpenVPN上面可以配置,当某条链路拨接上来后,就在服务器上加入一条路由,将其后面的网段加入网关路由表。于是,当192.168.0.100的某台服务器希望直接访问192.168.1.100。首先这台主机会检查自己的路由表,发现这个需要由网关192.168.0.1转发,就先转到了192.168.0.1。192.168.0.1检查路由表,发现192.168.1.100需要被转发到虚拟网关,即192.168.254.1。于是通过虚拟网络,该网关做出转发。当192.168.254.1接收到后,他会依照上面的路由表,检查到这条链路是否已经拨接上来,拨接上的话对应的虚拟IP是多少,然后转发过去。最后是目标网关,192.168.1.1,转发给192.168.1.100的过程。整个过程复杂无比,不过实现起来都是自动化的。

在配置文件中,有ca certkey三项,这三项分别对应不同作用。cert和key是用于向客户端验证服务器身份的。客户端那里有一个ca.crt,服务器这里的cert和key必须是那个ca.crt签署过的。这样,客户端就可以验证服务器是否是可信任的。而服务器这里的ca则是验证客户端身份的,客户端那里同样也有cert和key,必须由服务器端的ca.crt签署过。通常,我们用同一套ca.key签署两个cert,分别部署在服务器端和客户端,就可以工作了。

另外一点需要注意的是,ns-cert-typeserver这个参数。在debian的默认系统中有这个参数,一旦指定,openvpn就会检验服务器证书上是否有server的选项。对于easy-rsa签署的证书,这个肯定是有的。但是如果自己用openssl签署,就要记得做ext,否则检验不通过会报错。