参考连接:搭建基于证书认证登录的Open×××服务器

                 用easyrsa3来制作证书

                Open×××项目组

推荐阅读:openvpn服务器&客户端配置

                 Open×××2.4.3 安装部署文档(实战)

                 Open×××的配置和使用

                 Open×××常见错误

                 利open×××自带的http-proxy突破防火墙的封锁

                

一、Open×××简介

    Open××× 是一个基于 OpenSSL 库的应用层 ××× 实现。和传统 ××× 相比,它的优点是简单易用。

    Open×××允许参与建立×××的单点使用共享金钥,电子证书,或者用户名/密码来进行身份验证。它大量使用了OpenSSL加密库中的SSLv3/TLSv1 协议函式库。Open×××能在Solaris、Linux、OpenBSD、FreeBSD、NetBSD、Mac OS X与Windows 2000/XP/Vista上运行,并包含了许多安全性的功能。它并不是一个基于Web的×××软件,也不与IPsec及其他×××软件包兼容。

    Open×××2.0后引入了用户名/口令组合的身份验证方式,它可以省略客户端证书,但是仍有一份服务器证书需要被用作加密。 Open×××所有的通信都基于一个单一的IP端口, 默认且推荐使用UDP协议通讯,同时TCP也被支持。Open×××连接能通过大多数的代理服务器,并且能够在NAT的环境中很好地工作。服务端具有向客 户端“推送”某些网络配置信息的功能,这些信息包括:IP地址、路由设置等。Open×××提供了两种虚拟网络接口:通用Tun/Tap驱动,通过它们, 可以建立三层IP隧道,或者虚拟二层以太网,后者可以传送任何类型的二层以太网络数据。传送的数据可通过LZO算法压缩。在选择协议时候,需要注意2个加密隧道之间的网络状况,如有高延迟或者丢包较多的情况下,请选择TCP协议作为底层协议,UDP协议由于存在无连接和重传机制,导致要隧道上层的协议进行重传,效率非常低下。


二、Open×××的安装

    

    Open×××服务器

       内网地址:10.124.151.251

       外网地址:vpn.apicloud.com

        vpn网段:10.124.163.0/24

        系统环境:Centos6.9

    本地客户端

       网段:192.168.0.0

       本机IP:192.168.13.5


搭建基于证书认证登录的OpenVPN2.4.6服务器部署_openvpn


    1. 安装前准备工作:

setenforce 0 #关闭SELinux
yum install epel-release-6-8.noarch -y #安装epel第三方源
sysctl -w net.ipv4.ip_forward=1 #开启服务器端路由转发功能

    2. 配置防火墙iptables:

#开通openvpn监听端口对外开放
-A INPUT -p udp -m multiport --dports 1194 -j ACCEPT
#设置NAT转发,保证×××地址池可路由出外网(二选一,第一个是按照本地监听地址配置,第二个是按照本地网卡名称配置)
-A POSTROUTING -s 10.124.163.0/24 -j SNAT --to-source 10.124.151.251 
#-A POSTROUTING -s 10.124.163.0/24 -o eth0 -j MASQUERADE

    3. 使用yum安装openvpn:

yum install openvpn openvpn-devel -y #这里使用yum最新版2.4.6

    4. 查看yum安装openvpn具体安装的文件列表

rpm -ql openvpn

/etc/openvpn
/etc/rc.d/init.d/openvpn
/usr/lib64/openvpn
/usr/lib64/openvpn/plugin
/usr/lib64/openvpn/plugin/lib
/usr/lib64/openvpn/plugin/lib/openvpn-auth-pam.so
/usr/lib64/openvpn/plugin/lib/openvpn-down-root.so
/usr/lib64/openvpn/plugins
/usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so
/usr/lib64/openvpn/plugins/openvpn-plugin-down-root.so
/usr/sbin/openvpn
/usr/share/doc/openvpn-2.4.6
/usr/share/doc/openvpn-2.4.6/AUTHORS
/usr/share/doc/openvpn-2.4.6/COPYING
/usr/share/doc/openvpn-2.4.6/COPYRIGHT.GPL
/usr/share/doc/openvpn-2.4.6/ChangeLog
/usr/share/doc/openvpn-2.4.6/Changes.rst
/usr/share/doc/openvpn-2.4.6/README
/usr/share/doc/openvpn-2.4.6/README.auth-pam
/usr/share/doc/openvpn-2.4.6/README.down-root
/usr/share/doc/openvpn-2.4.6/contrib
/usr/share/doc/openvpn-2.4.6/contrib/OCSP_check
/usr/share/doc/openvpn-2.4.6/contrib/OCSP_check/OCSP_check.sh
/usr/share/doc/openvpn-2.4.6/contrib/README
/usr/share/doc/openvpn-2.4.6/contrib/openvpn-fwmarkroute-1.00
/usr/share/doc/openvpn-2.4.6/contrib/openvpn-fwmarkroute-1.00/README
/usr/share/doc/openvpn-2.4.6/contrib/openvpn-fwmarkroute-1.00/fwmarkroute.down
/usr/share/doc/openvpn-2.4.6/contrib/openvpn-fwmarkroute-1.00/fwmarkroute.up
/usr/share/doc/openvpn-2.4.6/contrib/pull-resolv-conf
/usr/share/doc/openvpn-2.4.6/contrib/pull-resolv-conf/client.down
/usr/share/doc/openvpn-2.4.6/contrib/pull-resolv-conf/client.up
/usr/share/doc/openvpn-2.4.6/management-notes.txt
/usr/share/doc/openvpn-2.4.6/sample
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/README
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/client.conf
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/firewall.sh
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/home.up
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/loopback-client
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/loopback-server
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/office.up
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/openvpn-shutdown.sh
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/openvpn-startup.sh
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/roadwarrior-client.conf
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/roadwarrior-server.conf
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/server.conf
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/static-home.conf
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/static-office.conf
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/tls-home.conf
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/tls-office.conf
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/xinetd-client-config
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/xinetd-server-config
/usr/share/doc/openvpn-2.4.6/sample/sample-scripts
/usr/share/doc/openvpn-2.4.6/sample/sample-scripts/auth-pam.pl
/usr/share/doc/openvpn-2.4.6/sample/sample-scripts/bridge-start
/usr/share/doc/openvpn-2.4.6/sample/sample-scripts/bridge-stop
/usr/share/doc/openvpn-2.4.6/sample/sample-scripts/ucn.pl
/usr/share/doc/openvpn-2.4.6/sample/sample-scripts/verify-cn
/usr/share/doc/openvpn-2.4.6/sample/sample-windows
/usr/share/doc/openvpn-2.4.6/sample/sample-windows/sample.ovpn
/usr/share/man/man8/openvpn.8.gz
/var/lib/openvpn
/var/run/openvpn

其中:

/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/server.conf   #服务端配置文件模板
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/client.conf   #Linux平台客户端配置模板
/usr/share/doc/openvpn-2.4.6/sample/sample-windows/sample.ovpn        #Windows平台客户端配置模板

下面两行是运行在预共享的静态密钥下的示例配置文件:

/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/static-home.conf
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/static-office.conf

下面两行是运行在SSL/TLS模式下的示例配置文件:

/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/tls-home.conf
/usr/share/doc/openvpn-2.4.6/sample/sample-config-files/tls-office.conf

三、Open×××的配置    

    1. 首先把主要配置文件复制到/etc/openvpn:

cp /usr/share/doc/openvpn-2.4.6/sample/sample-config-files/server.conf /etc/openvpn
# grep -Ev "^$|^[#;]" /etc/openvpn/server.conf 

port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key  # This file should be kept secret
dh dh2048.pem
server 10.124.163.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 10.0.0.0 255.0.0.0"
push "dhcp-option DNS 223.5.5.5"
push "dhcp-option DNS 223.6.6.6"
client-to-client
keepalive 10 120
tls-auth ta.key 0 # This file is secret
cipher AES-256-CBC
comp-lzo
user nobody
group nobody
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log         /var/log/openvpn/openvpn.log
log-append  /var/log/openvpn/openvpn.log
verb 3
explicit-exit-notify 1

附注:

配置文件参数解析

注:可按照默认模板配置,本例为自定义配置文件,";"还有"#"开头的是注释
--------------------------
# 设置监听IP,默认是监听所有IP
;local a.b.c.d
# 设置监听端口,必须要对应的在防火墙里面打开
port 1194
# 设置用TCP还是UDP协议?(用UDP会比较快些)
;proto tcp
proto tcp
# 设置创建tun的路由IP通道,还是创建tap的以太网通道路,由于IP容易控制,所以推荐使用tun;但如果IPX等必须使用第二层才能通过的通讯,则可以用tap方式,tap也就是以太网桥接
;dev tap
dev tun
# Windows服务端需要给网卡一个名称,linux不需要
;dev-node MyTap
# 这里是重点,必须指定SSL/TLS root certificate (ca),certificate(cert), and private key (key),ca文件是服务端和客户端都必须使用的,但不需要ca.key,服务端和客户端指定各自的.crt和.key,请注意路径,可以使用以配置文件开始为根的相对路径,也可以使用绝对路径,请小心存放.key密钥文件
ca /usr/share/doc/openvpn-2.3.7/sample/sample-keys/ca.crt
cert /usr/share/doc/openvpn-2.3.7/sample/sample-keys/server.crt
key /usr/share/doc/openvpn-2.3.7/sample/sample-keys/server.key
# 指定Diffie hellman parameters.
dh /usr/share/doc/openvpn-2.3.7/sample/sample-keys/dh2048.pem
# 配置服务器模式和×××使用的网段,Open×××会自动提供基于该网段的DHCP服务,但不能和任何一方的局域网段重复,×××服务器将会把10.8.0.1留给自己,其余的分配给×××客户端,每一个客户端都会从10.8.0.1这个IP到达OpenVpn服务端,如果使用dev tap模式,则需要注释掉该指令。
server 10.8.0.0 255.255.255.0
# 维持一个客户端和virtual IP的对应表,以方便客户端重新连接可以获得同样的IP
ifconfig-pool-persist ipp.txt
# 配置为以太网桥模式(dev tap),但需要使用系统的桥接功能,这里不需要使用
;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100
# 为客户端创建对应的路由,以另其通达公司网内部服务器,但记住,公司网内部服务器也需要有可用路由返回到客户端,这里主要填写openvpn所在局域网的网段,我的openvpn所在的局域网是10.0.0.0,如果你的openvpn所在的局域网是其他的网段,下面请填写其他网段,可以填写多个网段。
;push "route 192.168.20.0 255.255.255.0"
push "route 10.0.0.0 255.255.255.0"
# 若客户端希望所有的流量都通过×××传输,则可以使用该语句,其会自动改变客户端的网关为×××服务器,推荐关闭,一旦设置,请小心服务端的DHCP设置问题,如果需要抓取所以连接×××客户端的流量信息,需要开启,这就是网络上面所说的×××。
;push "redirect-gateway def1 bypass-dhcp"   所有数据都通过×××
# 用Open×××的DHCP功能为客户端提供指定的DNS、WINS等
push "dhcp-option DNS 114.114.114.114"
;push "dhcp-option WINS 10.8.0.1"
# 默认客户端之间是不能直接通讯的,除非把下面的语句注释掉
client-to-client
# 如果您希望有相同Common Name的客户端都可以登陆,也可以注释下面的语句,推荐每个客户端都使用不用的Common Name,开启的话,一个证书可以多个客户端连接
;duplicate-cn
# 设置服务端检测的间隔和超时时间
keepalive 10 120
# 使用lzo压缩的通讯,服务端和客户端都必须配置
comp-lzo
# 设置最大用户数
;max-clients 100
# 让Open×××以nobody用户和组来运行(安全)
;user nobody
;group nobody
#持续选项会尽量避免访问某些资源的重新启动可能不可以因为特权的降级。
persist-key
persist-tun
# 输出短日志,每分钟刷新一次,以显示当前的客户端
status /var/log/openvpn/openvpn-status.log
# 缺省日志会记录在系统日志中,但也可以导向到其他地方建议调试的使用先不要设置,调试完成后再定义,只能使用其中的一个,log会每次启动前先清楚日志,log-append会对数据追加
;log /var/log/openvpn/openvpn.log
log-append /var/log/openvpn/openvpn.log
# 设置日志的级别
verb 3

    2. 生成证书

涉及到证书生成,请参考下面的文章:

    使用easyrsa来制作证书

四、Open×××的启动

    1.启动命令

service openvpn {start|stop|restart|condrestart|reload|reopen|status}

    2.日志路径:如果/var/log/openvpn/ 不存在,可能需要创建

mkdir -p /var/log/openvpn/
/var/log/openvpn/
├── openvpn.log  #启动运行日志
└── openvpn-status.log #记录当前哪一个客户端连接的状态

五、客户端的安装

    这里记录Windows客户端的安装和配置

    1. 2.4.6客户端安装包下载地址:

https://softpedia-secure-download.com/dl/c140a1a4e8771e05455151d1ec61e793/5b029341/100090870/software/security/openvpn-install-2.4.6-I601.exe

    2. 安装过程:

    搭建基于证书认证登录的OpenVPN2.4.6服务器部署_openvpn_02  搭建基于证书认证登录的OpenVPN2.4.6服务器部署_vpn_03  

这里只安装客户端和网络,见下图:

搭建基于证书认证登录的OpenVPN2.4.6服务器部署_vpn_04 搭建基于证书认证登录的OpenVPN2.4.6服务器部署_vpn_05 

剩下的步骤默认即可。

    3. 将服务端内ca.crt、client.crt、client.key、client.conf复制到客户端D:\Program Files\Open×××\config下。

D:\Program Files\Open×××>tree /f
卷 软件 的文件夹 PATH 列表
卷序列号为 0000008F 04B4:1271
D:.
│  icon.ico
│  Uninstall.exe
│
├─bin
│      libcrypto-1_1-x64.dll
│      liblzo2-2.dll
│      libpkcs11-helper-1.dll
│      libssl-1_1-x64.dll
│      openssl.exe
│      openvpn-gui.exe
│      openvpn.exe
│      openvpnserv.exe
│
├─config
│      ca.crt
│      client.crt
│      client.key
│      client.ovpn
│      README.txt
│      ta.key
│
├─doc
│      INSTALL-win32.txt
│      license.txt
│      openvpn.8.html
│
├─log
│      README.txt
│
└─sample-config
        client.ovpn
        sample.ovpn
        server.ovpn

    4. 配置文件:

#D:\Program Files\Open×××\config>grep -Ev "^$|^[#;]" client.ovpn

client
dev tun
proto udp
remote vpn.apicloud.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-CBC
comp-lzo
verb 3

    配置文件解析:

# 定义是一个客户端
client
# 定义使用路由IP模式,与服务端一致
;dev tap
dev tun
# 定义Windows下使用的网卡名称,linux不需要
;dev-node MyTap
# 定义使用的协议,与服务端一致
;proto tcp
proto tcp
# 指定服务端地址和端口,可以用多行指定多台服务器实现负载均衡高可用(从上往下尝试)
remote 211.152.x.x 1194
;remote my-server-2 1194
# 若上面配置了多台服务器,让客户端随机连接,以便实现负载均衡
;remote-random
# 解析服务器域名
resolv-retry infinite
# 客户端不需要绑定端口
nobind
# Try to preserve some state across restarts.
persist-key
persist-tun
# 重点,就是指定ca和客户端的证书
ca ca.crt
cert client.crt
key client.key
# 使用lzo压缩,与服务端一致
comp-lzo
# Set log file verbosity.
verb 3

    5. 连接:

搭建基于证书认证登录的OpenVPN2.4.6服务器部署_openvpn_06

搭建基于证书认证登录的OpenVPN2.4.6服务器部署_vpn_07

搭建基于证书认证登录的OpenVPN2.4.6服务器部署_vpn_08


六、客户端IP地址的使用

    在--topology mode选项中,mode有三种取值,即net30、subnet和p2p。

    当运行在--dev tun模式下时,可以通过--topology mode选项来配置虚拟地址的拓扑结构。而对于--dev tap而言,该选项没有任何意义,因为在--dev tap模式下,总是使用子网拓扑如果在服务器端设置了--topology mode选项,那么--server和--server-bridge选项将会很好地自动地把拓扑模式推送到客户端。该选项也可以被手动的推送到客户端,类似于--dev选项,另外,还要求服务器端和客户端必须支持该选项。

1、net30

   Open×××默认的子网掩码是/30,也就是255.255.225.252。在这样的情况下,每组网络四个地址,只有两个地址可以使用,一个给服务端,一个给客户端,另外一个是网络地址,一个是广播地址,这样地址是很浪费的,这是Open××× 2.0的默认模式。

   在Open×××的2.0版本中,Open×××能通过虚拟一个TUN虚拟接口处理多个客户端,要处理这种技术,可以把服务器上看到的PtP连接看作是一个操作系统和Open×××之间的连接,而在Open×××内部还需要为每一个客户端创建另一个PtP。如何所有的O/S在TUN接口上真正的支持PtP连接,那么这将会是的Open×××服务器仅使用一个IP地址,并且一个客户端也使用一个IP地址。

    在OS系统和Open×××之间首先要有一个10.8.0.1<->10.8.0.2的PtP连接。

搭建基于证书认证登录的OpenVPN2.4.6服务器部署_vpn_09   于是Open×××为每一个连接的客户端指定一个/30的子网,第一个可以使用的/30的子网是:

  • 10.8.0.4:网络地址;

  • 10.8.0.5:在Open×××中的“虚拟”IP地址;

  • 10.8.0.6:指定给客户端的IP地址;

  • 10.8.0.7:广播地址。

    然后将路由推到客户端,这样便使所有IP地址为10.8.0.5的流量都必须通过“网关”10.8.0.5才可以出去或者进入。

    由于10.8.0.5仅是Open×××内部的一个虚拟IP地址,它被用作末端路由,对应这个地址,Open×××不会接受ping,而10.8.0.6对于服务器的操作系统来说却是一个真正的IP地址,因此它可以接受ping,我们让客户端连接查看一下。

以此类推,第二个客户端连接分配的IP地址对就是10.8.0.9<->10.8.0.10,从这个IP分配来看,对IP的使用造成的浪费。但是对于Open×××服务器端仅使用一个配置来为所有类型的客户端分配地址来说这是最好的一种方式。

2、subnet

   subnet通过配置TUN接口的本地IP地址和子网掩码来使用一个子网,而不是点对点的拓扑结构,类似于使用--dev tap和以太网桥模式的拓扑结构。这种模式为每个客户端分配单个IP地址。

3、p2p

   p2p模式使用点对点拓扑,仅适用于Windows系统下,现在已经不再赞成使用。

七、遇到的问题

    1. 安装所有步骤配置完成后, 启动服务器, 启动客户端,发现连接失败, 错误如下:

Wed May 23 14:07:08 2018 117.107.209.233:11840 [client-user-test1] Peer Connection Initiated with [AF_INET]117.107.209.233:11840
Wed May 23 14:07:08 2018 MULTI: new connection by client 'client-user-test1' will cause previous active sessions by this client to be dropped.  Remember to use the --duplicate-cn option if you want multiple clients using the same certificate or username to concurrently connect.
Wed May 23 14:07:08 2018 MULTI_sva: pool returned IPv4=10.124.163.6, IPv6=(Not enabled)
Wed May 23 14:07:08 2018 MULTI: Learn: 10.124.163.6 -> client-user-test1/117.107.209.233:11840
Wed May 23 14:07:08 2018 MULTI: primary virtual IP for client-user-test1/117.107.209.233:11840: 10.124.163.6
Wed May 23 14:07:09 2018 client-user-test1/117.107.209.233:11840 PUSH: Received control message: 'PUSH_REQUEST'
Wed May 23 14:07:09 2018 client-user-test1/117.107.209.233:11840 SENT CONTROL [client-user-test1]: 'PUSH_REPLY,route 10.0.0.0 255.0.0.0,dhcp-option DNS 223.5.5.5,dhcp-option DNS 223.6.6.6,route 10.124.163.0 255.255.255.0,topology net30,ping 10,ping-restart 120,ifconfig 10.124.163.6 10.124.163.5,peer-id 0,cipher AES-256-GCM' (status=1)
Wed May 23 14:07:09 2018 client-user-test1/117.107.209.233:11840 Data Channel: using negotiated cipher 'AES-256-GCM'
Wed May 23 14:07:09 2018 client-user-test1/117.107.209.233:11840 Outgoing Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Wed May 23 14:07:09 2018 client-user-test1/117.107.209.233:11840 Incoming Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key

        原因: windows客户端在安装的时候没有安装TAP Virtual Ethernet Adapter。导致客户端openvpn对应的网络连接处于禁用状态。

    2. 在 Linux Open××× 服务端吊销(revoke)客户端证书

1)进入easy-rsa的安装路径。
2)执行 source vars
3)假设吊销的客户端名称为client1 则执行./revoke-full client1
注:这条命令执行完成之后, 会在 keys 目录下面, 生成一个 crl.pem 文件,这个文件中包含了吊销证书的名单。成功注销某个证书之后,可以打开 keys/index.txt 文件,可以看到被注销的证书前面,已标记为R
4)确保服务器配置文件存在 crl-verify选项。
在server.conf 中加入 
 crl-verify crl.pem  //crl.pem 根据实际路径写
5)重启openvpn服务器

    3. 报错:Authenticate/Decrypt packet error: packet HMAC authentication failed

    尝试将服务端和客户端的tls-auth相关配置去掉试试

    4. 报错:

TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)  
TLS Error: TLS handshake failed

    查阅资料,说是网络有可能有问题,路由器没有开nat,或者其它的网络问题。 想来可能是防火墙限制了,是否是防火墙的问题,需要试一下。有两种方式,第一种方式,使用不受限的SSL端口443和TCP协议 。实际遇到的问题是TLS 认证服务器端和客户端配置不一致导致。