OpenVPN的工作原理


在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的连接上从物理网卡发送出去

环境说明

  1. 192.168.0.10外网 10.4.82.10 内网
  2. 系统环境
  3. $ cat /etc/redhat-release
  4. CentOS Linux release 7.7.1908 (Core)
  5. $ uname -r
  6. 3.10.0-1062.9.1.el7.x86_64
  7. 网卡为双网卡
  8. $ ifconfig
  9. eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
  10. inet 192.168.0.11 netmask 255.255.255.0 broadcast 192.168.0.255
  11. inet6 fe80::6b5a:9ab8:1bb:5f8d prefixlen 64 scopeid 0x20
  12. ether 00:0c:29:32:b2:36 txqueuelen 1000 (Ethernet)
  13. RX packets 15104 bytes 16993218 (16.2 MiB)
  14. RX errors 0 dropped 0 overruns 0 frame 0
  15. TX packets 8661 bytes 889872 (869.0 KiB)
  16. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  17. eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
  18. inet 10.4.82.11 netmask 255.255.255.0 broadcast 10.4.82.255
  19. inet6 fe80::20c:29ff:fe32:b240 prefixlen 64 scopeid 0x20
  20. ether 00:0c:29:32:b2:40 txqueuelen 1000 (Ethernet)
  21. RX packets 202 bytes 18735 (18.2 KiB)
  22. RX errors 0 dropped 0 overruns 0 frame 0
  23. TX packets 8 bytes 656 (656.0 B)
  24. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

制作证书

制作服务端CA证书


首先我们先使用easy-rsa制作openVPN证书,下载并解压easy-rsa软件包

  1. $ mkdir /data/tools -p
  2. $ wget -P /data/tools http://down.i4t.com/easy-rsa.zip
  3. $ unzip -d /usr/local /data/tools/easy-rsa.zip

在开始制作CA证书之前,我们还需要编辑vars文件,修改如下相关选项

  1. $ cd /usr/local/easy-rsa-old-master/easy-rsa/2.0/
  2. $ vim vars
  3. export KEY_COUNTRY="cn"
  4. export KEY_PROVINCE="BJ"
  5. export KEY_CITY="BJ"
  6. export KEY_ORG="abcdocker"
  7. export KEY_EMAIL="cyh@i4t.com"
  8. export KEY_CN=abc # 这里填写证书文件名称,后续要用到
  9. export KEY_NAME=abc # 这里填写证书文件名称,后续要用到
  10. export KEY_OU=abc # 这里填写证书文件名称,后续要用到
  11. # 行数大约67行开始,主要是修改默认的注册信息,比如注册公司、公司名称、部门、国家城市等

注意:以上内容,我们也可以使用系统默认的,也就是说不进行修改也是可以使用的

然后使用使环境变量生效

  1. # 初始化环境
  2. $ source vars
  3. $ ./clean-all
  4. # 注意:执行clean-all命令会在当前目录下创建一个名词为keys的目录

接下来开始正式制作CA证书,命令如下:

  1. $ ./build-ca
  2. # 生成根证书ca.crt和根密钥ca.key
  3. # 因为在vars中填写了证书的基本信息,所以这里一路回车即可

这时我们可以查看keys目录,已经帮我们生成ca.crtca.key两个文件,其中ca.crt就是我们的证书文件

  1. $ ls keys
  2. ca.crt ca.key index.txt serial


制作Server端证书

为服务端生成证书和密钥

  1. # 一直回车,按2个y
  2. $ ./build-key-server server
  3. ....
  4. An optional company name []:
  5. Using configuration from /usr/local/easy-rsa-old-master/easy-rsa/2.0/openssl-1.0.0.cnf
  6. Check that the request matches the signature
  7. Signature ok
  8. The Subject's Distinguished Name is as follows
  9. countryName :PRINTABLE:'cn'
  10. stateOrProvinceName :PRINTABLE:'BJ'
  11. localityName :PRINTABLE:'BJ'
  12. organizationName :PRINTABLE:'abcdocker'
  13. organizationalUnitName:PRINTABLE:'abc'
  14. commonName :PRINTABLE:'abc'
  15. name :PRINTABLE:'abc'
  16. emailAddress :IA5STRING:'cyh@i4t.com'
  17. Certificate is to be certified until Jan 31 14:01:35 2030 GMT (3650 days)
  18. Sign the certificate? [y/n]:y
  19. 1 out of 1 certificate requests certified, commit? [y/n]y
  20. Write out database with 1 new entries
  21. Data Base Updated
  22. # 这里的server就是我们server端的证书

查看新生成的证书

  1. $ ls keys
  2. 01.pem abc.key index.txt serial
  3. server.crt ca.crt index.txt.attr serial.old
  4. server.csr ca.key index.txt.old


这里我们已经生成了server.crtserver.keyserver.csr三个文件,其中server.crtserver.key两个文件是我们需要使用的

制作Client端证书

这里我们创建2个用户,分别为client1和client2

  1. # 每一个登陆的VPN客户端需要有一个证书,每个证书在同一时刻只能供一个客户端连接,下面建立2份
  2. # 为客户端生成证书和密钥(一路按回车,直到提示需要输入y/n时,输入y再按回车,一共两次)
  3. $ ./build-key client1
  4. $ ./build-key client2

每一个登陆的VPN客户端需要有一个证书,每个证书在同一时刻只可以一个客户端连接(可以修改配置文件)

生成加密交换时的Diffie-Hellman文件

  1. $ ./build-dh
  2. # 创建迪菲·赫尔曼密钥,会生成dh2048.pem文件(生成过程比较慢,在此期间不要去中断它)

证书生成完毕

  1. $ ll keys
  2. total 84
  3. -rw-r--r-- 1 root root 7997 Feb 3 09:01 01.pem
  4. -rw-r--r-- 1 root root 7880 Feb 3 09:09 02.pem
  5. -rw-r--r-- 1 root root 7997 Feb 3 09:01 abc.crt
  6. -rw-r--r-- 1 root root 1765 Feb 3 09:01 abc.csr
  7. -rw------- 1 root root 3272 Feb 3 09:01 abc.key
  8. -rw-r--r-- 1 root root 2293 Feb 3 09:01 ca.crt
  9. -rw------- 1 root root 3272 Feb 3 09:01 ca.key
  10. -rw-r--r-- 1 root root 424 Feb 3 09:06 dh2048.pem
  11. -rw-r--r-- 1 root root 211 Feb 3 09:09 index.txt
  12. -rw-r--r-- 1 root root 21 Feb 3 09:09 index.txt.attr
  13. -rw-r--r-- 1 root root 21 Feb 3 09:01 index.txt.attr.old
  14. -rw-r--r-- 1 root root 105 Feb 3 09:01 index.txt.old
  15. -rw-r--r-- 1 root root 3 Feb 3 09:09 serial
  16. -rw-r--r-- 1 root root 3 Feb 3 09:01 serial.old
  17. -rw-r--r-- 1 root root 7880 Feb 3 09:09 test.crt
  18. -rw-r--r-- 1 root root 1765 Feb 3 09:09 test.csr
  19. -rw------- 1 root root 3272 Feb 3 09:09 test.key

其中包含了一个test用户和abc用户的证书

其中只有.crt和.key文件是我们需要使用的

安装OpenVPN

安装vpn的方法有2种,一种是编译安装,另外一种是使用yum安装, 这两个我们选择一个就可以.

编译安装

  1. # 安装依赖包
  2. $ curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
  3. $ wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
  4. $ yum makecache
  5. $ yum install -y lzo lzo-devel openssl openssl-devel pam pam-devel net-tools git lz4-devel
  6. # 下载openVPN软件包
  7. $ wget -P /data/tools http://down.i4t.com/openvpn-2.4.7.tar.gz
  8. $ cd /data/tools
  9. # 安装openVPN
  10. $ tar zxf openvpn-2.4.7.tar.gz
  11. $ cd openvpn-2.4.7
  12. $ ./configure --prefix=/usr/local/openvpn-2.4.7
  13. $ make
  14. $ make install
  15. # 创建软连接
  16. $ ln -s /usr/local/openvpn-2.4.7 /usr/local/openvpn


yum安装

OpenVPN需要安装EPEL

  1. $ curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
  2. $ yum clean all && yum makecache

yum 安装openVPN

  1. $ yum install -y openvpn
  2. # 安装后配置文件在 /etc/openvpn
  3. # 安装后配置示例文件在 /data/tools/openvpn-2.4.7/sample/

配置服务端

创建openVPN文件目录和证书目录

  1. # openVPN配置文件目录,yum安装默认存在
  2. $ mkdir /etc/openvpn
  3. # openvpn证书目录
  4. $ mkdir /etc/openvpn/keys

生成tls-auth key并将其拷贝到证书目录中(防DDos攻击、UDP淹没等恶意攻击)

  1. # 编译安装执行此句
  2. $ /usr/local/openvpn/sbin/openvpn --genkey --secret ta.key
  3. # yum安装执行此句
  4. openvpn --genkey --secret ta.key
  5. # 将本地的ta.key移动到openVPN证书目录
  6. $ mv ./ta.key /etc/openvpn/keys/

将上面生成的CA证书和服务端证书拷贝到证书目录中

  1. $ cp /usr/local/easy-rsa-old-master/easy-rsa/2.0/keys/{server.crt,server.key,ca.crt,dh2048.pem} /etc/openvpn/keys/
  2. $ ll /etc/openvpn/keys/
  3. total 24
  4. -rw-r--r-- 1 root root 2342 Feb 3 12:48 ca.crt
  5. -rw-r--r-- 1 root root 424 Feb 3 12:48 dh2048.pem
  6. -rw-r--r-- 1 root root 8089 Feb 3 12:48 server.crt
  7. -rw------- 1 root root 3272 Feb 3 12:48 server.key
  8. -rw------- 1 root root 636 Feb 3 12:47 ta.key
  9. # abc和test为我们client端用户的证书


拷贝OpenVPN配置文件

  1. # 编译安装
  2. cp /data/tools/openvpn-2.4.7/sample/sample-config-files/server.conf /etc/openvpn/
  3. # yum安装
  4. cp /usr/share/doc/openvpn-2.4.7/sample/sample-config-files/server.conf /etc/openvpn/

配置服务端的配置文件

  1. $ cat /etc/openvpn/server.conf
  2. port 1194 #openVPN端口
  3. proto tcp #tcp连接
  4. dev tun #生成tun0虚拟网卡
  5. ca keys/ca.crt #相关证书配置路径(可以修改为全路径/etc/openvpn/keys)
  6. cert keys/server.crt
  7. key keys/server.key # This file should be kept secret
  8. dh keys/dh2048.pem
  9. server 10.4.82.0 255.255.255.0 #默认虚拟局域网网段,不要和实际的局域网冲突就可以
  10. ifconfig-pool-persist ipp.txt
  11. push "route 10.4.82.0 255.255.255.0" #可以通过iptables进行路由的转发
  12. client-to-client #如果客户端都是用一个证书和密钥连接VPN,需要打开这个选项
  13. duplicate-cn
  14. keepalive 10 120
  15. tls-auth keys/ta.key 0 # This file is secret
  16. comp-lzo
  17. persist-key
  18. persist-tun
  19. status openvpn-status.log #状态日志路径
  20. log-append openvpn.log #运行日志
  21. verb 3 #调试信息级别
  22. # 如果需要接入ldap,需要在server.conf下添加如下2行
  23. plugin /usr/lib64/openvpn/plugin/lib/openvpn-auth-ldap.so "/etc/openvpn/auth/ldap.conf cn=%u"
  24. client-cert-not-required
  25. # 如何环境和我相同,可以直接cp我的配置文件

开启内核路由转发功能

  1. echo "net.ipv4.ip_forward = 1" >>/etc/sysctl.conf
  2. sysctl -p

如果有iptables可以开启iptables策略

  1. $ iptables -P FORWARD ACCEPT
  2. $ iptables -I INPUT -p tcp --dport 1194 -m comment --comment "openvpn" -j ACCEPT
  3. $ iptables -t nat -A POSTROUTING -s 10.4.82.0/24 -j MASQUERADE

启动openvpn服务

  1. $ cd /etc/openvpn/
  2. # 编译安装启动
  3. $ /usr/local/openvpn/sbin/openvpn --daemon --config /etc/openvpn/server.conf
  4. # yum安装启动
  5. $ openvpn --daemon --config /etc/openvpn/server.conf

检查服务是否启动

  1. $ netstat -lntup|grep 11194
  2. tcp 0 0 0.0.0.0:1194 0.0.0.0:* LISTEN 48091/openvpn

设置开机启动

  1. # 编译安装
  2. $ echo "/usr/local/openvpn/sbin/openvpn --daemon --config /etc/openvpn/server.conf > /dev/null 2>&1 &" >> /etc/rc.local
  3. # yum安装
  4. $ echo "openvpn --daemon --config /etc/openvpn/server.conf > /dev/null 2>&1 &" >> /etc/rc.local


配置客户端

无论我们是在Windows还是Linux OS上Client端的配置,都需要将Client证书CA证书以及Client配置文件下载下来。
现在我们需要先配置一下client.conf(也可以下载后在本地电脑上配置)。

  1. $ cp /data/tools/openvpn-2.4.7/sample/sample-config-files/client.conf /root/
  2. # 修改如下,并将client.conf修改为client.ovpn
  3. $ cat /root/client.conf
  4. client
  5. dev tun
  6. proto tcp
  7. remote 192.168.0.10 1194 #openvpn服务器的外网IP和端口(可以写多个做到高可用)
  8. resolv-retry infinite
  9. nobind
  10. persist-key
  11. persist-tun
  12. ca ca.crt
  13. cert client1.crt #用户的证书
  14. key client1.key
  15. tls-auth ta.key 1
  16. cipher AES-256-CBC
  17. comp-lzo
  18. verb 3
  19. #比较重点的就是修改remote 地址,这里的地址为server
  20. cert key,我们这里使用用户的证书,所以证书也应当修改为client1.crtclient1.key
  21. tls-auth 因为使用加密协议,所以ta.key也需要下载下来

修改后缀并导出

  1. $ mv client.conf client.ovpn
  2. $ sz client.ovpn
  3. #同时还需要导出几个证书
  4. $ mv client.conf client.ovpn
  5. $ sz /root/client.ovpn
  6. $ sz /etc/openvpn/keys/ca.crt
  7. $ sz /etc/openvpn/keys/ta.key
  8. $ sz /usr/local/easy-rsa-old-master/easy-rsa/2.0/keys/client1.crt
  9. $ sz /usr/local/easy-rsa-old-master/easy-rsa/2.0/keys/client1.key

添加用户

以后我们如果想添加用户只需要到cd /usr/local/easy-rsa-old-master/easy-rsa/2.0目录下执行./build-key 用户名,在将keys目录下生成的用户名.crt.key导出,修改一下client.ovpn用户key名称即可

连接进行测试

Windows

客户端需要证书如下
image.png
Windows客户端下载
http://down.i4t.com/openvpn-install-2.4.7-I606-Win10.exe
http://down.i4t.com/openvpn-install-2.4.7-I606-Win7.exe
打开浏览器即可下载
安装步骤,直接C盘就可以了,文件很小~
image.png
疯狂下一步即可
image.png
安装完成后
image.png
接下来我们需要替换一下证书
点击桌面的logo,右击属性
image.png
点击打开文件位置
image.png
点击上方OpenVPN从新选择目录
image.png
选择config目录
image.png
将config目录下文件全部删除
image.png
然后将我们导出的5个证书复制过去
image.png
其中client1.*为client1用户的证书
现在我们进行启动openvpn客户端,进行连接
双击桌面OpenVPN
右击图标,选择连接
image.png
image.png
image.png
这里可以看到已经连接成功
image.png


Mac

复制链接到浏览器,下载软件包
http://down.i4t.com/Tunnelblick_3.8.1_build_5400.dmg
我们直接点开client.ovpn就可以自动链接
image.png
image.png
成功后会有下面的流量图
image.png
配置文件打开方式
image.png
这时候网络已经通了
image.png

配置参考地址

安装OpenVPN
https://i4t.com/4481.html

固定客户端IP
http://dnaeon.github.io/static-ip-addresses-in-openvpn/

http://dnaeon.github.io/installing-openvpn-on-debian-gnu-linux/

https://my.oschina.net/u/4303561/blog/3828035

https://www.bbsmax.com/A/A7zgR34Vd4/

配置文件详解
https://www.ilanni.com/?p=9847
http://blog.sina.com.cn/s/blog_946ad36f0102w9e3.html

easy-rsa3使用教程
https://blog.csdn.net/iteye_14218/article/details/82653391?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link