引言
这篇文章其实是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,可以很容易找到搭建的方法,非常符合我们的要求。
开始搭建(基于账号密码认证) 安装依赖 1 yum install -y openssl openssl-devel lzo lzo-devel pam pam-devel pam_mysql automake pkgconfig gcc gcc-c++
规范安装目录
安装 easy-rsa 并生成相关证书 easy-rsa 下载地址:网页链接
1 2 3 [root@m01 ~] [root@m01 /application/easy-rsa-old-master] configure.ac COPYING COPYRIGHT.GPL distro doc easy-rsa Makefile.am
生成相关证书 1 2 3 4 5 [root@m01 /application/easy-rsa-old-master] [root@m01 /application/easy-rsa-old-master/easy-rsa/2.0] 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 相关文件 1 2 3 [root@m01 /application/easy-rsa-old-master/easy-rsa/2.0] [root@m01 /application/easy-rsa-old-master/easy-rsa/2.0] lrwxrwxrwx 1 root root 17 2月 2 01:34 openssl.cnf -> openssl-1.0.0.cnf
编辑证书基本信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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 ./build-ca (y/n)y ls keys/ca.crt ca.key index.txt serial
生成服务器端秘钥 1 2 ./build-key-server server (y/n)y
生成密钥如下 1 2 ls keys01.pem ca.crt ca.key index.txt index.txt.attr index.txt.old serial serial.old server.crt server.csr server.key
生成客户端证书 1 2 3 ./build-key client (y/n)y (y/n)y
创建迪菲·赫尔曼密钥
查看生成的所有证书 1 2 3 [root@m01 /application/easy-rsa-old-master/easy-rsa/2.0] 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 1 2 3 4 5 6 7 8 9 10 [root@m01 ~] [root@m01 ~] ./configure --prefix=/application/openvpn-2.4.8 && make && make install [root@m01 /application] [root@m01 /application] 总用量 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 1 2 3 4 配置 OpenVPN 服务端 创建配置文件目录和证书目录: mkdir -p /etc/openvpn mkdir -p /etc/openvpn/pki
生成ta.key文件(防DDos攻击、UDP淹没等恶意攻击) 1 2 3 [root@m01 /application/easy-rsa-old-master/easy-rsa/2.0/keys] [root@m01 /application/easy-rsa-old-master/easy-rsa/2.0/keys] ta.key
将签名生成的 CA 证书秘钥和服务端证书秘钥拷贝到证书目录中 1 2 3 4 5 6 7 8 9 [root@m01 /application/easy-rsa-old-master/easy-rsa/2.0/keys] [root@ZJVPN /application/easy-rsa-old-master/easy-rsa/2.0/keys] 总用量 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
拷贝配置文件模版 1 2 3 4 5 6 7 8 9 10 11 12 13 [root@m01 ~] [root@m01 ~] /etc/openvpn/ ├── pki ├── pki │ ├── ca.crt │ ├── ca.key │ ├── dh2048.pem │ ├── ipp.txt │ ├── server.crt │ ├── server.key │ └── ta.key └── server.conf
编辑openvpn配置文件 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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 [root@m01 ~] local 0.0.0.0port 8888 proto tcp dev tun ca /etc/openvpn/pki/ca.crt cert /etc/openvpn/pki/server.crt key /etc/openvpn/pki/server.key dh /etc/openvpn/pki/dh2048.pem server 10.10.10.0 255.255.255.0 push "dhcp-option DNS 192.168.200.177" push "dhcp-option DNS 114.114.114.114" ifconfig-pool-persist ipp.txt push "route 192.168.200.177 255.255.255.255" push "route 192.168.200.120 255.255.255.255" 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" push "route 192.168.1.32 255.255.255.255" push "route 192.168.1.238 255.255.255.255" push "route 192.168.1.17 255.255.255.255" push "route 192.168.1.121 255.255.255.255" push "route 182.18.3.0 255.255.255.0" push "route 192.168.1.160 255.255.255.255" push "route 192.168.200.0 255.255.255.0" push "route 192.168.2.0 255.255.255.0" push "route 192.168.1.19 255.255.255.255" push "route 192.168.1.114 255.255.255.255" 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 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 ;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.loglog-append /var/log/openvpn.log verb 3
上传密码验证脚本 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 44 45 46 47 [root@m01 /etc/openvpn] checkpsw.sh pki server.conf [root@m01 /etc/openvpn] 总用量 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] [root@ZJVPN /etc/openvpn] 总用量 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.shPASSFILE="/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 1fi 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 1fi if [ "${password} " = "${CORRECT_PASSWORD} " ]; then echo "${TIME_STAMP} : Successful authentication: username=\"${username} \"." >> ${LOG_FILE} exit 0fi echo "${TIME_STAMP} : Incorrect password: username=\"${username} \", password=\"${password} \"." >> ${LOG_FILE} exit 1[root@m01 ~] -rw-r--r-- 1 root root 151 12月 1 11:05 /etc/openvpn/psw-file [root@m01 ~] felix 591740
配置systemd启动脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 策略: 1 2 3 4 5 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
开启内核路由转发功能 1 2 3 4 vim /etc/sysctl.conf 添加如下内容 net.ipv4.ip_forward = 1 sysctl -p
安装OpenVPN客户端 1 2 3 4 5 6 7 客户端安装完成后,将以下证书和秘钥文件拷贝到安装目录中的 config 目录下: [root@ZJVPN /etc/openvpn/pki] [root@ZJVPN /application/easy-rsa-old-master/easy-rsa/2.0/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 ta.key [root@ZJVPN /application/easy-rsa-old-master/easy-rsa/2.0/keys]
Windows 检查路由是否已经推送到客户端 MacOS 检查路由是否已经推送到客户端
这里选择了推送部分路由通过tun虚拟网卡设备,如果是0.0.0.0的话会导致连上VPN的客户端上网卡顿,即全部流量都走VPN访问。
到此为止,我们就构建好了一个点到站VPN,如果你的服务器在公司内网需要麻烦IT同事将你的VPN端口如我这里的8888端口通过公司防火墙或者最外层路由设备做DNAT映射出去。在OPENVPN服务端配置文件中添加相关内网资源如Git仓库、测试数据库的内网IP 加入到路由中。在psw-file给出差员工开账号,吧相关证书和配置文件发给他们让他们可以连接你的VPN。
客户端下载:https://openvpn.net/vpn-client/
客户端主配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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