OpenVPN部署方案

1、前言(背景)

考虑到数据传输的安全性,我们需要利用开源技术对数据包进行加密并对数据流通进行身份验证,在参考第三方案例的基础上,经过初步评估,OpenVPN能充分满足我们的基本需求。

 

2、原理剖析

内容简介:了解OpenVPN工作原理并在实际环境中部署OpenVPN Community 2.4.14(多用户)版

网络:

LAN网段:192.168.0.0/23

VPN网段:10.8.0.0/24

系统环境:CentOS6.9-x86_64

OpenVPN的工作原理简图

VPN技术通过密钥交换、封装、认证、加密手段在公共网络上建立起私密的隧道,保障传输数据的完整性、私密性和有效性。OpenVPN是基于该技术产生的优秀开源项目,实现了SSL VPN的一种解决方案。

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

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

 

虚拟网卡

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

 

地址池以及路由

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

 

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

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

 

数据包的处理过程

 

发送数据流程:

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

 

接收数据流程

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

 

数据包的封装

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

 

OpenVPN与Openssl

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

 

3、安装部署

3.1 安装 epel源

#yum -y install epel-release

#yum -y update

 

3.2 查看系统tun模块信息(2.4.x以上版本系统自带)

#modinfo tun

filename:       /lib/modules/2.6.32-431.el6.x86_64/kernel/drivers/net/tun.ko

alias:          char-major-10-200

license:        GPL

author:         (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>

description:    Universal TUN/TAP device driver

srcversion:     490B6F6A77D645CFFCDF9D2

depends:

vermagic:       2.6.32-431.el6.x86_64 SMP mod_unload modversions

 

3.3 安装OpenVPN相关依赖包

#yum -y install openssl openssl-devel lzo lzo-devel pam pam-devel

 

3.4 安装OpenVPN/easy-rsa

#yum install -y openvpn easy-rsa

 

3.5 easy-rsa配置

 

#mkdir -p /etc/openvpn/easy-rsa/keys

#cp -rf /usr/share/easy-rsa/2.0/* /etc/openvpn/easy-rsa/

#cd /etc/openvpn/easy-rsa/

#ln -s openssl-1.0.0.cnf openssl.cnf

为openssl配置文件设置软链接

 

3.6 配置PKI

#chmod +x ./vars

#vim vars

找到

export KEYCOUNTRY=”US”

export KEYPROVINCE=”CA”

export KEYCITY=”SanFrancisco”

export KEYORG=”Fort-Funston”

export <KEY_EMAIL=”me@myhost.mydomain”>

这个根据自身情况做对应修改,当然不改也可以运行。

这次修改后内容为:

export KEY_COUNTRY=”CN”

export KEY_PROVINCE=”GuangDong”

export KEY_CITY=”GuangZhou”

export KEY_ORG=”Infinite”

export KEY_EMAIL=”deyanggong@infinite.net.cn”

export KEY_OU=”OP”

注:在后面生成服务端ca证书时,这里的配置内容将作为缺省选项。

 

3.7 产生证书

#source ./vars

#./clean-all

初始化证书授权中心

#./build-ca

创建CA证书和密钥

#./build-key-server server

创建服务器端证书和密钥

#./build-key client

创建客户端的证书和密钥

#./build-dh

生成DH验证文件(生成diffie hellman参数),用于增强openvpn安全性。

#openvpn –genkey –secret /etc/openvpn/keys/ta.key

生成ta.key文件

#cd /etc/openvpn/easy-rsa/keys/

#cp dh2048.pem ca.crt server.crt server.key /etc/openvpn/

4、服务端配置简介

4.1 编辑服务配置文件

#mkdir -p /var/log/openvpn

#cp /usr/share/doc/openvpn-2.3.14/sample/sample-config-files/server.conf /etc/openvpn/

#vim /etc/openvpn/server.conf

——————————————————————————

# 设置监听IP,默认是监听所有IP

;local a.b.c.d

#监听本机eth0网络接口,因内网用的固定ip所以直接…

local 192.168.0.10

 

# 设置监听端口,必须要对应的在防火墙里面打开

port 1194

 

# 设置用TCP还是UDP协议?

;proto udp

#使用TCP传输协议更有保证。

proto tcp

 

# 设置创建tun的路由IP通道,还是创建tap的以太网通道,由于路由IP容易控制,所以推荐使用tunnel;

# 但如果如IPX等必须使用第二层才能通过的通讯,则可以用tap方式,tap也就是以太网桥接

;dev tap

dev tun

 

# 这里是重点,必须指定SSL/TLS root certificate (ca),

# certificate(cert), and private key (key)

# ca文件是服务端和客户端都必须使用的,但不需要ca.key

# 服务端和客户端指定各自的.crt和.key

# 请注意路径,可以使用以配置文件开始为根的相对路径,

# 也可以使用绝对路径

# 请小心存放.key密钥文件

ca ca.crt

cert server.crt

key server.key # This file should be kept secret

 

# 指定Diffie hellman parameters.

(默认是2048,如果生成ca的时候修改过dh参数“export KEY_SIZE”则改为对应的数字)

dh dh2048.pem

 

# 配置VPN使用的网段,OpenVPN会自动提供基于该网段的DHCP服务,但不能和任何一方的局域网段重复,需保证唯一

server 10.8.0.0 255.255.255.0

 

# 维持一个客户端和virtual IP的对应表,以方便客户端重新连接可以获得同样的IP

ifconfig-pool-persist ipp.txt

 

# 为客户端创建对应的路由,以另其通达公司网内部服务器

# 但记住,公司网内部服务器也需要有可用路由返回到客户端

;push “route 192.168.20.0 255.255.255.0”

push “route 192.168.0.0 255.255.254.0”  (修改为LAN网段)

 

# 若客户端希望所有的流量都通过VPN传输,则可以使用该语句

# 其会自动改变客户端的网关为VPN服务器,推荐关闭

# 一旦设置,请小心服务端的DHCP设置问题

;push “redirect-gateway def1 bypass-dhcp”

 

# 用OpenVPN的DHCP功能为客户端提供指定的DNS、WINS等

;push “dhcp-option DNS 208.67.222.222”

;push “dhcp-option DNS 208.67.220.220”

 

# 默认客户端之间是不能直接通讯的,除非把下面的语句注释掉

client-to-client

# keepalive指令将导致类似于ping命令的消息被来回发送,以便于服务器端和客户端知道对方何时被关闭。

# 每10秒钟ping一次,如果120秒内都没有收到对方的回复,则表示远程连接已经关闭。

keepalive 10 120

 

# 下面是一些对安全性增强的措施

# For extra security beyond that provided by SSL/TLS, create an “HMAC firewall”

# to help block DoS attacks and UDP port flooding.

#

# Generate with:

# openvpn –genkey –secret ta.key

#

# The server and each client must have a copy of this key.

# The second parameter should be 0 on the server and 1 on the clients.

;tls-auth ta.key 0 # This file is secret

(这句要注释掉)

 

# 使用lzo压缩的通讯,服务端和客户端都必须配置

comp-lzo

 

# 输出短日志,每分钟刷新一次,以显示当前的客户端

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

 

# 缺省日志会记录在系统日志中,但也可以导向到其他地方

# 建议调试的使用先不要设置,调试完成后再定义

Log  /var/log/openvpn/openvpn.log

log-append  /var/log/openvpn/openvpn.log

 

# 设置日志的级别

#

# 0 is silent, except for fatal errors

# 4 is reasonable for general usage

# 5 and 6 can help to debug connection problems

# 9 is extremely verbose

verb 5

#前期对日志信息要求展示丰富点,后期视情况而修改,改成verb 5可以多查看一些调试信息,范围0~9,数字越大,日志记录更详细。

 

# Notify the client that when the server restarts so it

# can automatically reconnect.

#explicit-exit-notify 1

#当服务端重启时通知客户端从而能自动重新连接,此功能暂时不需要打开,注释。

——————————————————————————

 

#openvpn /etc/openvpn/server.conf

#service openvpn start

#chkconfig openvpn on

如果遭遇启动失败的情况,可以在配置文件中加上一行log-append openvpn.log

再尝试启动,然后到/var/log/openvpn/检查openvpn.log文件来查看错误发生原因。

 

4.2 内核开启路由转发功能

#echo “1” > /proc/sys/net/ipv4/ip_forward

# vim /etc/sysctl.conf

 

# Controls IP packet forwarding

net.ipv4.ip_forward = 1

 

# Controls source route verification

net.ipv4.conf.default.rp_filter = 0

 

# Do not accept source routing

net.ipv4.conf.default.accept_source_route = 1

 

#sysctl -p

4.3 设置iptables(这一条至关重要,通过配置nat将vpn网段IP转发到server内网)

 

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

设置openvpn端口通过:

#iptables -A INPUT -p TCP –dport 1194 -j ACCEPT

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

 

#iptables -A INPUT -i tun0 -j ACCEPT

#iptables -A INPUT -s 10.8.0.0/24 -j ACCEPT

#iptables -A FORWARD -i tun+ -j ACCEPT

保存iptable设置:

#service iptables save

 

5、客户端配置

5.1 客户端配置文件模板

将服务器端生成的key(ca.crt,client.crt,client.key,ta.key)下载到本地。

进入客户端OpenVPN目录,将sample-config下的client.ovpn文件复制到config目录,

client端做相应的修改:

client

dev tun

proto tcp

remote 192.168.0.10 1194

ca ca.crt

cert client.crt

key client.key

;tls-auth ta.key 0 (这句要注释掉)

comp-lzo

;user nobody (仅供非windows客户端配置,windows请用“;”注释掉)

;group nobody   (仅供非windows客户端配置,windows请用“;”注释掉)

persist-key

persist-tun

 

5.2 Windows客户端

下载地址:http://openvpn.net/index.php/download.html

将key和新建的client.ovpn放到OpenVPN所在config目录下,到桌面双击openvpn图标在右下角任务栏点击连接即可即可。

 

5.3 Mac客户端

https://tunnelblick.net/downloads.html

1.打开Tunnelblick

2.点击左下角+

3.我有设置文件

4.OpenVPN设置

5.打开私人设置文件夹

6.将key和新建的client.ovpn放到此目录下

备注:最新版本是要拖曳配置文件到Tunnelblick会话框,请注意姿势优雅。

 

5.3 Linux客户端

#yum install openvpn

#openvpn –daemon –config client.ovpn

#chkconfig openvpn on

 

6、日常维护篇

——–生成密钥——

#cd /etc/openvpn/easy-rsa

#source ./vars

切记万勿执行./clean-all(初始化证书授权中心),这将清空所有key文件。

创建客户端证书和密钥

#./build-key client_name

依次按提示选择默认或自定义相关信息,完成后进入keys目录导出ca.crt、client_name.crt、client_name.key。

——–注销密钥——

#./revoke-full

 

7、补充

7.1 用户密钥生成脚本

说明:openvpn.sh为密钥生成脚本,client.conf.mod为客户端配置文件模板(模板内容支持自定义,个人建议将公网IP作为自定量),需将上述两个文件放到相同目录下运行。

7.2 下发路由

1)、在/etc/openvpn/server.conf如下位置添加记录(示例):

# Push routes to the client to allow it

# to reach other private subnets behind

# the server.  Remember that these

# private subnets will also need

# to know to route the OpenVPN client

# address pool (10.8.0.0/255.255.255.0)

# back to the OpenVPN server.

push “route 42.236.73.236 255.255.255.255”

2)、如果对方服务器端只对公司特定外网IP放行,则建议在出口路由器上做策略路由,确保OpenVPN的流量通过指定线路(WAN口)出去。

 

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.