cover

引言

这篇文章其实是2019年年末记录的,当时是因为疫情原因公司需要协助员工在家办公。开发部门和总部安全部门认为直接吧公司内网系统开放访问不安全,一个一个给员工家里公网IP加白名单也不现实。就临危受命接下了搭建VPN的任务。这次将文档整理发出其实在纠结会不会被请去喝茶,毕竟话题敏感。希望人没事

PS:文档在记录时并没有太多中文参考资料,是自己摸索的,所以可能生成的有些证书并没有用上(多余的操作)。大家海涵

OpenVPN介绍

  • OpenVPN是一个用于创建虚拟专用网络加密通道的软件包,最早由James Yonan编写。OpenVPN允许创建的VPN使用公开密钥、电子证书、或者用户名/密码来进行身份验证。
  • 它大量使用了OpenSSL加密库中的SSLv3/TLSv1协议函数库。
  • 目前OpenVPN能在Solaris、Linux、OpenBSD、FreeBSD、NetBSD、Mac OS X与Microsoft Windows以及Android、iOS、MacOS(2020年官方推出Mac客户端)上运行,并包含了许多安全性的功能。它并不是一个基于Web的VPN软件,也不与IPsec及其他VPN
  • OpenVPN2.0后引入了用户名/口令组合的身份验证方式,它可以省略客户端证书,但是仍有一份服务器证书需要被用作加密。 OpenVPN所有的通信都基于一个单一的IP端口, 默认且推荐使用UDP协议通讯,同时TCP也被支持。OpenVPN连接能通过大多数的代理服务器,并且能够在NAT的环境中很好地工作。服务端具有向客 户端“推送”某些网络配置信息的功能,这些信息包括:IP地址、路由设置等。
  • OpenVPN提供了两种虚拟网络接口:通用Tun/Tap驱动,通过它们, 可以建立三层IP隧道,或者虚拟二层以太网,后者可以传送任何类型的二层以太网络数据。传送的数据可通过LZO算法压缩。在选择协议时候,需要注意2个加密隧道之间的网络状况,如有高延迟或者丢包较多的情况下,请选择TCP协议作为底层协议,UDP协议由于存在无连接和重传机制,导致要隧道上层的协议进行重传,效率非常低下。

VPN的主要作用是在局域网外部时也可以访问局域网的资源,比如公司内网有许多资源只能公司内网访问,而我们外派出差员工还想访问公司内网资源[如:GitLab/测试库/其他测试环境接口]就需要通过连接公司公网出口暴露VPN来实现。

由于众所周知的原因,几种简单的VPN协议比如L2TP/IPsec和PPTP协议在大陆地区已经被干扰的基本无法正常使用了。因此也就SSL VPN还可以使用。SSL VPN有非常多种,但很多都是商业软件,不开源也不适合个人搭建。而OpenVPN是一款开源的SSL VPN,可以很容易找到搭建的方法,非常符合我们的要求。

OpenVpn

开始搭建(基于账号密码认证)

安装依赖

yum install -y openssl openssl-devel lzo lzo-devel pam pam-devel pam_mysql automake pkgconfig gcc gcc-c++

规范安装目录

mkdir -p /application/

安装 easy-rsa 并生成相关证书

easy-rsa 下载地址:网页链接

[root@m01 ~]# unzip -d /application/ easy-rsa-old-master.zip
[root@m01 /application/easy-rsa-old-master]# ls
configure.ac  COPYING  COPYRIGHT.GPL  distro  doc  easy-rsa  Makefile.am

生成相关证书

[root@m01 /application/easy-rsa-old-master]# cd /application/easy-rsa-old-master/easy-rsa/2.0/
[root@m01 /application/easy-rsa-old-master/easy-rsa/2.0]# ls
build-ca     build-key         build-key-server  clean-all      openssl-0.9.6.cnf  pkitool      vars
build-dh     build-key-pass    build-req         inherit-inter  openssl-0.9.8.cnf  revoke-full  whichopensslcnf
build-inter  build-key-pkcs12  build-req-pass    list-crl       openssl-1.0.0.cnf  sign-req

准备 openssl 相关文件

[root@m01 /application/easy-rsa-old-master/easy-rsa/2.0]# ln -s openssl-1.0.0.cnf openssl.cnf
[root@m01 /application/easy-rsa-old-master/easy-rsa/2.0]# ll openssl.cnf 
lrwxrwxrwx 1 root root 17 2月   2 01:34 openssl.cnf -> openssl-1.0.0.cnf

编辑证书基本信息

pwd 
/application/easy-rsa-old-master/easy-rsa/2.0
vim vars 
 67 export KEY_COUNTRY="CN"
 68 export KEY_PROVINCE="SH"
 69 export KEY_CITY="Shanghai"
 70 export KEY_ORG="360XXX"
 71 export KEY_EMAIL="yaXXXXXhi-jk@360jiXXXng.net"
 
. vars  #生效环境变量

##生成证书,以下命令全部一直回车
./clean-all   
(y/n)y
#清空所有证书(keys目录下)
./build-ca   
(y/n)y
#生成服务器ca证书

##生成证书如下:
ls keys/
ca.crt  ca.key  index.txt  serial

生成服务器端秘钥

./build-key-server server
(y/n)y

生成密钥如下

ls keys
01.pem  ca.crt  ca.key  index.txt  index.txt.attr  index.txt.old  serial  serial.old  server.crt  server.csr  server.key

生成客户端证书

./build-key client
(y/n)y
(y/n)y

创建迪菲·赫尔曼密钥

## 会生成dh2048.pem文件(生成过程比较慢,在此期间不要去中断它)
./build-dh

查看生成的所有证书

[root@m01 /application/easy-rsa-old-master/easy-rsa/2.0]# ls keys/
01.pem  ca.crt  client.crt  client.key  index.txt       index.txt.attr.old  serial      server.crt  server.key
02.pem  ca.key  client.csr  dh2048.pem  index.txt.attr  index.txt.old       serial.old  server.csr

安装openvpn

[root@m01 ~]# tar -xf openvpn-2.4.8.tar.gz 
[root@m01 ~]# cd openvpn-2.4.8/
./configure --prefix=/application/openvpn-2.4.8 && make && make install

[root@m01 /application]# ln -s openvpn-2.4.8 openvpn
[root@m01 /application]# ll
总用量 0
drwxr-xr-x 5 root root 178 1月  23 2018 easy-rsa-old-master
lrwxrwxrwx 1 root root  13 2月   2 02:06 openvpn -> openvpn-2.4.8
drwxr-xr-x 6 root root  57 2月   2 02:06 openvpn-2.4.8

配置openvpn

配置 OpenVPN 服务端
创建配置文件目录和证书目录:
mkdir -p /etc/openvpn        # openvpn 配置文件路径
mkdir -p /etc/openvpn/pki    # openvpn 证书存放位置

生成ta.key文件(防DDos攻击、UDP淹没等恶意攻击)

[root@m01 /application/easy-rsa-old-master/easy-rsa/2.0/keys]# /application/openvpn/sbin/openvpn --genkey --secret ta.key 
[root@m01 /application/easy-rsa-old-master/easy-rsa/2.0/keys]# ls
ta.key

将签名生成的 CA 证书秘钥和服务端证书秘钥拷贝到证书目录中

[root@m01 /application/easy-rsa-old-master/easy-rsa/2.0/keys]# cp {ca.crt,ca.key,dh2048.pem,server.crt,server.key,ta.key} /etc/openvpn/pki/
[root@ZJVPN /application/easy-rsa-old-master/easy-rsa/2.0/keys]# ll /etc/openvpn/pki/
总用量 28
-rw-r--r-- 1 root root 2382 2月   2 05:43 ca.crt
-rw------- 1 root root 3268 2月   2 05:43 ca.key
-rw-r--r-- 1 root root  424 2月   2 05:43 dh2048.pem
-rw-r--r-- 1 root root 8146 2月   2 05:43 server.crt
-rw------- 1 root root 3272 2月   2 05:43 server.key
-rw------- 1 root root  636 2月   2 05:43 ta.key

拷贝配置文件模版

[root@m01 ~]# cp openvpn-2.4.8/sample/sample-config-files/server.conf /etc/openvpn/
[root@m01 ~]# tree /etc/openvpn/
/etc/openvpn/
├── pki
├── pki
│   ├── ca.crt
│   ├── ca.key
│   ├── dh2048.pem
│   ├── ipp.txt
│   ├── server.crt
│   ├── server.key
│   └── ta.key
└── server.conf

编辑openvpn配置文件

[root@m01 ~]# cat /etc/openvpn/server.conf 
local 0.0.0.0
port 8888
proto tcp
dev tun
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/server.crt
key /etc/openvpn/pki/server.key  # This file should be kept secret
dh /etc/openvpn/pki/dh2048.pem
server 10.10.10.0 255.255.255.0    # 分配给客户端的虚拟局域网段
push "dhcp-option DNS 192.168.200.177"    #客户端连入后使用的DNS
push "dhcp-option DNS 114.114.114.114"
ifconfig-pool-persist ipp.txt
#k8sDNS
push "route 192.168.200.177 255.255.255.255"  # 推送路由和DNS到客户端
#k8s负载
push "route 192.168.200.120 255.255.255.255"
#gitlab新
push "route 192.168.1.55 255.255.255.255"
push "route 192.168.1.249 255.255.255.255"
#内网测试库
push "route 192.168.1.233 255.255.255.255"
#felix电脑
push "route 192.168.1.32 255.255.255.255"
#老麦测试机
push "route 192.168.1.238 255.255.255.255"
#jacky电脑
push "route 192.168.1.17 255.255.255.255"
#mo电脑
push "route 192.168.1.121 255.255.255.255"
#三楼
push "route 182.18.3.0 255.255.255.0"
#VPN
push "route 192.168.1.160 255.255.255.255"
#测试机网段
push "route 192.168.200.0 255.255.255.0"
#lke
push "route 192.168.2.0 255.255.255.0"
push "route 192.168.1.19 255.255.255.255"
#hali
push "route 192.168.1.114 255.255.255.255"
#August
push "route 192.168.1.14 255.255.255.255"
#签名层
push "route 192.168.1.71 255.255.255.255"
#国内文章
push "route 192.168.1.171 255.255.255.255"

client-to-client
keepalive 10 120
tls-auth /etc/openvpn/pki/ta.key 0 # This file is secret
cipher AES-256-CBC
comp-lzo
;max-clients 50
user nobody
group nobody
auth-user-pass-verify /etc/openvpn/checkpsw.sh via-env
script-security 3
#client-cert-not-required
;link-mtu 1500
verify-client-cert none
username-as-common-name
persist-key
persist-tun
status /var/log/openvpn-status.log
log         /var/log/openvpn.log
log-append  /var/log/openvpn.log
verb 3

#这里选择了推送部分路由通过tun虚拟网卡设备,如果是0.0.0.0的话会导致连上VPN的客户端上网卡顿,即全部流量都走VPN访问

上传密码验证脚本

[root@m01 /etc/openvpn]# ls
checkpsw.sh  pki  server.conf
[root@m01 /etc/openvpn]# ll
总用量 8
-rw-r--r-- 1 root root 1167 2月   2 02:59 checkpsw.sh #验证账号密码脚本
drwxr-xr-x 2 root root  102 2月   2 05:43 pki #账号密码文件 账号一行一个
-rw-r--r-- 1 root root 1174 2月   2 05:47 server.conf
[root@ZJVPN /etc/openvpn]# chmod +x checkpsw.sh 
[root@ZJVPN /etc/openvpn]# ll
总用量 8
-rwxr-xr-x 1 root root 1167 2月   2 02:59 checkpsw.sh
drwxr-xr-x 2 root root  102 2月   2 05:43 pki
-rw-r--r-- 1 root root 1174 2月   2 05:47 server.conf

cat checkpsw.sh
#!/bin/sh
###########################################################
# checkpsw.sh (C) 2004 Mathias Sundman 
#
# This script will authenticate OpenVPN users against
# a plain text file. The passfile should simply contain
# one row per user with the username first followed by
# one or more space(s) or tab(s) and then the password.
PASSFILE="/etc/openvpn/psw-file"
LOG_FILE="/application/openvpn/logs/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

[root@m01 ~]# ll /etc/openvpn/psw-file
-rw-r--r-- 1 root root 151 12月  1 11:05 /etc/openvpn/psw-file
[root@m01 ~]# cat /etc/openvpn/psw-file
felix 591740

配置systemd启动脚本

cat /usr/lib/systemd/system/openvpn.service
[Unit]
Description=openvpn
After=network.target
  
[Service]
EnvironmentFile=-/etc/openvpn/openvpn
ExecStart=/application/openvpn/sbin/openvpn --config /etc/openvpn/server.conf
Restart=on-failure
Type=simple
LimitNOFILE=65536
  
[Install]
WantedBy=multi-user.target

systemctl enable --now openvpn.service

2021年补图 补图

配置 iptables 策略:

iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
也可以这样做:添加 iptables 转发规则,对所有源地址(openvpn为客户端分配的地址)为 10.10.10.0/24 的数据包转发后进行源地址转换,伪装成 openvpn 服务器内网地址 x.x.x.x, 这样 VPN 客户端就可以访问服务器内网的其他机器了。

iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -j SNAT --to-source 192.168.1.160
iptables -I INPUT -p tcp -m tcp --dport 8888 -j ACCEPT

开启内核路由转发功能

vim /etc/sysctl.conf
添加如下内容
net.ipv4.ip_forward = 1
sysctl -p

安装OpenVPN客户端

客户端安装完成后,将以下证书和秘钥文件拷贝到安装目录中的 config 目录下:
[root@ZJVPN /etc/openvpn/pki]# cd /application/easy-rsa-old-master/easy-rsa/2.0/keys/
[root@ZJVPN /application/easy-rsa-old-master/easy-rsa/2.0/keys]# ls
01.pem  ca.crt  client.crt  client.key  index.txt       index.txt.attr.old  serial      server.crt  server.key
02.pem  ca.key  client.csr  dh2048.pem  index.txt.attr  index.txt.old       serial.old  server.csr  ta.key
[root@ZJVPN /application/easy-rsa-old-master/easy-rsa/2.0/keys]# sz {ca.crt,client.crt,client.key,ta.key}

Windows windows客户端windows客户端 检查路由是否已经推送到客户端 windows客户端 MacOS MacOSMacOS 检查路由是否已经推送到客户端 upload successful

这里选择了推送部分路由通过tun虚拟网卡设备,如果是0.0.0.0的话会导致连上VPN的客户端上网卡顿,即全部流量都走VPN访问。

到此为止,我们就构建好了一个点到站VPN,如果你的服务器在公司内网需要麻烦IT同事将你的VPN端口如我这里的8888端口通过公司防火墙或者最外层路由设备做DNAT映射出去。在OPENVPN服务端配置文件中添加相关内网资源如Git仓库、测试数据库的内网IP 加入到路由中。在psw-file给出差员工开账号,吧相关证书和配置文件发给他们让他们可以连接你的VPN

客户端下载:https://openvpn.net/vpn-client/

客户端主配置文件

client
dev tun
proto tcp
remote 你的公网ip 8888
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
auth-user-pass
auth-nocache
comp-lzo
企业级OpenVPN搭建
转载前请阅读本站 版权协议,文章著作权归 饼铛 所有,转载请注明出处。

目录