OpenVPN

image-20240922110244149

环境准备

机器 IP 应用
web01 10.0.0.7 OpenVPN 服务端
web02 10.0.0.8 OpenVPN 客户端
db01 172.16.1.51 连接的机器
windows OpenVPN 客户端

服务端准备

#### 安装  环境搭建
yum install easy-rsa openvpn

mkdir -p   /opt/easy-rsa
cp -a /usr/share/easy-rsa/3.0.8/*   /opt/easy-rsa/
cp /usr/share/doc/easy-rsa-3.0.8/vars.example   /opt/easy-rsa/vars

cat >/opt/easy-rsa/vars << 'EOF'
if [ -z "$EASYRSA_CALLER" ]; then
	echo "You appear to be sourcing an Easy-RSA 'vars' file." >&2
     echo "This is no longer necessary and is disallowed. See the section called" >&2
     echo "'How to use this file' near the top comments for more details." >&2
     return 1
fi
set_var EASYRSA_DN "cn_only"
set_var EASYRSA_REQ_COUNTRY "CN"
set_var EASYRSA_REQ_PROVINCE "Beijing"
set_var EASYRSA_REQ_CITY "Beijing"
set_var EASYRSA_REQ_ORG "linux"
set_var EASYRSA_REQ_EMAIL "123qq.com"
set_var EASYRSA_NS_SUPPORT "yes"
EOF

创建证书

#### 创建证书
创建CA证书
server密钥
client密钥
dh-pem算法文件
OpenVPN服务端配置文件


### 速度版
创建vars文件(伪装ca机构),创建ca证书 
	./easyrsa init-pki
	./easyrsa build-ca

创建server证书和私钥
	./easyrsa gen-req server nopass
	./easyrsa sign server server
创建client证书和私钥
	./easyrsa gen-req client nopass
	./easyrsa sign client client
dh.pem 文件
	./easyrsa gen-dh
创建ca证书
##1.初始化,在当前目录创建PKI目录,用于存储证书
[root@web01 easy-rsa]# ./easyrsa init-pki

Note: using Easy-RSA configuration from: /opt/easy-rsa/vars

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /opt/easy-rsa/pki


##2.创建根证书,会提示设置密码,用于ca对之后生成的server和client证书签名时使用,其他可默认  
## 温馨提示: 加上密码
[root@web01 easy-rsa]# ./easyrsa build-ca

Note: using Easy-RSA configuration from: /opt/easy-rsa/vars
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017

Enter New CA Key Passphrase: 1234 ### (密码4-1023位) 以后要用记住
Re-Enter New CA Key Passphrase: 1234 ###
Generating RSA private key, 2048 bit long modulus
...............................................................................................................................................................................................................................................................+++
.....+++
e is 65537 (0x10001)
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.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:lzd.cn  ### (填写域名即可)

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/opt/easy-rsa/pki/ca.crt     ## ca证书的位置
创建server证书
#01 创建请求文件及服务端私钥,nopass表示不加密私钥文件,其他可默认
[root@web01 easy-rsa]# ./easyrsa gen-req server nopass

Note: using Easy-RSA configuration from: /opt/easy-rsa/vars
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating a 2048 bit RSA private key
.................................................................+++
.......................................+++
writing new private key to '/opt/easy-rsa/pki/easy-rsa-7669.lVCqXD/tmp.yAv09s'
-----
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.
-----
Common Name (eg: your user, host, or server name) [server]:

Keypair and certificate request completed. Your files are:
req: /opt/easy-rsa/pki/reqs/server.req              
     #server.req 用于 创建证书(证书资料)
key: /opt/easy-rsa/pki/private/server.key          
      #server私钥文件

#02 给server端证书签名,首先是对一些信息的确认,可以输入yes,然后创建ca根证书时设置的密码
[root@web01 easy-rsa]#  ./easyrsa sign server server

Note: using Easy-RSA configuration from: /opt/easy-rsa/vars
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017


You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 825 days:

subject=
    commonName                = server


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes  ## 输入yes
Using configuration from /opt/easy-rsa/pki/easy-rsa-7704.oC8LXF/tmp.1ymBQ7
Enter pass phrase for /opt/easy-rsa/pki/private/ca.key: ## 输入ca密码
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'server'
Certificate is to be certified until Dec 26 02:06:08 2026 GMT (825 days)

Write out database with 1 new entries
Data Base Updated
### server证书
Certificate created at: /opt/easy-rsa/pki/issued/server.crt
创建client证书
#01.创建client端证书和私钥文件,nopass表示不加密私钥文件,其他可默认
[root@web01 easy-rsa]# ./easyrsa gen-req client nopass

Note: using Easy-RSA configuration from: /opt/easy-rsa/vars
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating a 2048 bit RSA private key
.........................................................+++
......................................................+++
writing new private key to '/opt/easy-rsa/pki/easy-rsa-7781.OQES7P/tmp.ZX2snu'
-----
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.
-----
Common Name (eg: your user, host, or server name) [client]:

Keypair and certificate request completed. Your files are:
## 创建client证书的依赖
req: /opt/easy-rsa/pki/reqs/client.req
## 创建的client密钥
key: /opt/easy-rsa/pki/private/client.key


#02.给client端证书签名,首先是对一些信息的确认,可以输入yes,然后创建ca根证书时设置的密码
[root@web01 easy-rsa]# ./easyrsa sign client client

Note: using Easy-RSA configuration from: /opt/easy-rsa/vars
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017


You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a client certificate for 825 days:

subject=
    commonName                = client


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes ## 输入yes
Using configuration from /opt/easy-rsa/pki/easy-rsa-7808.f1OnM1/tmp.3ndWIe
Enter pass phrase for /opt/easy-rsa/pki/private/ca.key: 1234 ## 输入ca密码
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'client'
Certificate is to be certified until Dec 26 02:08:01 2026 GMT (825 days)

Write out database with 1 new entries
Data Base Updated
## client证书
Certificate created at: /opt/easy-rsa/pki/issued/client.crt
创建dh-pem算法文件和
1.# 创建Diffie-Hellman文件,秘钥交换时的Diffie-Hellman算法
[root@web01 easy-rsa]#  ./easyrsa gen-dh

Note: using Easy-RSA configuration from: /opt/easy-rsa/vars
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
..............................................+....................................................................................................+.....................................................................................................................................................................++*++*
### 算法文件
DH parameters of size 2048 created at /opt/easy-rsa/pki/dh.pem
目录汇总
[root@web01 easy-rsa]# tree pki
pki
├── ca.crt     #### ca证书
├── certs_by_serial
│   ├── 42A8B9DD47F4430FC81BC634B2C82C98.pem
│   └── 5223A6A7BD259586EEEFE3FDE20453E8.pem
├── dh.pem     #### 算法文件
├── index.txt
├── index.txt.attr
├── index.txt.attr.old
├── index.txt.old
├── issued
│   ├── client.crt  #### client 证书
│   └── server.crt  #### server 证书
├── openssl-easyrsa.cnf
├── private
│   ├── ca.key      #### ca密钥
│   ├── client.key  #### client密钥
│   └── server.key  #### server密钥
├── renewed
│   ├── certs_by_serial
│   ├── private_by_serial
│   └── reqs_by_serial
├── reqs
│   ├── client.req
│   └── server.req
├── revoked
│   ├── certs_by_serial
│   ├── private_by_serial
│   └── reqs_by_serial
├── safessl-easyrsa.cnf
├── serial
└── serial.old

image-20240922101514056

#### 服务端配置文件

server.conf 
port 1194   # #端口
proto udp   # #协议
dev tun     # #采用路由隧道模式tun
ca ca.crt   # # ca证书 /etc/openvpn/ca.crt
dh dh.pem	# # 算法证书
cert server/server.crt  # # server证书 /etc/openvpn/server/server.crt
key server/server.key   # # server密钥
server 10.8.0.0 255.255.255.0  # #给客户端分配地址池(ip地址范围),注意:不能和VPN服务器内网网段有相同
push "route 172.16.1.0 255.255.255.0"   #客户端连接后,推送给客户端的路由规则
									 #客户端想访问 172.16.1.0/24 网段联系openvpn服务端
									 	##ifconfig-pool-persist ipp.txt    
										#地址池记录文件位置 未来让openvpn 客户端固定ip地址使用的
keepalive 10 120 			#存活时间,10秒ping一次,120 如未收到响应则视为断线
max-clients 100				##最多允许100个客户端连接
status /var/log/openvpn-status.log   #  #日志记录位置openvpn状态
log /var/log/openvpn.log    ## #openvpn日志记录位置
verb 3                      ## 级别 最多11(debug)
client-to-client            ## #客户端与客户端之间支持通信
persist-key    #通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys 对私钥进行缓存.
persist-tun  #检测超时后,重新启动VPN,一直保持tun是linkup的。否则网络会先linkdown然后再linkup
duplicate-cn #客户端密钥(证书和私钥)是否可以重复
port 1194
proto udp
dev tun
ca ca.crt
dh dh.pem
cert server/server.crt
key server/server.key
server 10.8.0.0 255.255.255.0
push "route 172.16.1.0 255.255.255.0"
keepalive 10 120
max-clients 100
status /var/log/openvpn-status.log
log /var/log/openvpn.log
verb 3
client-to-client
persist-key
persist-tun
duplicate-cn
## 根据配置文件放入
[root@web01 easy-rsa]# cd /etc/openvpn/server/
[root@web01 server]# vim server.conf
[root@web01 server]# cd /opt/easy-rsa/pki/
[root@web01 pki]# \cp ca.crt /etc/openvpn/
[root@web01 pki]# \cp dh.pem  /etc/openvpn/
[root@web01 pki]# \cp  issued/server.crt private/server.key /etc/openvpn/server/


### 检测目录结构
[root@web01 openvpn]# tree
.
├── ca.crt
├── client
├── dh.pem
└── server
    ├── server.conf
    ├── server.crt
    └── server.key
#### 编辑启动文件
[root@web01 openvpn]# vim /usr/lib/systemd/system/[email protected]
[Unit]
Description=OpenVPN Robust And Highly Flexible Tunneling Application On %I
After=network.target

[Service]
Type=notify
PrivateTmp=true
ExecStart=/usr/sbin/openvpn --cd /etc/openvpn/ --config %i/%i.conf  ## 编辑这一行  %i/%i

[Install]
WantedBy=multi-user.target


### 启动 检查端口
[root@web01 openvpn]# systemctl start openvpn@server
[root@web01 openvpn]# netstat -lntup    
udp        0      0 0.0.0.0:1194            0.0.0.0:*                           8005/openvpn         

windows连接vpn

### 安装vpn

image-20240921223923252

##### 配置文件所需
C:\Program Files\OpenVPN\config
linux.cn #目录
   ca.crt           #ca证书
   client.crt       #客户端证书
   client.key       #客户端私钥
   client.ovpn      #客户端配置文件 类似于client.conf
##### 下载移动配置文件
[root@web01 easy-rsa]# cd /opt/easy-rsa/pki/
[root@web01 pki]# sz ca.crt 
[root@web01 pki]# sz issued/client.crt 
[root@web01 pki]# sz private/client.key 
#client.ovpn  
[root@openvpn-client ~]# cat /etc/openvpn/clinet.ovpn
client                  #指定当前VPN是客户端
dev tun                 #使用tun隧道传输协议
proto udp               #使用udp协议传输数据
remote 10.0.0.5 1194   #openvpn服务器IP地址端口号
resolv-retry infinite   #断线自动重新连接,在网络不稳定的情况下非常有用
nobind                  #不绑定本地特定的端口号
ca ca.crt               #指定CA证书的文件路径
cert client.crt         #指定当前客户端的证书文件路径
key client.key          #指定当前客户端的私钥文件路径
verb 3                  #指定日志文件的记录详细级别,可选0-9,等级越高日志内容越详细
persist-key             #通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys

client 
dev tun 
proto udp 
remote 10.0.0.5 1194 
resolv-retry infinite 
nobind 
ca ca.crt 
cert client.crt 
key client.key 
verb 3 
persist-key 

image-20240922103835314

## 开启测试
绿色就成功了

image-20240922104007550

image-20240922104051771

#### 测试连接本机172.16.1.7 ok   ssh ok
内网其他机器不同

image-20240922104256075

image-20240922104622456

image-20240922104503101

开启内网转发
opnevpn连接服务器局域网:
开启openvpn 服务端内核转发功能
	在内网服务器上面配置路由规则(永久生效命令写入 /etc/rc.local )
解决方案01: 批量执行添加路由命令并永久生效
解决方案02:把openvpn服务器设置为 局域网的网关
解决方案03: 通过防火墙配置
[root@Web01 ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf    
#确保openvpn开启了ip转发
[root@Web01~]# sysctl -p
net.ipv4.ip_forward = 1
[root@web01 pki]# sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
[root@web01 pki]# route add -net 10.8.0.0/24 gw 172.16.1.7
[c:\~]$ ping 172.16.1.8            
#1、无法ping通其他内网服务器,也就是无法直连
 
正在 Ping 172.16.1.8 具有 32 字节的数据:
请求超时。
......
 
[root@Web02 ~]# yum -y install tcpdump          
#2、安装tcpdump尝试监控流量
[root@Web02 ~]# tcpdump -i eth1 -nn not icmp    
#3、windows端再次ping,虽然ping显示请求超时,但是tcp监控有流量进入,说明只能接收,不能返回
12:47:58.759367 IP 10.8.0.10 > 172.16.1.8: ICMP echo request, id 1, seq 514, length 40
12:48:03.290454 IP 10.8.0.10 > 172.16.1.8: ICMP echo request, id 1, seq 515, length 40
......
[root@Web02 ~]# route add -net 10.8.0.0 netmask 255.255.255.0 gw 172.16.1.7    #4、添加路由,临时生效,可以加入/etc/rc.local实现永久生效
 
[c:\~]$ ping 172.16.1.8            #5、本地成功ping通
 
正在 Ping 172.16.1.8 具有 32 字节的数据:
来自 172.16.1.8 的回复: 字节=32 时间=1ms TTL=63
来自 172.16.1.8 的回复: 字节=32 时间=2ms TTL=63
......
[c:\~]$ ssh 172.16.1.8        #6、直连也没有问题
 
Connecting to 172.16.1.8:22...
Connection established.
To escape to local shell, press Ctrl+Alt+].
 
Last login: Sun May 21 12:47:51 2023 from 10.0.0.1
[root@Web02 ~]# 

Linux连接VPN

[root@openvpn-client ~]# cat /etc/openvpn/client/clinet.conf
client                  #指定当前VPN是客户端
dev tun                 #使用tun隧道传输协议
proto udp               #使用udp协议传输数据
remote 10.0.0.61 1194   #openvpn服务器IP地址端口号
resolv-retry infinite   #断线自动重新连接,在网络不稳定的情况下非常有用
nobind                  #不绑定本地特定的端口号
ca ca.crt               #指定CA证书的文件路径
cert client/client.crt         #指定当前客户端的证书文件路径
key client/client.key          #指定当前客户端的私钥文件路径
verb 3                  #指定日志文件的记录详细级别,可选0-9,等级越高日志内容越详细
#修改systemctl 配置
[root@m01 ~]# cat  /usr/lib/systemd/system/[email protected]
[Unit]
Description=OpenVPN Robust And Highly FlexibleTunneling Application On %I
After=network.target

[Service]
Type=notify
PrivateTmp=true
ExecStart=/usr/sbin/openvpn Վʔcd /etc/openvpn/ Վʔconfig %i/%i.conf  #增加%i即可修改这一行#%i表示 server或 client

[Install]
WantedBy=multi-user.target

## 加载
[root@m01 ~]# systemctl daemon-reload


#启动
systemctl enable openvpn@client
systemctl start openvpn@client

OpenVPN的加密

image-20240922131148729

#openvpn server
1.先配置服务端支持密码认证:
[root@web01 ~]# vim /etc/openvpn/server.conf       
#服务端配置文件增加 3行  
script-security 3                                  
#允许使用自定义脚本
auth-user-pass-verify /etc/openvpn/check.sh via-env
#指定认证脚本
username-as-common-name                            
#用户密码登陆方式验证
2.编写/etc/openvpn/check.sh 脚本文件
[root@m01 ~]# cat /etc/openvpn/check.sh
#!/bin/sh
#desc: openvpn uesr check   scripts
#author: by oldboylinux
###########################################################
PASSFILE="/etc/openvpn/openvpnfile"             #密码文件 用户名 密码明文
LOG_FILE="/var/log/openvpn-password.log"        #用户登录情况的日志
TIME_STAMP=`date "+%Y-%m-%d %T"`

if [ ! -r "${PASSFILE}" ]; then
	echo "${TIME_STAMP}: Could not open password file \"${PASSFILE}\" for reading." ՎҴ ${LOG_FILE}
	exit 1
fi

CORRECT_PASSWORD=`awk '!/^;/ՎҐ!/^#/ՎҐ$1Վҧ"'${username}'"{print $2;exit}' ${PASSFILE}`

if [ "${CORRECT_PASSWORD}" = "" ]; then
	echo "${TIME_STAMP}: User does not exist: username=\"${username}\", password=\"${password}\"." >> ${LOG_FILE}
	exit 1
fi
if [ "${password}" = "${CORRECT_PASSWORD}" ];then
	echo "${TIME_STAMP}: Successful authentication: username=\"${username}\"." >> ${LOG_FILE}
	exit 0
 fi
 echo "${TIME_STAMP}: Incorrect password: username=\"${username}\", password=\"${password}\"." >>${LOG_FILE}
exit 1



3. 设置权限
chmod 700 /etc/openvpn/check.sh
4. 创建用户
cat > /etc/openvpn/openvpnfileՎӒEOF
oldboy 1
lidao        1
EOF
5. 重启服务端
#openvpn 客户端
auth-user-pass