OpenVPN访问公司内网

使用OpenVPN访问公司内网详细教程。

概述

VPN (Virtual Private Network) 是虚拟私有网,它通过在公网上创建一个专用并且加密的网络通道(隧道)进行通讯,在实际的应用中可以帮助远程用户、公司分支机构、商业伙伴及供应商等之间建立一个安全可信的网络连接.

实际上使用VPN的目的及作用就是从网络层面打通两个或多个异地网络,就好像在同一个局域网一样,并且是加密安全的.

使用vpn的一些场景:

  • 穿墙,看外面的世界
  • 本地网络访问公司内网资源,比如在家里或出差的同事要访问到公司内部的网络设备、服务器资源
  • 两个或以上的异地网络互通,比如多个IDC机房、多个分支机构之间内网互通以及数据传输

VPN软件有很多,有商业的、开源的,openvpn就是其中一个非常好的开源vpn软件,在生产环境中使用也非常稳定及可靠,其主要特点:开源、跨平台、易于使用、稳定与安全性,对于中小型企业来说用openvpn架设vpn服务器是个不错的选择,而不去考虑商业的vpn软件,有一定成本优势。呵呵,做运维就是这样,总是用一些开源的软件搭建一套还不错的系统.

用openvpn实现访问远程网络

有这样的需求:有些同事不在公司或在外面出差但又要访问公司内网的服务器资源,一般的做法是做端口映射,但是随着端口映射的数量越来越多带来一些问题:管理比较麻烦、不是很安全、配置繁琐。
对于这种需求可以使用vpn打通自己(本地)的网络与公司的网络,这样就像是在公司内网访问服务器一样并且是安全的.
因此用openvpn来搭建vpn服务器,规划如下:

环境说明:

  • 目的是让你所在的本地网络能够通过vpn服务器访问公司内网(172.16.0.0/24、172.16.2.0/24、10.10.10.0/24)中的主机
  • 用公司内网中的一台(172.16.0.100)作为vpn服务器,然后在防火墙上做外网端口映射, 发布在外网(因为没有公网地址,只能这样做)
  • 公司网络中的172.16.0.0/24、172.16.2.0/24、10.10.10.0/24网段已经是互通的
IP 作用 说明
172.16.0.100 openvpn 监听在内网1999端口,映射为外网183.16.133.212的1999端口
10.10.10.2 公司内网服务器
172.16.2.22 公司内网服务器

部署openvpn服务端(172.16.0.100)

openvpn需要tun模块支持,所以先检查是否支持tun模块

1
2
# ls /dev/net/tun 
/dev/net/tun # 如果有表示支持

停掉selinux

1
2
# setenforce 0
setenforce: SELinux is disabled

开启路由转发,编辑 /etc/sysctl.conf 文件将 net.ipv4.ip_forward = 0 改为 net.ipv4.ip_forward = 1,然后执行:

1
sysctl -p

安装openvpn及相关包

1
2
$ yum install epel-release -y  #curl http://mirrors.aliyun.com/repo/epel-6.repo  -o  /etc/yum.repos.d/epel-6.repo --silent   # 添加阿里的EPEL源
$ yum install openssl openvpn easy-rsa lzo -y

  • openssl包,用来加密的
  • lzo包, 用来进行数据压缩
  • easy-ras包, 提供了一些证书生成脚本、模板配置文件等

可以看下装了哪些东西:

1
2
rpm -ql openvpn
rpm -ql easy-rsa

创建相关目录:

1
2
3
mkdir /var/log/openvpn                      # 放openvpn相关日志文件
mkdir /etc/openvpn/easy-rsa # 放easy-rsa包提供的相关工具
mkdir /etc/openvpn/ccd # openvpn客户端的配置目录,后面会用到

将easy-ras包提供的工具复制到 /etc/openvpn/easy-rsa

1
2
3
4
5
6
# cp /usr/share/easy-rsa/2.0/* /etc/openvpn/easy-rsa/ -r 
# cd /etc/openvpn/easy-rsa
# ls // 可以看到就是一堆脚本,主要是用来生成证书
build-ca build-key build-key-server clean-all list-crl openssl-1.0.0.cnf sign-req whichopensslcnf
build-dh build-key-pass build-req inherit-inter openssl-0.9.6.cnf pkitool vars
build-inter build-key-pkcs12 build-req-pass keys openssl-0.9.8.cnf revoke-full

修改 openssl-1.0.0.cnf 文件中 default_crl_days值,调大为3650或者更大,默认是30 (注: 这步不做的话如果服务端开启了crl-verify功能,30天后全部客户端会连不上)

1
default_crl_days = 3650

编辑/etc/openvpn/easy-rsa/vars文件,找到下面的变量修改成你指定的值,后面生成证书的时候会应用这些变量值(不做这步也可以,它会应用默认的变量值)

1
2
3
4
5
6
7
export KEY_COUNTRY="CN"        # 国家
export KEY_PROVINCE="GD" # 省份
export KEY_CITY="GZ" # 城市
export KEY_ORG="MY_ORG" # 组织/公司
export KEY_EMAIL="vpn@qq.com" # 邮箱
export KEY_OU="vpn" # 单位
export KEY_NAME="openvpn" # 服务器名称

然后执行

1
2
# source vars      # 导入vars文件中的变量作为当前的环境变量
# ./clean-all # 清除旧的keys目录下的文件

生成CA(证书颁发机构),一直回车即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ./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) [GD]:
Locality Name (eg, city) [GZ]:
Organization Name (eg, company) [MY_ORG]:
Organizational Unit Name (eg, section) [vpn]:
Common Name (eg, your name or your server's hostname) [openvpn CA]:
Name [openvpn]:
Email Address [vpn@qq.com]:

会在 /etc/openvpn/easy-rsa/keys 目录下生成ca.crt、ca.key两个证书文件

1
2
3
# ls /etc/openvpn/easy-rsa/keys/ | grep ca
ca.crt
ca.key

生成服务器证书

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
41
42
43
./build-key-server vpnserver     # 起个名字叫vpnserver,后面会用到 (注:必须是唯一的、尽量是有意义的名称)
Generating a 2048 bit RSA private key
................................+++
.....+++
writing new private key to 'vpnserver.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) [GD]:
Locality Name (eg, city) [GZ]:
Organization Name (eg, company) [MY_ORG]:
Organizational Unit Name (eg, section) [vpn]:
Common Name (eg, your name or your server's hostname) [vpnserver]:
Name [vpn]:
Email Address [vpn@qq.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: # 这里是设置连接vpn的时候要不要输入账号和密码,如果不设置就直接回车(可选)
An optional company name []:
Using configuration from /etc/openvpn/easy-rsa/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:'GD'
localityName :PRINTABLE:'GZ'
organizationName :PRINTABLE:'MY_ORG'
organizationalUnitName:PRINTABLE:'vpn'
commonName :PRINTABLE:'vpnserver'
name :PRINTABLE:'vpn'
emailAddress :IA5STRING:'vpn@qq.com'
Certificate is to be certified until Apr 29 06:26:49 2026 GMT (3650 days)
Sign the certificate? [y/n]:y # 输入y
out of 1 certificate requests certified, commit? [y/n]y # 输入y
Write out database with 1 new entries
Data Base Updated

它会在 /etc/openvpn/easy-ras/keys 目录下生成三个证书文件

1
2
3
4
# ls /etc/openvpn/easy-rsa/keys/ | grep vpnserver
vpnserver.crt
vpnserver.csr
vpnserver.key

生成客户端证书,客户端会用证书来连接服务端:

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
41
42
43
./build-key vpnclient      --- 表示为vpnclient这个客户端生成证书,后面会用到 (注:必须是唯一的、尽量是有意义的名称)
Generating a 2048 bit RSA private key
.......+++
....................+++
writing new private key to 'vpnclient.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) [GD]:
Locality Name (eg, city) [GZ]:
Organization Name (eg, company) [MY_ORG]:
Organizational Unit Name (eg, section) [vpn]:
Common Name (eg, your name or your server's hostname) [vpnclient]:
Name [vpn]:
Email Address [vpn@qq.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/easy-rsa/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:'GD'
localityName :PRINTABLE:'GZ'
organizationName :PRINTABLE:'MY_ORG'
organizationalUnitName:PRINTABLE:'vpn'
commonName :PRINTABLE:'vpnclient'
name :PRINTABLE:'vpn'
emailAddress :IA5STRING:'vpn@qq.com'
Certificate is to be certified until Apr 29 06:30:42 2026 GMT (3650 days)
Sign the certificate? [y/n]:y --- 输入y
out of 1 certificate requests certified, commit? [y/n]y --- 输入y
Write out database with 1 new entries
Data Base Updated

它会在 /etc/openvpn/easy-ras/keys 目录下生成三个证书文件

1
2
3
4
# ls /etc/openvpn/easy-rsa/keys/ | grep vpnclient
vpnclient.crt
vpnclient.csr
vpnclient.key

上面是交互式的生成证书,还可以使用非交互式的方式生成证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# ./build-key --batch vpnclient
Generating a 2048 bit RSA private key
.....................................................+++
..........+++
writing new private key to 'vpnclient.key'
-----
Using configuration from /etc/openvpn/easy-rsa/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:'GD'
localityName :PRINTABLE:'GZ'
organizationName :PRINTABLE:'weconex.inc'
organizationalUnitName:PRINTABLE:'test'
commonName :PRINTABLE:'vpnclient'
name :PRINTABLE:'TEMP'
emailAddress :IA5STRING:'weconex@weconex.com'
Certificate is to be certified until Oct 8 17:33:15 2027 GMT (3650 days)

Write out database with 1 new entries
Data Base Updated

最后创建Diffie Hellman文件,这步需要一点时间,等它执行完就行

1
$ ./build-dh

查看生成的Diffie hellman秘钥文件

配置openvpn,编辑/etc/openvpn/server.conf文件,添加如下:

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
local 172.16.0.100                               # 监听的ip
port 1999 # 监听的端口,默认1194,我设置1999,根据你的需求改就行
proto tcp # 使用的协议,默认udp,因为经常要通过vpn传文件对可靠性要求比较高,所以用tcp
dev tun # 使用tun(隧道)模式,openvpn有两种模式,一种是TUN,另一种是TAP
ca /etc/openvpn/easy-rsa/keys/ca.crt # 这四条都是指定证书的路径,要确保路径或文件能够访问
cert /etc/openvpn/easy-rsa/keys/vpnserver.crt
key /etc/openvpn/easy-rsa/keys/vpnserver.key
dh /etc/openvpn/easy-rsa/keys/dh2048.pem
server 10.8.0.0 255.255.255.0 # 设置成server模式并给客户端分配的ip段,服务端会用其中.1和.2两个ip,不要和你的内网冲突
ifconfig-pool-persist ipp.txt # 当vpn断开或重启后,可以利用该文件重新建立相同的IP地址连接
push "route 172.16.0.0 255.255.255.0" # 这三条是给客户端推的路由,客户端连上后会根据这个添加路由,vpn服务器后端有几个网段就写几个
push "route 172.16.2.0 255.255.255.0" # 这些路由的作用是告诉客户端去另一个子网都转发给TUN接口,类似于静态路由
push "route 10.10.10.0 255.255.255.0"
client-config-dir /etc/openvpn/ccd # 客户端的个性配置目录,比如针对每个客户端推送不同的路由、配置不同的ip
keepalive 10 120 # 每10秒ping一次,如果超过120s认为对方已经down了,需要重连
comp-lzo # 在vpn链接上启用压缩,服务端开启客户端也必须开启
max-clients 100 # 最多有几个vpn客户端可以连
user nobody # 启动openvpn的用户和组,建议用nobody
group nobody
client-to-client # 允许vpn客户端之间通信
duplicate-cn # 允许多个客户端使用同一个证书登陆,生产环境建议为每个用户都生成自己的证书
persist-key # 通过keepalived检测后重新启动vpn,不重新读取keys,保留第一次使用的keys
persist-tun # 通过keepalived检测后重新启动vpn,一直保持tun或tap设备是linkup
status /var/log/openvpn/openvpn-status.log # openvpn的状态日志文件
log /var/log/openvpn/openvpn.log # openvpn的日志文件
writepid /var/run/openvpn/server.pid # pid文件
verb 3 # 日志级别
mute 20 # 如果连续出现20条相同的日志,只记录一条

然后启动openvpn

1
2
3
# service openvpn start
# chkconfig --add openvpn
# chkconfig --level 35 openvpn on

会看到有个tun0接口并且添加了两条路由

1
2
3
4
5
6
7
8
9
10
11
12
# ifconfig tun0
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.8.0.1 P-t-P:10.8.0.2 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:2499142 errors:0 dropped:0 overruns:0 frame:0
TX packets:2719489 errors:0 dropped:45 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:895142072 (853.6 MiB) TX bytes:1093625277 (1.0 GiB)

# route -n | grep tun0
10.8.0.2 0.0.0.0 255.255.255.255 UH 0 0 0 tun0
10.8.0.0 10.8.0.2 255.255.255.0 UG 0 0 0 tun0
  • 启动了一个tun0网络接口,ip是10.8.0.1,P-t-P:10.8.0.2 是点到点的意思
  • 添加了两条路由,一个是主机路由 (UH),另一个是静态路由 (UG),表示去10.8.0.0网段的数据包下一跳是10.8.0.2

添加一条SNAT规则,让源地址是10.8.0.0/24网段的地址进来转换成vpn服务器的内网地址(172.16.0.100),这样vpn客户端访问公司内网服务器的时候伪装成vpn服务器去访问

1
2
3
4
# iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j SNAT --to-source 172.16.0.100 
# service iptables save
# service iptables start
# chkconfig --level 35 iptables on

如果不用上面的SNAT方式,还有种做法是在所有公司内网中的主机或服务器上添加回程路由,这样才能回包给vpn客户端

1
2
# route add 10.8.0.0 MASK 255.255.255.0 172.16.0.100        // 如果是windows
# ip route add 10.8.0.0/24 via 172.16.0.100 // 如果是linux

如果数量少还好,但很多的话就比较麻烦,所以推荐用SNAT的方式,到了这里openvpn服务端已经配好了,客户端可以连了。

客户端连接vpn服务器

openvpn支持linux、window、mac等多种客户端,

如果是windows客户端

先安装openvpn-gui,一直下一步就行,默认会安装在C:\Program Files\OpenVPN

进到config目录,创建一个vpnclient目文件夹,把服务器上的 /etc/openvpn/easy-rsa/keys下的ca.crt、vpnclient.crt、vpnclient.key三个证书文件拉下来放进去

然后添加一个vpnclient.ovpn的文件,这个文件用来连接openvpn服务端

vpnclient.ovpn文件的内容是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
client                        # 设置为client模式
dev tun # 设置为tun模式,必须和服务端一致
proto tcp # 使用的协议,必须和服务端一致
remote 183.6.133.212 1999 # 指定openvpn服务器的地址和端口
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert vpnclient.crt
key vpnclient.key
remote-cert-tls server
auth-nocache # 不在内存中缓存密码
comp-lzo # 启动压缩,必须和服务端一致
verb 3

然后连接openvpn,点击运行 img选 Connect ,如果出现绿色图标img说明vpn连接成功了.

连接成功后会启一个网络连接,可以看到分配的ip地址是10.8.0.10 / 30

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
以太网适配器 本地连接 2:

连接特定的 DNS 后缀 . . . . . . . :
描述. . . . . . . . . . . . . . . : TAP-Windows Adapter V9
物理地址. . . . . . . . . . . . . : 00-FF-0A-6B-5D-9D
DHCP 已启用 . . . . . . . . . . . : 是
自动配置已启用. . . . . . . . . . : 是
本地链接 IPv6 地址. . . . . . . . : fe80::bca0:7a3d:716c:5769%17(首选)
IPv4 地址 . . . . . . . . . . . . : 10.8.0.10(首选)
子网掩码 . . . . . . . . . . . . : 255.255.255.252
获得租约的时间 . . . . . . . . . : 2017年10月18日 3:43:41
租约过期的时间 . . . . . . . . . : 2018年10月18日 3:43:41
默认网关. . . . . . . . . . . . . :
DHCP 服务器 . . . . . . . . . . . : 10.8.0.9
DHCPv6 IAID . . . . . . . . . . . : 469827338
DHCPv6 客户端 DUID . . . . . . . : 00-01-00-01-1C-F4-C8-B2-34-E6-D7-6C-5E-88
........

客户端还会添加路由,可以看下路由表,下面这些是服务端配置推送给客户端的路由,其实就是告诉客户端去这些网段都通过vpn服务器,类似于静态路由

1
2
3
4
5
6
7
8
9
10
11
12
> route PRINT -4
IPv4 路由表
===========================================================================
活动路由:
网络目标 网络掩码 网关 接口 跃点数
10.8.0.0 255.255.255.0 10.8.0.9 10.8.0.10 20
10.8.0.8 255.255.255.252 在链路上 10.8.0.10 276
10.8.0.10 255.255.255.255 在链路上 10.8.0.10 276
10.8.0.11 255.255.255.255 在链路上 10.8.0.10 276
10.10.10.0 255.255.255.0 10.8.0.9 10.8.0.10 20
172.16.0.0 255.255.255.0 10.8.0.9 10.8.0.10 20
172.16.2.0 255.255.255.0 10.8.0.9 10.8.0.10 20

测试,ping下公司内网中的主机,看下是否能够访问,如果可以说明ok了

如果是linux客户端

和windows一样,先安装openvpn

1
2
# curl http://mirrors.aliyun.com/repo/epel-6.repo  -o  /etc/yum.repos.d/epel-6.repo --silent   # 添加阿里的EPEL源
# yum install openvpn -y

创建相关目录

1
2
# mkdir /etc/openvpn/keys          # 放客户端的相关证书
# mkdir /var/log/openvpn # 放日志的目录

将服务器上 /etc/openvpn/easy-rsa/keys 下的ca.crt、vpnclient.crt、vpnclient.key这些证书文件拉下来放到 /etc/openvpn/keys

1
2
# ls /etc/openvpn/keys
ca.crt vpnclient.crt vpnclient.key

编辑客户端的配置文件/etc/openvpn/client.conf,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
client                                      # 设置为clinet模式
dev tun # 使用tun模式,必须和服务端一致
proto tcp # 使用的协议,必须和服务端一致
remote 183.6.133.212 1999 # 指定openvpn服务端的ip和端口,有需要可以使用多个做高可用.
resolv-retry infinite
nobind
persist-key
persist-tun
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/vpnclient.crt
key /etc/openvpn/keys/vpnclient.key
remote-cert-tls server
auth-nocache
user nobody
group nobody
status /var/log/openvpn/openvpn-status.log
log /var/log/openvpn/openvpn.log
writepid /var/run/openvpn/client.pid # 指定pid文件
comp-lzo # 压缩数据,服务端有指定客户端也要
verb 3
mute 20

启动openvpn客户端

1
2
3
# service openvpn stat
# chkconfig --add openvpn
# chkconfig --level 35 openvpn on

客户端启动后只有进程,因为它作为客户端去连服务端,不需要提供端口

1
2
3
# ps aux | grep vpn
nobody 4236 0.1 0.3 46916 3232 ? Ss 01:36 0:00 /usr/sbin/openvpn --daemon --writepid /var/run/openvpn/client.pid
--cd /etc/openvpn --config client.conf --script-security 2

同样也会有个tun0网络接口

1
2
3
4
5
6
7
8
# ifconfig tun0
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.8.0.14 P-t-P:10.8.0.13 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

此时我们可以看下路由表,下面这些路由就是根据服务器的配置(push)推送过来的,目的是通知客户端根据这个来添加路由,实际上就是告诉客户端去这些网段都转发给tun0接口,也就是vpn服务器,类似静态路由

1
2
3
4
5
6
# route -n | grep tun0
10.8.0.13 0.0.0.0 255.255.255.255 UH 0 0 0 tun0 # 主机路由
172.16.2.0 10.8.0.13 255.255.255.0 UG 0 0 0 tun0 # 去172.16.2.0 下一跳(网关)是10.8.0.13
10.8.0.0 10.8.0.13 255.255.255.0 UG 0 0 0 tun0 # 去10.8.0.0 下一跳(网关)是10.8.0.13
172.16.0.0 10.8.0.13 255.255.255.0 UG 0 0 0 tun0 # 去172.16.0.0 下一跳(网关)是10.8.0.13
10.10.10.0 10.8.0.13 255.255.255.0 UG 0 0 0 tun0 # 去10.10.10.0 下一跳(网关)是10.8.0.13

最后测试,ping下公司内网中的主机,看下是否能够访问,如果可以说明ok了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# ping 172.16.0.104                                           # 可以通公司内网172.16.0.0段中的主机
PING 172.16.0.104 (172.16.0.104) 56(84) bytes of data.
64 bytes from 172.16.0.104: icmp_seq=1 ttl=63 time=7.52 ms
^C
--- 172.16.0.104 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 327ms
rtt min/avg/max/mdev = 7.524/7.524/7.524/0.000 ms

# ping 172.16.2.1 # 可以通公司内网172.16.2.1段中的主机
PING 172.16.2.1 (172.16.2.1) 56(84) bytes of data.
64 bytes from 172.16.2.1: icmp_seq=1 ttl=253 time=205 ms
--- 172.16.2.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 768ms
rtt min/avg/max/mdev = 205.701/205.701/205.701/0.000 ms

# ping 10.10.10.2 # 可以通公司内网10.10.10.0段中的主机
PING 10.10.10.2 (10.10.10.2) 56(84) bytes of data.
64 bytes from 10.10.10.2: icmp_seq=1 ttl=126 time=5.86 ms
^C
--- 10.10.10.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 755ms
rtt min/avg/max/mdev = 5.865/5.865/5.865/0.000 ms

数据包的走向是:客户端访问公司内网主机 —– 通过路由转发 —- vpn服务器(tun0) —- SNAT —– 公司内网主机

要点小结:

  • vpn的作用就是让两个网络可以互通,就好像在同一个局域网里面一样
  • openvpn配置好了后可以把它看成一个路由器,需要有点网络方面的知识才好理解

其它功能及需求:

1、如何给客户端指定配置,比如不同的客户端不同的ip地址、推送不同路由等

先在server.conf中指定 client-config-dir目录,能够让openvpn访问的到

1
client-config-dir /etc/openvpn/ccd        #  确保/etc/openvpn/ccd存在

在/etc/openvpn/ccd目录下编辑一个与客户端同名的文件,比如想给vpnclient的这个客户端指定配置,那么就是/etc/openvpn/ccd/vpnclient,这些配置可以是

1
2
3
4
5
ifconfig-push 10.8.0.9 10.8.0.10       # 指定客户端的IP地址,如果想固定客户端的ip可以这样做
push "route 172.16.0.0 255.255.255.0" # 推送指定的路由,不同的客户端推送不同的路由可以这样做
iroute 172.16.20.0 255.255.255.0 # 忽略路由
push "dhcp-option DNS 202.96.128.166" # 推送DNS
..........

2、openvpn服务端怎么做高可用

如果vpn服务器只有一台的话就是个单点,如果有需求可以做高可用,做法是准备两台openvpn服务器,它们相关证书、配置都一样(可以做一个然后复制到另一个),然后在客户端的配置文件中指定两个remote

1
2
remote  第一个vpn服务器ip   端口
remote 第二个vpn服务器ip 端口

然后测试下模拟挂掉一个,能不能用、对使用有没有什么影响

3、怎么给客户端推送指定的DNS

可以在服务端server.conf或者ccd下面配置推送给客户端的dns

1
2
push "dhcp-option DNS 202.96.128.166" 
push "dhcp-option DNS 202.96.128.167"

这种场景一般是要用到远程内网中的dns,用的不多

4、怎么给客户端生成证书

img 通过build-key生成客户端证书

对于生成证书需要考虑的问题:是为每个用户生成证书、还是多个客户端使用一个证书? 如果是多个客户端用同一个证书登陆,优点是省事,缺点是如果想吊销这个证书那么就会影响所有的用户, 如果是每个用户都有自己的证书,优点是管理方便,缺点是麻烦(官方推荐为每个用户生成一个证书,每个用户用自己的证书连接vpn,虽然麻烦了点)

5、如何把客户端的默认网关指向vpn服务器

1
push "redirect-gateway def1 bypass-dhcp"

需要的注意的是,如果这样配置会导致所有的流量都经过vpn服务器,这样的vpn服务器的压力会比较大,一般用的不是很多,除非必须要这么做

吊销证书


吊销证书是指让客户端的证书无效,那么被吊销证书的用户就不能连上vpn了。有这个样的场景,某个同事之前给他分配了vpn客户端,可以连vpn,现在它离职了,不想在让他在用vpn了,这时可以吊销它的证书。

例如:吊销客户端 ( vpnclient ) 的证书.

1
2
3
# cd /etc/openvpn/easy-rsa
# source ./vars
# ./revoke-full vpnclient # 通过revoke-full脚本吊销证书, 吊销vpnclient这个客户端的证书

执行后将看到下面的提示,表示证书已经被吊销

1
2
3
4
5
6
Using configuration from /etc/openvpn/easy-rsa/openssl-1.0.0.cnf
Revoking Certificate 03.
Data Base Updated
Using configuration from /etc/openvpn/easy-rsa/openssl-1.0.0.cnf
client02.crt: C = US, ST = CA, L = SanFrancisco, O = Fort-Funston, OU = MyOrganizationalUnit, CN = client02, name = EasyRSA, emailAddress = me@myhost.mydomain
error 23 at 0 depth lookup:certificate revoked # 出现error 23 表示证书已经被吊销了

需要注意的是到这步还没有彻底完成,此时客户端仍然可以连上。

当通过 revoke-full 脚本吊销客户端的证书后它会在keys(我这里是/etc/openvpn/easy-rsa/keys)目录生成一个crl.pem(吊销证书列表 )文件,所以还需要在openvpn服务器的配置文件 /etc/openvpn/server.conf 添加:

1
crl-verify /etc/openvpn/easy-rsa/keys/crl.pem      # 指定crl.pem文件的路径,必须存在并能够被启动openvpn的用户有权限读取,否则会报cannot read错误

然后重启openvpn服务

1
2
3
# service openvpn restart
Shutting down openvpn: [ OK ]
Starting openvpn: [ OK ]

最后测试被吊销证书的客户端能不能连上vpn服务,如果不能连上说明成功.

此外,还可以通过查看/etc/openvpn/easy-ras/keys/index.txt文件,了解vpn客户端的吊销状态.

  • R 开头的表示reovke,说明是吊销状态,V表示是正常的
  • CN=vpnclient,表示客户端vpnclient已经被吊销
1
2
3
4
# cat /etc/openvpn/easy-rsa/keys/index.txt
V 270929154610Z 01 unknown /C=US/ST=CA/L=SanFrancisco/O=Fort-Funston/OU=MyOrganizationalUnit/CN=vpnserver/name=EasyRSA/emailAddress=me@myhost.mydomain
V 270929154708Z 02 unknown /C=US/ST=CA/L=SanFrancisco/O=Fort-Funston/OU=MyOrganizationalUnit/CN=client01/name=EasyRSA/emailAddress=me@myhost.mydomain
R 271005070515Z 171008142938Z 03 unknown /C=US/ST=CA/L=SanFrancisco/O=Fort-Funston/OU=MyOrganizationalUnit/CN=vpnclient/name=EasyRSA/emailAddress=me@myhost.mydomain

那么问题来了,又想恢复这个被吊销的客户端(vpnclient)呢? 同样可以在openvpn服务器的配置文件/etc/openvpn/server.conf注释或取消:

1
crl-verify /etc/openvpn/easy-rsa/keys/crl.pem      # 注释或取消掉这行

重启openvpn,客户端测试,如果能连上说明成功了,又可以连了

故障与排错


如果不成功,需要从各个方面排查:

  • 检查openvpn服务器端口和进程是否正常
  • 检查tun0接口和路由表是否正常
  • 检查证书的路径是否能够正常访问
  • 查看openvpn服务器日志(重点)
  • 检查防火墙是否做了限制,是否放通了openvpn的ip或端口
  • 使用tcpdump一节一节的抓包,看包到了那个环节
-------------本文结束感谢您的阅读-------------