博客 > 硬件&操作系统&网络&DevOps > Linux
# Ubuntu 18.04+ 安装维护企业内网 OpenVPN 最佳实践 ## 首先:跟着教程走完安装 > 教程: > - 原文:<https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-18-04> > - 译文1:<https://www.howtoing.com/how-to-set-up-an-openvpn-server-on-ubuntu-18-04> > - 译文2:<https://www.gobeta.net/posts/how-to-set-up-an-openvpn-server-on-ubuntu-18-04/> - 这个教程总共有12个大步骤(12个主要章节),其中所有没标Optional(可选)的大步骤**都是必须做的**,别省任何一步。它里面必选和可选是交替出现的,所以别看到一个可选就停止往下看了,下面还有其他必须做的。 - 一定注意这个教程的Prerequisites(先决条件)章节,这里面是有干货的,讲了把OpenVPN服务器和CA签名服务器分离开的架构设计。如果你觉得安全性不那么重要,可以直接使用同一个服务器,同一个EasyRSA工具包。不过就是要把教程里导入导出、在两个服务器间传输文件之类的步骤自己跳过,相信熟悉Linux命令行的你一定没有问题。其实分离开确实看起来非常牛逼,但是在接下来的维护中,尤其是自动化中,会搞出一些麻烦。建议非必要不分离。 - 教程里生成客户端连接配置(`.ovpn`文件)时的脚本只负责生成连接配置,证书还是要手动创建的。因此我写了一个魔改版本,把自动生成证书的脚本也揉合进去了,文件见本文最后。使用我这个魔改版,只要运行一次,就自动生成一个客户端证书和其对应的`.ovpn`,直接把`.ovpn`文件发给客户端使用就可以了。 - 教程的最后一章是介绍证书吊销的,建议在开服的时候就预先生成一个吊销文件,然后写到`server.conf`里,这样以后真的有需要吊销的证书时,就可以不动配置文件了。 别看步骤多,按部就班跟下来就没有问题! 接下来补充一些教程中缺少的东西。 ## 一键生成/吊销证书 ### 一键生成证书和连接配置 > 下面附上我写的一个开箱即用的脚本,魔改自前面教程里的脚本。 > > 请先按前面的教程走一遍,知道客户端配置文件生成脚本的大概用法后,再替换成本段脚本。 给新人开户时,一键签名,自动导出`.ovpn`文件,可以直接分发。下面放代码`gen-ovpn.sh`: ```bash #!/bin/bash # First argument: Client identifier # Second argument: nopass cd $(dirname $0) || exit 127 if [ $# -eq 0 ] || [ "$1" == "" ]; then echo "No arguments provided, please set a Client ID in arg 1, 'nopass' if need in arg 2." exit 1 fi KEY_DIR=./keys OUTPUT_DIR=./files BASE_CONFIG=./base.conf EASYRSA_PATH=/opt/EasyRSA-3.0.8 CURRENT_PATH="$(pwd)" # register and sign a cert cd $EASYRSA_PATH if [ "$2" == "nopass" ]; then ./easyrsa gen-req "$1" nopass else ./easyrsa gen-req "$1" fi cp "pki/private/$1.key" "$CURRENT_PATH/keys/" ./easyrsa sign-req client "$1" cp "pki/issued/$1.crt" "$CURRENT_PATH/keys/" # generate client config file cd $CURRENT_PATH cat ${BASE_CONFIG} \ <(echo -e '<ca>') \ ${KEY_DIR}/ca.crt \ <(echo -e '</ca>\n<cert>') \ ${KEY_DIR}/${1}.crt \ <(echo -e '</cert>\n<key>') \ ${KEY_DIR}/${1}.key \ <(echo -e '</key>\n<tls-auth>') \ ${KEY_DIR}/ta.key \ <(echo -e '</tls-auth>') \ > ${OUTPUT_DIR}/${1}.ovpn echo "Done. See$CURRENT_PATH/files/$1.ovpn" ``` - 执行脚本时,第一个参数传准备生成的客户端名称(ID),第二个参数不传或传`nopass`,取决于有没有密码,要设置密码则不传,生成过程中会主动让你输入 - `EASYRSA_PATH`是你解压的EasyRSA工具包的根目录,视情况变动 - `KEY_DIR`、`OUTPUT_DIR`、`BASE_CONFIG`这几个东西是教程里有的,一般不需要变动 现在好了,开始派发证书给VPN客户端吧! ### 一键吊销证书 根据给定的名称一键式吊销一个(或多个)证书 ## (可选)打开单证书共用模式 OpenVPN默认是**一个连接设备一个证书**,但是生成不是特别自动化,有时候会显得麻烦。 **建议给需要较高安全性的连接使用单独证书,不要混用证书。连接人员经常变动也不要混用证书,否则任何人员离职都需要吊销证书,全体更新**。但是不特别要求安全性的场景,就可以打开共用模式。这样也方便控制证书管理的粒度。 共用模式可以有如下用途: 1. 一个项目组的开发期间,组内所有的开发机器可以使用同一个证书,开发结束后证书失效; 2. 每名员工只产生一个证书,如果这名员工有多台个人设备需要连VPN,则使用同一个证书。 **做法:**`server.conf`里,激活`duplicate-cn`(如果没有就加一行) ## (可选)允许客户端互访 OpenVPN默认只支持C<->S的访问,不允许连接到同一局域网的各个客户端互访。解决方法是在`server.conf`里,激活`client-to-client`(如果没有就加一行) ## 实时状态监控和管理 可以使用OpenVPN自带的管理界面(management interface):在`server.conf`里添加`management localhost <port>`,然后重启服务,再`telnet localhost <port>`,就可以看到里面有大量的操作。 当然也可以简单查看活跃的客户端连接:`cat /var/log/openvpn/openvpn-status.log` ## 静态IP和组网 > **注意:** 静态IP与单证书共用存在冲突,设定了静态IP的证书必须永远只在一个客户端上使用,不能两个客户端同时用一个静态IP证书。 参考[这篇教程](https://openvpn.net/community-resources/configuring-client-specific-rules-and-access-policies/) 在`server.conf`里,我的配置如下,仅供参考: ```bash # 网络结构: # 10.8.0.0/25 DHCP,也是VPN基本服务,支持64*128-1=8191个动态IP # 10.8.128.0/25 静态IP,支持64*128=8192个静态IP # 10.9.0.0/29 管理员特殊权限的静态IP,支持2个静态IP server 10.8.0.0 255.255.128.0 client-config-dir ccd route 10.8.128.0 255.255.128.0 route 10.9.0.0 255.255.255.248 push "route 10.8.128.0 255.255.128.0" # 管理员不需要客户端互访,提升安全性 # push "route 10.9.0.0 255.255.255.248" ``` 在`server.conf`同级新建一个`ccd`目录,比如我在生成客户端时(见上)把一个客户端定名为`admin`,那么我就可以在`ccd/admin`文件中写入: ``` ifconfig-push 10.9.0.1 10.9.0.2 ``` 整个文件就这一行。其中IP地址的最后8位(最后一段)必须是如下64种组合之一: ``` [ 1, 2] [ 5, 6] [ 9, 10] [ 13, 14] [ 17, 18] [ 21, 22] [ 25, 26] [ 29, 30] [ 33, 34] [ 37, 38] [ 41, 42] [ 45, 46] [ 49, 50] [ 53, 54] [ 57, 58] [ 61, 62] [ 65, 66] [ 69, 70] [ 73, 74] [ 77, 78] [ 81, 82] [ 85, 86] [ 89, 90] [ 93, 94] [ 97, 98] [101,102] [105,106] [109,110] [113,114] [117,118] [121,122] [125,126] [129,130] [133,134] [137,138] [141,142] [145,146] [149,150] [153,154] [157,158] [161,162] [165,166] [169,170] [173,174] [177,178] [181,182] [185,186] [189,190] [193,194] [197,198] [201,202] [205,206] [209,210] [213,214] [217,218] [221,222] [225,226] [229,230] [233,234] [237,238] [241,242] [245,246] [249,250] [253,254] ``` 这样,再次通过`admin`客户端连接到VPN时,就可以看到它被分配了地址`10.9.0.1`,而且,这个客户端依然可以访问`10.8.0.0`下的IP地址。 > **后记:** > > 接下来我们就可以通过ufw、iptables、Nginx的`allow/deny`等手段来控制不同用户和不同网络的连接权限了。这部分略。 > > 另外OpenVPN支持客户端的内网穿透,可以实现客户端自带一大堆内部网,然后通过客户端整体连接到VPN并与VPN其他网络互访,这部分略,可以参考<http://www.linuxfly.org/post/86/>。 ## 内网DNS 仅在连接上VPN后,才能访问某些域名,或者把某些域名从公网ip切换到���网ip,以实现一些内网Web服务。 ### 服务器配置(`server.conf`) `push`是一个服务端向客户端推送配置项的功能,写在`server.conf`里。其实和去掉push和外层引号后直接写在客户端的`.ovpn`文件里作用是一样的。 ``` push "dhcp-option DNS 127.0.0.1" push "dhcp-option DNS 10.8.0.1" push "dhcp-option DNS 223.5.5.5" push "dhcp-option DNS 8.8.8.8" ``` `10.8.0.1`可以改成别的地址,你的内网DNS的地址。我使用的是Bind9+Webmin作DNS服务器。 ### Windows客户端配置 使用GUI客户端连接即可,没什么额外配置。