当前位置: > CentOS > CentOS教程 >

Openvpn在Centos服务器上的完美实现

时间:2014-05-04 23:49来源:linux.it.net.cn 作者:it

Openvpn在linux上的完美实现

一,OpenVPN的工作原理

 

VPN技术通过密钥交换、封装、认证、加密手段在公共网络上建立起私密的隧道,保障传输数据的完整性、私密性和有效性。OpenVPN是近年来新出现的开放源码项目,实现了SSLVPN的一种解决方案。

传统SSL VPN通过端口代理的方法实现,代理服务器根据应用协议的类型(如httptelnet等)做相应的端口代理,客户端与代理服务器之间建立SSL安全连接,客户端与应用服务器之间的所有数据传输通过代理服务器转发。这种实现方式烦琐,应用范围也比较窄:仅适用于用TCP固定端口进行通信的应用系统,且对每个需要代理的端口进行单独配置;对于每个需要用到动态端口的协议都必须重新开发,且在代理中解析应用协议才能实现代理,如FTP协议;不能对TCP以外的其它网络通信协议进行代理;代理服务器前端的防火墙也要根据代理端口的配置变化进行相应调整。

OpenVPN以一种全新的方式实现了SSLVPN的功能,克服了传统SSLVPN的一些缺陷,扩展了应用领域,并且防火墙上只需开放TCPUDP协议的一个端口。

1,虚拟网卡

Linux2.4版本以上,操作系统支持一个名为tun的设备,tun设备的驱动程序中包含两个部分,一部分是字符设备驱动,一部分是网卡驱动。网卡的驱动把从TCP/IP协议栈收到的数据包结构skb放于tun设备的读取队列,用户进程通过调用字符设备接口read获得完整的IP数据包,字符驱动read函数的功能是从设备的读取队列读取数据,将核心态的skb传递给用户;反过来字符驱动write函数给用户提供了把用户态的数据写入核心态的接口,write函数把用户数据写入核心空间并穿入TCP/IP协议栈。该设备既能以字符设备的方式被读写,作为系统的虚拟网卡,也具有和物理网卡相同的特点:能够配置IP地址和路由。对虚拟网卡的使用是OpenVPN实现其SSLVPN功能的关键。

2,地址池以及路由

OpenVPN服务器一般需要配置一个虚拟IP地址池和一个自用的静态虚拟IP地址(静态地址和地址池必须在同一个子网中),然后为每一个成功建立SSL连接的客户端动态分配一个虚拟IP地址池中未分配的地址。这样,物理网络中的客户端和OpenVPN服务器就连接成一个虚拟网络上的星型结构局域网,OpenVPN服务器成为每个客户端在虚拟网络上的网关。OpenVPN服务器同时提供对客户端虚拟网卡的路由管理。当客户端对OpenVPN服务器后端的应用服务器的任何访问时,数据包都会经过路由流经虚拟网卡,OpenVPN程序在虚拟网卡上截获数据IP报文,然后使用SSL协议将这些IP报文封装起来,再经过物理网卡发送出去。OpenVPN的服务器和客户端在虚拟网卡之上建立起一个虚拟的局域网络,这个虚拟的局域网对系统的用户来说是透明的。

3,客户端与服务端安全连接的建立

OpenVPN的服务器和客户端支持tcpudp两种连接方式,只需在服务端和客户端预先定义好使用的连接方式(tcpudp)和端口号,客户端和服务端在这个连接的基础上进行SSL握手。连接过程包括SSL的握手以及虚拟网络上的管理信息,OpenVPN将虚拟网上的网段、地址、路由发送给客户端。连接成功后,客户端和服务端建立起SSL安全连接,客户端和服务端的数据都流入虚拟网卡做SSL的处理,再在tcpudp的连接上从物理网卡发送出去。

4,数据包的处理过程

4.1发送数据流程

应用层的外出数据,经过系统调用接口传入核心TCP/IP层做处理,在TCP/IP经过路由到虚拟网卡,虚拟网卡的网卡驱动发送处理程序hard_start_xmit()将数据包加入skb表并完成数据包从核心区到用户区的复制,OpenVPN调用虚拟网卡的字符处理程序tun_read(),读取到设备上的数据包,对读取的数据包使用SSL协议做封装处理后,通过socket系统调用发送出去。

4.2接收数据流程
物理
网卡接收数据包,经过核心TCP/IP上传到OpenVPNOpenVPN通过link_socket_read()接收数据包,使用SSL协议进行解包处理,经过处理的数据包OpenVPN调用虚拟网卡的字符处理程序tun_write()写入虚拟网卡的字符设备,设备驱动程序完成数据从用户区到核心区的复制,并将数据写入skb链表,然后调用网卡netif_rx()接收程序,数据包再次进入系统TCP/IP协议栈,传到上层应用程序。

100916330.jpg

 

5,数据包的封装

OpenVPN提供tuntap两种工作模式。在tun模式下,从虚拟网卡上收到的是不含物理帧头IP数据包,SSL处理模块对IP包进行SSL封装;在tap模式下,从虚拟网卡上收到的是包含物理帧头的数据包,SSL处理模块对整个物理帧进行SSL封装。Tap模式称为网桥模式,整个虚拟的网络就像网桥方式连接的物理网络。这种模式可以传输以太网帧、IPXNETBIOS等数据包,应用范围更广。

6,OpenVPNOpenssl

OpenVPN软件包需要和openssl软件一起安装,因为OpenVPN调用了Openssl函数库,OpenVPN的客户端和服务端建立SSL链接的过程是通过调用Openssl来实现的。通过bio_write()/函数把数据写入Openssl的状态机通道,bio_read()Openssl读取结果。OpenVPN还调用Openssl的加解密函数处理转发的数据包。

 

二,OpenVPN的应用

OpenVPN能够运行于大多常见的系统平台,是一个基于SSL/TLS的VPN解决方案。OpenVPN能够基于TAP/TUN虚拟设备驱动实现2层及3层的链接,提供基于SSL/TLS的工业级别加密功能,并且实现了大多数常见VPN解决方案的全部特性。但目前提供整合了OpenVPN的VPN硬件厂商还不太多。

120711433.jpg

1,安装openvpn软件包

lzo提供了一种数据加密的算法,这里openvpn会用到lzo算法,所以要安装lzo

 

1
2
3
4
5
6
7
8
9
10
11
解压及安装
# tar xvf lzo-2.04.tar.gz
# cd lzo-2.04
# ./configure  --prefix=/usr/local/lzo
# make && make install
# cd ../
# tar xvf openvpn-2.1.4.tar.gz
# cd openvpn-2.1.4
# ./configure  --prefix=/usr/local/openvpn  --with-lzo-headers=/usr/local/lzo/include/  --with-lzo-lib=/usr/local/lzo/lib/ --with-ssl-headers=/usr/include/openssl/ --with-ssl-lib=/usr/lib
# make && make install
# cd ../


2,openvpn设置

2.1用easy-rsa生成服务器证书客户端证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@test1 ~]# mkdir  /etc/openvpn
[root@test1 ~]# cp /root/openvpn-2.1.4/easy-rsa/  /etc/openvpn/ -r
[root@test1 ~]# cd /etc/openvpn/easy-rsa/2.0/
[root@test1 2.0]# cat vars |grep -v '^$'|grep -v '^#'
export EASY_RSA="`pwd`"        RSA在当前目录
export OPENSSL="openssl"
export PKCS11TOOL="pkcs11-tool"
export GREP="grep"
export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`
     这个是一个很特别的参数没有“”, openssl的配置文件
export KEY_DIR="$EASY_RSA/keys"   密钥的位置
echo NOTE: If you run ./clean-all, I will be doing a rm -rf on $KEY_DIR
export PKCS11_MODULE_PATH="dummy"
export PKCS11_PIN="dummy"
export KEY_SIZE=1024     密钥的大小长度
export CA_EXPIRE=3650    CA证书的过期时间天数
export KEY_EXPIRE=3650   密钥的时间过期天数
export KEY_COUNTRY="CN"  国家
export KEY_PROVINCE="HB"  省份
export KEY_CITY="WH"     城市
export KEY_ORG="test.com" 组织
export KEY_EMAIL="root@localhost" 邮箱

 

2.2下面这个命令在第一次安装时可以运行,以后在添加客户端时千万别运行,这个命令 会清除所有已经生成的证书密钥。

1
# ./clean-all

 

2.3建立根证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@test1 2.0]# ./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) [CN]:CN
State or Province Name (full name) [HB]:HUB
Locality Name (eg, city) [WH]:WH
Organization Name (eg, company) [test.com]:test.com
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [test.com CA]:test1.test.com
Name []:
Email Address [root@localhost]:

 

2.4生成服务器端密钥key, 后面这个server-name就是服务器名,可以自定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[root@test1 2.0]# ./build-key-server test1.test.com
Generating a 1024 bit RSA private key
.......................................++++++
..........................++++++
writing new private key to 'test1.test.com.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]:CN
State or Province Name (full name) [HB]:HB
Locality Name (eg, city) [WH]:WH
Organization Name (eg, company) [test.com]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [test1.test.com]:
Name []:
Email Address [root@localhost]:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:
Using configuration from /etc/openvpn/easy-rsa/2.0/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'CN'
stateOrProvinceName   :PRINTABLE:'HB'
localityName          :PRINTABLE:'WH'
organizationName      :PRINTABLE:'test.com'
commonName            :PRINTABLE:'test1.test.com'
emailAddress          :IA5STRING:'root@localhost'
Certificate is to be certified until Oct  6 03:30:01 2023 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

 

2.5生成客户端 key

注意在进入 Common Name (eg, your name or your server's hostname) []: 的输入时, 每个证书输入的名字必须不同.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[root@test1 2.0]# ./build-key  test2.test.com
Generating a 1024 bit RSA private key
............................................................................................................................++++++
......................++++++
writing new private key to 'test2.test.com.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) [HB]:
Locality Name (eg, city) [WH]:
Organization Name (eg, company) [test.com]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [test2.test.com]:      每个client的hostname都不能一样
Name []:
Email Address [root@localhost]:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:
Using configuration from /etc/openvpn/easy-rsa/2.0/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'CN'
stateOrProvinceName   :PRINTABLE:'HB'
localityName          :PRINTABLE:'WH'
organizationName      :PRINTABLE:'test.com'
commonName            :PRINTABLE:'test2.test.com'
emailAddress          :IA5STRING:'root@localhost'
Certificate is to be certified until Oct  6 03:36:48 2023 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

 

2.6生成Diffie Hellman参数,加强安全

1
2
3
4
[root@test1 2.0]# ./build-dh
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
..............+...............+..+..............................................+..+..............+.......+.............

 

2.7创建服务端配置文件

local 192.168.55.25 #换成服务端的IP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@test1 2.0]# mkdir /etc/openvpn/easy-rsa/2.0/conf
[root@test1 2.0]# cp /root/openvpn-2.1.4/sample-config-files/server.conf  /etc/openvpn/easy-rsa/2.0/conf/
[root@test1 2.0]# cat /etc/openvpn/easy-rsa/2.0/conf/server.conf |grep -v '^$'|grep -v'^;'|grep -v '^#'
port 1194
proto udp
dev tun
ca  /etc/openvpn/easy-rsa/2.0/keys/ca.crt
cert /etc/openvpn/easy-rsa/2.0/keys/test1.test.com.crt
key  /etc/openvpn/easy-rsa/2.0/keys/test1.test.com.key  # This file should be kept secret
dh /etc/openvpn/easy-rsa/2.0/keys/dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "dhcp-option DNS 192.168.55.25"
push "dhcp-option DNS 8.8.8.8"
client-to-client
keepalive 10 120
comp-lzo
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
log         openvpn.log
verb 3

 

2.8启动openvpn 

1
2
[root@test1 2.0]# /usr/local/openvpn/sbin/openvpn  --config  /etc/openvpn/easy-rsa/2.0/conf/server.conf &
[3] 11924

2.9打开服务器的路由功能

1
2
3
# vim /etc/sysctl.conf
修改以下内容:
net.ipv4.ip_forward = 1
 

2.10使sysctl.conf配置文件生效并添加iptables转发规则:

1
2
3
# sysctl –p
# iptables -t nat -A POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE
# /etc/init.d/iptables save

 

 

四,测试openvpn的功能

4.1在windows7客户端上安装openvpn-2.1_rc22-install.exe

4.2将服务器上的/etc/openvpn/easy-rsa/2.0/keys下的文件拷贝到C:\Program Files (x86)\OpenVPN\config

4.3在windows7客户端上将C:\Program Files (x86)\OpenVPN\sample-config\client.ovpn拷贝到C:\Program Files (x86)\OpenVPN\config下

4.4编辑client.ovpn 修改如下

remote 服务器IP 1194

4.5 运行client.ovpn测试是否可以ping通10.8.0.1,,也就是服务器的tun接口IP。。

 

 

 

五,openvpn排错

5.1连接openvpn时出现错误提示:

TLS_ERROR: BIO read tls_read_plaintext error: error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned

TLS Error: TLS object -> incoming plaintext read error

TLS Error: TLS handshake failed

这个似乎是提示系统时间和证书时间不一致,具体解决措施为:

1.修改vps时间与本地时间一致

2.重启vps

3.重新连接openvpn试试

4.如果依旧不能连接openvpn,可以在vps上重新生成一个新的证书。

 

5.2今天,部署了下VPN,部署完成连接的时候,总是提示连接失败,很郁闷,贴出日志:
Sun Mar 18 20:25:54 2012 [jesse] Peer Connection Initiated with 10.0.0.200:5000
Sun Mar 18 20:25:55 2012 SENT CONTROL [jesse]: 'PUSH_REQUEST' (status=1)
Sun Mar 18 20:25:55 2012 PUSH: Received control message: 'PUSH_REPLY,route 172.16.1.0 255.255.255.0,route 10.0.1.0 255.255.255.0,topology net30,ping 10,ping-restart 120,ifconfig 10.0.1.6 10.0.1.5'
Sun Mar 18 20:25:55 2012 Options error: Unrecognized option or missing parameter(s) in [PUSH-OPTIONS]:3: topology (2.0.9)
Sun Mar 18 20:25:55 2012 OPTIONS IMPORT: timers and/or timeouts modified
Sun Mar 18 20:25:55 2012 OPTIONS IMPORT: --ifconfig/up options modified
Sun Mar 18 20:25:55 2012 OPTIONS IMPORT: route options modified
Sun Mar 18 20:25:55 2012 TAP-WIN32 device [本地连接 3] opened: \\.\Global\{2893A584-9C99-43FE-B17C-E1F7160BE530}.tap

解决方法

There are no TAP-Win32 adapters on this system. You should be able to create a TAP-Win32 adapter by going to Start -> All Programs -> OpenVPN -> Add a new TAP-Win32 virtual ethernet adapter.

 

5.3 All TAP-Win32 adapters on this system are currently in use

那么很有可能是你的TAP虚拟网卡没有打好驱动,那么只能换其他的openvpn的gui软件了

162905599.jpg

 

5.5官方的openvpn排错

如果遇到OpenVPN初始化失败,或者ping失败,下面有一些共同的问题症状和解决办法:

1.你得到如下错误信息: TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity). 这个错误指出客户端不能跟服务器建立网络链接.

解决办法:

a.请确认客户端访问的服务器的机器名/IP和端口是正确的. 
b.如果你的OpenVPN服务器是单网卡,并处在受保护的局域网中,请确认你你的网关防火墙使用了正确的端口转发规则。比如:你的OpenVPN机器的地址是192.168.4.4,但处在防火墙保护下,时刻监听着UDP协议1194的连接请求,那么负责维护192.168.4.x子网的网关就会有一个端口转发策略,即所有访问UDP协议1194端口的请求都被转发到192.168.4.4 。
c.打开服务器的防火墙允许UDP协议1194端口连接进来,(或者不管是TCP还是UDP协议在服务器的配置文件中配置了)。

2.你得到如下错误信息: Initialization Sequence Completed with errors – 这个错误可能发生在windows下(a)你没有启用DHCP客户端服务(b)你的XP SP2使用了某个第三方的个人防火墙。

解决办法: 启动DHCP客户端服务或者你确认你的XP SP2正确使用了个人防火墙.

3.你虽然获得了Initialization Sequence Completed 的信息,但ping测试还是失败了,那就通常是在服务器或者客户端的防火墙阻止过滤了在TUN/TAP设备结构上的网络流量。

解决办法: 关闭客户端的防火墙,如果防火墙过滤了TUN/TAP设备端口的流量。比如在Windows XP SP2系统,你可以到Windows 安全中心 -> Windows 防火墙 -> 高级 然后不要选择TAP-Win32 adapter设备 (即禁止TUN/TAP设备使用防火墙过滤 ,实质上就是告诉防火墙不要阻止VPN认证信息)。 同样在服务器端也要确认TUN/TAP设备不实用防火墙过滤 (也就是说在TUN/TAP接口上选择过滤是有一定的安全保障的. 具体请看下面一节的访问策略).

4.当以udp协议的配置文件启动的时候连接停止,服务器的日志文件显示如下一行信息:

TLS: Initial packet from x.x.x.x:x, sid=xxxxxxxx xxxxxxxx

不管怎么样,这信息只在服务器端显示,在客户端是不会显示相同的信息。

解决办法: 你只拥有单向连接从客户端到服务器,从服务器到客户端的连接被防火墙挡住, 通常在客户端这边,防火墙(a)可能是个运行在客户端的个人防火墙软件(b)或者服务客户端的NAT路由 网关被设置为从服务器端访问客户端的UDP协议包被阻挡返回。

(责任编辑:IT)
------分隔线----------------------------
栏目列表
推荐内容