红联Linux门户
Linux帮助

CentOS6.3下OpenVPN的搭建及相关配置详解

发布时间:2015-03-29 10:56:49来源:linux网站作者:tanxw

一、搭建背景

由于公司做的业务比较多,因为分为网络公司和其他业务的公司,也就是几家公司分开,不在同一个地方,然后网络公司的一些数据需要给其他业务的公司访问,也就是共享资料也去让大家都可以访问,网络公司的很多共享数据都是放到Linux测试机上,因此就有使用VPN的需求。


二、OpenVPN原理与实战汇总

概述:

1.OpenVPN 开源软件,首先要感谢OpenVPN团队。

2.在网上找了些关于OpenVPN文章发现在大部分都在讲配置,很少有人写原理的。

3.大家可以在网上找一下OpenVPN的相关原理


三、OpenVPN原理及实现--一般理论

OpenVPN基于OpenSSL来实现安全,但是却不是传统意义上的sslvpn,它只是一个普通的vpn,工作在ip层而不是传输层。vpn的含义着重点有两层意思,一个是v,也就是虚拟,另一个是p,也就是专用。

虚拟就是说不用物理布线,仅仅在逻辑上实现一个网络,虚拟网络之所以能实现并建立起来,靠的是分层模型的优势,分层模型直接将网络按照逻辑意义纵向分成了7个层次(或者tcp/ip的5个层次),每一层都仅仅承载数据而不管数据的格式和内容,上下层次间仅仅通过接口和服务来通信,理论上任何层次的数据都可以被承载在其它的任何层次或者它当前的层次上,于是就出现了很多XX over YY的网络模型,比较典型的比如ppp over ethernet等。

over模型按照数据层次可以分为三类:

第一类是上层数据承载于下层,这实际上就是我们使用的普通的tcp/ip模型;

第二类是同层承载,比如上面说的pppoe,这一类构建方式主要是为了在一个以传输占主导的层次上增加一个非传输意义的逻辑或者说实现一个隧道,比如pppoe中,ethernet主要用于局域网传输,而且性价比十分合理,但是却缺乏认证机制,但是ppp协议的认证功能虽然很好,但是却缺乏多点通信和寻址能力,作为传输协议意义不大,于是就使用ethernet进行传输,使用ppp进行认证,另外一个同层承载的例子是IPSec的隧道模式,它将一个ip数据报封装于另一个ip数据报中,这样实际上也就实现了一般意义上的“虚拟局域网络”(注意不是vlan),因为在数据报到达最终目的地之前,参与路由的始终是外层的ip头,内层的ip头连同真实数据都被外层ip当成了data,因此不参与路由,所以从隧道的出发路由器到结束路由器,不管中间经过的是局域网,广域网还是别的什么,内层的ip数据报一直“以为”自己在出发路由器的那个局域网内,因此就实现了一个虚拟网络,实现了vpn中的v,那么p呢,IPSec将v和p做到了一起,也就是说在实现ip over ip的过程中实现了安全,这就是熟知的ah协议和esp协议,实现了安全才能保证专用,否则别人都可以进入你的虚拟网络了,作为vpn来说,IPsec就到此为止,但是IPSec的用处不光如此,IPSec主要是保证ip数据报的安全(因为ip层不提供任何安全保护,ipv6就不一样了,完全不需要IPSec),vpn只是它的隧道模式的一个应用,除了隧道模式,IPSec还有传输模式,不建立隧道,只是将认证或者加密的功能置于ip数据报中,当然也就是不需要ip over ip了。

众所周知IPSec的隧道模式实现的vpn有一个缺陷,那就是很难穿越nat,因为nat要修改ip头,一旦ip头被修改了,那么最终的ah或者esp的认证加密的校验结果就会出错,因此就不能随意在nat的网络环境中使用IPSec实现的vpn,当然不涉及ip头认证的IPSec协议还是可以用的。难道vpn就IPSec这一根稻草了吗?认证和加密的逻辑十分复杂和多样,不适合在ip层做,ip层做好快速路由和连接不同子网就够了,如果将分层模型的每个层次仅仅当作一种交通工具来看待的话,问题就容易解决了,交通工具或者叫运输工具可以相互运输,大卡车可以运小卡车,也可以拆了被小卡车运,大卡车还可以运输别的大卡车,它们都可以被放入集装箱被轮船运输,分层模型就是这样的,我们可以让应用层或者表示层或者传输层来承载ip数据报,这也就是over模型的第三类,即上层承载下层,很多时候越往上层逻辑越复杂,实现越灵活,如果想要在低层次实现高度复杂的逻辑,不妨试试这种模型,这个意义上看,IPSec实现的vpn最后肯定不如ip over ssl好,因为扩充IPSec很难,毕竟它在协议栈中的位置不适合做大幅修改,但是ssl的扩展性却很好,它本身就在协议栈的顶端,即使影响也就影响应用层,比如迫使http转换到https。

如果说低层就不该有复杂多样且多变的逻辑这种设计思想是对的,那么IPsec就不该出现,IPv6除了扩充地址空间外,新增的功能净加重了ip层的负担,IPv6的复杂设计净是商业公司为了推自己的接口或者设备而使出的伎俩,不过也说不准,留给历史评述吧。

vpn不一定要实现隧道,只要能互相访问并且保证互访者独占性的网络理论上都是vpn,然而隧道的方式更具有代表性,各种实现也更丰富和花哨。


四、vpn原理及实现--隧道的一种实现

理论上已经合理的ip over ssl还需要一些额外的技术支撑才能使用,必须想办法将一个ip数据报原封不动的让它被ssl重新封装一次,这个动作不可能在原始的标准协议栈中执行,标准协议栈不支持数据双向流动,那么解决方案之一就是修改协议栈,在ip层之下实现一个轻量的ssl协议层,但是如此一来就又回到了IPSec的老路上,因此此法不可取,正确的方法是不修改协议栈,让一切留在它应该在的地方,于是ssl必然得在应用层或者说是表示层实现,现在的问题是如何将下层的ip数据报重新引入上面的应用层,而且还不能修改标准协议栈,于是必然地要让ip数据报继续往下走,然后最终从一个网卡流出,于是就出了协议栈,接下来就可以自由发挥了,让数据流出网卡的原因是不能修改协议栈,但是还不能真的让它流出机器,如果它走了就不能指望用ssl封装它了,那么流到哪里呢?

回环设备是一个不错的选择,从回环设备流出的数据实际上又流进了回环设备,用户空间只需要打开回环设备然后读取就可以了,注意不能通过一般套接字读取,毕竟那些数据不是发给我们的,要使用类似抓包的方式进行数据抓取,并且用防火墙禁止被抓取的数据继续被forward,这实际上是一种巧妙的拦截方式,被抓取得数据然后经过ssl封装后再发向一个真的ip地址,我们需要配置的就是将所有的vpn数据全部发往回环设备,其实就是添加一条路由,虚拟网络已经建立,事情到此为止看似要结束了。

但是且慢,问题来了,以后所有vpn数据都会经标准协议栈流出再流进loopback,然后作为裸数据进入应用层,接着整个原始vpn数据连同它的原始ip头封装作为应用数据接受ssl协议的封装,然后发往vpn的另一端,在另一端数据从真实网卡进入,然后由于这是隧道的终点,数据直接进入应用层,在应用层,vpn服务器等候在那里,得到原始的vpn裸数据还有它在发送端的ip头,服务端得到这个东西有什么用呢,接下来它要怎么做呢,它只是隧道的终点,并不是真的要接收数据的机器,因此它必须将数据重新发到真正需要它的机器,很显然它要作为一个应用层代理存在,剥去原始的ip头,得到原始的数据,然后将数据发给真实的目的地,且不说此法是否可能,有两点不合理之处足以否定它,由于vpn服务器实现了代理,那么数据必然要在该处集中并剥去ip头,并且在相反的方向要做同样的处理,那么它就要记住所有的ip头,否则数据就会有去无回,如此一来,vpn服务器的负载可堪忍受?性能呢?

第二点,代理的方式消除了隧道的透明性,目的地受到数据后会不知道数据从何而来,统一认为是vpn服务器发来的,这样就无法根据数据源点进行策略化服务。综上原因,loopback设备可用但不可行,因为它是本机闭合的,也就是说只有loopback出去的数据才能进入loopback,它又且仅有两个出口,一读一写都在应用层,你无法将数据作为物理层的流写入loopback,而只能作为应用层的数据通过协议栈逐级封装到达loopback,然后再逐级解封回来,vpn发送端面临同样的问题,因为仅仅是路由将数据出口指向了loopback, 如果不用抓包的方式(pcap)的话是得不到数据的,而这种方式又十分影响性能,加之还要配置复杂的防火墙规则禁止进入loopback的数据被转发,性能又受影响,隧道两端由于是全双工通信,因此一端面临的问题在数据反向时在对端同样存在,抛开这些不谈,仅就loopback无法自由配置ip地址这一条,它就不能被选中来实现隧道,vpn网络需要被管理,有时管理本身就很复杂,虚拟网络不仅仅就一张,我们需要为每张虚拟网络准备一个子网,也就是每个虚拟网络要有不同的ip,所以必然需要灵活的ip配置,故而loopback不能实现优雅透明的隧道,既然如此我们回到原点,无非就是做到两点:

第一,数据必须按照协议栈的标准逐级封装和解封装,不能修改协议栈;

第二就是数据到了最下面物理层的时候不能真的走掉,而是回到用户空间,于是乎虚拟网卡就成了很好的选择。

以上的都是OpenVPN的一些理论知识,这些也都是从网上搜集大牛们的blog来的。


五、OpenVPN在CentOS 6.3下搭建步骤

1、多的不说,上来直接yum安装,安装这个还不够,因为我们这里安装的是2.3.2,所以还要安装easy-rsa这个包:  

[root@backup yunwei]# yum install -y openvpn easy-rsa

2、复制相关的配置文件到/etc/openvpn目录下

[root@backup yunwei]# rpm -ql openvpn  //查看openvpn的各文件安装路径

[root@backup yunwei]# cp -r /usr/share/doc/openvpn-2.3.2/sample/sample-config-files/server.conf /etc/openvpn/

[root@backup yunwei]# cp -r /usr/share/easy-rsa/2.0/ /etc/openvpn/

3、生成证书,修改/etc/openvpn/2.0/目录下的vars文件

[root@backup 2.0]# vim vars

export KEY_COUNTRY="CN"                # 国家

export KEY_PROVINCE="BJ"          # 省份

export KEY_CITY="BJ"              # 城市

export KEY_ORG="openvpn"          # 组织

export KEY_EMAIL="admin@test.com"  # 邮件

export KEY_OU="MyOrganizationalUnit"  # 单位

修改好之后保存退出:

[root@backup 2.0]# env | grep KEY

[root@backup 2.0]# source ./vars    #让 vars 文件生效(还可以用点执行生效.  vars)

NOTE: If you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/2.0/keys

[root@backup 2.0]# env | grep KEY

KEY_EXPIRE=3650

KEY_EMAIL=admin@test.com

KEY_OU=MyOrganizationalUnit

KEY_SIZE=2048

KEY_DIR=/etc/openvpn/2.0/keys

KEY_NAME=EasyRSA

KEY_CITY=BJ

KEY_PROVINCE=BJ

KEY_ORG=openvpn

KEY_CONFIG=/etc/openvpn/2.0/openssl-1.0.0.cnf

KEY_COUNTRY=CN

[root@backup 2.0]# ./clean-all  #清除所有证书

[root@backup 2.0]# ls

build-ca  build-inter  build-key-pass    build-key-server  build-req-pass  inherit-inter  list-crl          openssl-0.9.8.cnf  pkitool      sign-req  whichopensslcnf

build-dh  build-key    build-key-pkcs12  build-req        clean-all      keys          openssl-0.9.6.cnf  openssl-1.0.0.cnf  revoke-full  vars

[root@backup 2.0]#

第一次安装 openvpn 服务必须执行./ clean-all,执行后会多出一个 keys 目录,keys 目录

中是存放所有证书。注意:生产环境 pvn 服务器上线很久了,如果再需要添加新客户端

证书,不需要执行./ clean-all,只需要执行 build-key-pass 或者 build-key。

4、创建CA证书:

[root@backup 2.0]# ./build-ca

Generating a 2048 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) [CN]: 按回车

State or Province Name (full name) [BJ]: 按回车

Locality Name (eg, city) [BJ]: 按回车

Organization Name (eg, company) [openvpn]: 按回车

Organizational Unit Name (eg, section) [3drich]: 按回车

Common Name (eg, your name or your server's hostname) [openvpn CA]: 按回车

Name [EasyRSA]: 按回车

Email Address [admin@test.com]: 按回车

[root@backup 2.0]#

5、创建服务端证书和密钥 key 文件

[root@backup 2.0]# ./build-key-server server

Generating a 2048 bit RSA private key

........................................................................

...............................+++

...............................................+++

writing new private key to 'server.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) [CN]: 回车

State or Province Name (full name) [BJ]: 回车

Locality Name (eg, city) [BJ]: 回车

Organization Name (eg, company) [openvpn]: 回车

Organizational Unit Name (eg, section) [3drich]: 回车

Common Name (eg, your name or your server's hostname) [server]: 回车

Name [EasyRSA]: 回车

Email Address [admin@test.com]: 回车

Please enter the following 'extra' attributes

to be sent with your certificate request

A challenge password []: 指服务端与客户端发送密钥交换认证,可以不填。

An optional company name []: 公司名称,可以不填。

Using configuration from /etc/openvpn/2.0/openssl-1.0.0.cnf

Check that the request matches the signature

Signature ok

The Subject's Distinguished Name is as follows

countryName          :PRINTABLE:'CN'

stateOrProvinceName  :PRINTABLE:'BJ'

localityName          :PRINTABLE:'BJ'

organizationName      :PRINTABLE:'openvpn'

organizationalUnitName:PRINTABLE:'3drich'

commonName            :PRINTABLE:'server'

name                  :PRINTABLE:'EasyRSA'

emailAddress          :IA5STRING:'admin@test.com'

Certificate is to be certified until Sep 12 01:19:20 2024 GMT (3650 days)

Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y

Write out database with 1 new entries

Data Base Updated

[root@backup 2.0]#

6、创建客户端证书和 key 文件(这里设置一个客户端分别为:yunwei,你可以根据需要生成多个客户端)  

[root@backup 2.0]# ./build-key yunwei

Generating a 2048 bit RSA private key

................................+++

...........................................+++

writing new private key to 'client1.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) [CN]:

State or Province Name (full name) [BJ]:

Locality Name (eg, city) [BJ]:

Organization Name (eg, company) [openvpn]:

Organizational Unit Name (eg, section) [3drich]:

Common Name (eg, your name or your server's hostname) [client1]:

Name [EasyRSA]:

Email Address [admin@test.com]:

Please enter the following 'extra' attributes

to be sent with your certificate request

A challenge password []:

An optional company name []:

Using configuration from /etc/openvpn/2.0/openssl-1.0.0.cnf

Check that the request matches the signature

Signature ok

The Subject's Distinguished Name is as follows

countryName          :PRINTABLE:'CN'

stateOrProvinceName  :PRINTABLE:'BJ'

localityName          :PRINTABLE:'BJ'

organizationName      :PRINTABLE:'openvpn'

organizationalUnitName:PRINTABLE:'3drich'

commonName            :PRINTABLE:'yunwei'

name                  :PRINTABLE:'EasyRSA'

emailAddress          :IA5STRING:'admin@test.com'

Certificate is to be certified until Sep 12 01:25:38 2024 GMT (3650 days)

Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y

Write out database with 1 new entries

Data Base Updated

根据自己的需求还可以创建第二第三第四.....个客户端。

7、创建密钥交换协议文件(Diffie Hellman)

[root@backup 2.0]# ./build-dh

Generating DH parameters, 2048 bit long safe prime, generator 2

This is going to take a long time

.....................................+...+........+............................................++*++*

root@backup 2.0] #


8、配置服务端 VPN 配置文件 server.conf。在 openvpn-2.3.2 目录中把 server.conf 和 client.conf 配置文件拷贝到/etc/openvpn/目录下

[root@backup 2.0]# cp /usr/share/doc/openvpn-2.3.2/sample/sample-config-files/client.conf /etc/openvpn/

9、备份 server.conf、client.conf 这 2 个文件

[root@backup openvpn]# cp server.conf{,.bak}

[root@backup openvpn]# cp client.conf{,.bak}

[root@backup openvpn]# ls

2.0  client.conf  client.conf.bak  server.conf  server.conf.bak

10、创建客户 VPN 日志文件

[root@backup openvpn]# mkdir /var/log/openvpn

[root@backup openvpn]# touch openvpn-status.log

[root@backup openvpn]# touch openvpn.log

[root@backup openvpn]# ls

openvpn.log  openvpn-status.log

11、配置 VPN 服务端 server.conf

[root@backup openvpn]# pwd

/etc/openvpn

[root@backup openvpn]# cat server.conf | grep "^[^#|^;]"

local 10.17.1.20    #监听地址

port 1194      #监听端口

proto tcp      #监听协议

dev tun      #采用路由隧道模式

ca /etc/openvpn/2.0/keys/ca.crt  #ca证书路径

cert /etc/openvpn/2.0/keys/server.crt    #服务器证书

key /etc/openvpn/2.0/keys/server.key    # This file should be kept secret 服务器密钥

dh /etc/openvpn/2.0/keys/dh2048.pem  #密钥交换协议文件

server 10.8.0.0 255.255.255.0        #给客户端分配地址池,注意:不能和VPN服务器内网网段有相同

ifconfig-pool-persist ipp.txt        

push "route 192.168.20.0 255.255.255.0"  #允许客户端访问内网 20.0 的网段。

client-to-client    #客户端之间互相通信

keepalive 10 120  #存活时间,10秒ping一次,120 如未收到响应则视为断线

comp-lzo        #传输数据压缩

max-clients 100  #最多允许 100 客户端连接

user nobody        #用户

group nobody      #用户组

persist-key

persist-tun

status        /var/log/openvpn/openvpn-status.log

log        /var/log/openvpn/openvpn.log

verb 3

到这里应该算是把服务器上的OpenVPN配置好了,这个的话我们就要把刚才生成的客户端key和ca拉到我们的电脑上去
CentOS6.3下OpenVPN的搭建及相关配置详解

12、在要需要连vpn的电脑上安装windows下的openvpn软件,这里就不再多说了,windows下安装软件应该不在话下了。
CentOS6.3下OpenVPN的搭建及相关配置详解

装好之后再找到vpn的安装路径,找到config这个文件,如果里面没有以下文件就自己手动创建
CentOS6.3下OpenVPN的搭建及相关配置详解

把刚才从服务器上拉下来的那三个文件放到openvpn这个文件夹里去,然后再使用txt编辑openvpn.ovpn这个文件,把下面内容贴进去,保存。
CentOS6.3下OpenVPN的搭建及相关配置详解

这里要注意:remote这个地址是你公司的外网地址,同时还要在你们公司的路由器上做1194的端口映射,因为openvpn服务器是在公司的测试机上,而公司的测试机使用的都是内网ip地址的,所以需要做外网到内网的ipt和端口的映射,很简单,有网管的话叫网管设置一下就可以了。

客户端改好之后就基本上差不多了,接下来我们先启动服务器上的openvpn服务,然后我们再连接一下就可以了。
CentOS6.3下OpenVPN的搭建及相关配置详解

接上之后图标会变成绿色:
CentOS6.3下OpenVPN的搭建及相关配置详解

注:以上图片上传到红联Linux系统教程频道中。

OK,现在已经连接上去了,但是我们还需要配置iptables,如果不配置iptables的话连接上vpn之后你就上不了网了,只能使用vpn,所以要配置一下iptables:

开启内核转发转发功能,将 net.ipv4.ip_forward = 0  改成 1

[root@backup1 openvpn]# vim /etc/sysctl.conf

[root@backup openvpn]# sysctl -p  #让它生效

net.ipv4.ip_forward = 1

net.ipv4.conf.default.rp_filter = 1

net.ipv4.conf.default.accept_source_route = 0

kernel.sysrq = 0

kernel.core_uses_pid = 1

net.ipv4.tcp_syncookies = 1

error: "net.bridge.bridge-nf-call-ip6tables" is an unknown key

error: "net.bridge.bridge-nf-call-iptables" is an unknown key

error: "net.bridge.bridge-nf-call-arptables" is an unknown key

kernel.msgmnb = 65536

kernel.msgmax = 65536

kernel.shmmax = 68719476736

kernel.shmall = 4294967296

-----------------  iptables for openvpn配置过程  -----------------------

配置默认过滤策略。这里一定要在打开22口后配置,否则配完后直接就断了。。。。

接下来允许openvpn的端口连接

# iptables -A INPUT -p udp --dport 1194 -j ACCEPT

这里777是我设置的openvpn的连接端口,各位同学根据自己的情况修改。

配置完成后,最后一步就是配置openvpn的nat功能了。

# iptables -t nat -A POSTROUTING -s 10.78.0.0/24 -o em1 -j MASQUERADE  ——将所有10.78.0.0网段的包转发到em1口,看准自己服务器上的是什么端口,我这里的是em1

配置完成,但是试了很久都连不上……经过仔细检查和百度,发现还有很多细节上的步骤……

1:开启系统的路由功能

echo "1" > /proc/sys/net/ipv4/ip_forward

2:添加FORWARD白名单

iptables -A FORWARD -i tun+ -j ACCEPT

3:允许虚拟网段的所有连接

iptables -A INPUT -s 10.78.0.0/24 -j ACCEPT

4:保持已经建立的连接(否则服务器无法上网)

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

好了,这样配置好ipables规则之后就可以连接上了,这样的话如在外地使用vpn连接之后就可以随意使用公司里配置内网ip的服务器了,可以连接你服务器上的共享文件的服务器,ftp,samba什么的都可以使用内网ip连接了。