Ubuntu架设OpenVPN实现内网穿透

前言

家里的网络因为没有公网 IP,有时候想要连接到家里的树莓派或者电脑就无法实现。这个时候可以采用内网穿透的方法远程连接家中的机器,内网穿透的方案有很多,下面介绍一种采用 OpenVPN 实现内网穿透的方案。


配置

主机:腾讯云/阿里云
操作系统:Ubuntu 16.04/18.04/20.04

教程

安装 OpenVPN

首先,我们需要在服务器安装 OpenVPN。在 Ubuntu 系统中我们可以通过 apt 简单的进行安装。同时我们也需要安装 easy-rsa,它可以帮助我们生成 VPN 使用过程中所需的 CA 证书。

设置 CA 目录

OpenVPN 是使用 TLS/SSL 的 VPN。这意味着它利用证书来加密服务器和客户端之间的通信。为了发布受信任的证书,我们需要建立一个自己的简单的证书颁发机构(CA)。 使用 make-cadir 命令复制 easy-rsa 模板到 home 目录。

接着进入刚刚新建的目录准备配置 CA:

配置 CA 变量

进入 ~/openvpn/openvpn-ca 目录后,我们需要修改 vars 文件,以便于生成需要的 CA 值。

在文件底部找到以下配置:

将这些变量修改为任意你喜欢的值,但是不要为空:

然后,我们还要修改紧接着出现的 KEY_NAME 的值,为了简单起见,我们改为 server  (这个不要修改成其他名字,后续的配置文件中默认是这个名字), 默认是 EasyRSA:

构建 CA 证书

针对 ubuntu 16.04 LTS/ubuntu 18.04 LTS 执行如下操作

首先进入你的 CA 目录,然后执行 source vars :

接着会有以下输出:

执行下列操作确保操作环境干净:

现在我们可以构建根 CA:

这将会启动创建根证书颁发密钥、证书的过程。由于我们刚才修改了 vars 文件,所有值应该都会自动填充。所以,一路回车就好了:

现在,我们就有了创建以下步骤需要的 CA 证书。

针对 ubuntu 20.04.6 LTS, 由于OpenVPN版本升级,已经没有上面的命令了,需要调整脚本为如下:

创建服务器端证书、密钥和加密文件

通过下列命令生成服务器端证书和秘钥:

注:server 就是刚才在 vars 文件中修改的 KEY_NAME 变量的值。请不要使用别的名字! 然后一直回车选择默认值即可,不要设置 challenge password ,直接回车即可。到最后,你需要输入两次 y 注册证书和提交。

然后还需要生成一些其他东西。我们可以在密钥交换过程中生成一个强大的 Diffie-Hellman 密钥:

这个操作大约会花费几分钟不等。 然后,我们可以生成 HMAC 签名加强服务器的 TLS 完整性验证功能:

配置 OpenVPN 服务

首先将刚刚生成的各类文件复制到 OpenVPN 目录下:

然后,解压并复制一个 OpenVPN 配置文件到 OpenVPN 目录:

接着更改配置,注释掉 udp 更改协议为 tcp :

找到 tls-auth 位置,去掉注释,并在下面新增一行:

去掉 usergroup 行前的注释:

去掉 client-to-client 行前的注释允许客户端之间互相访问:

开启客户端固定 IP 配置文件夹:

去掉注释后的完整配置如下:

去掉注释之后,精简的关键信息如下:

调整服务器网络配置
调整 UFW 规则

首先,确认UFW防火墙状态,如果状态为开启,则调整。如果防火墙是关闭的,则不需要调整。

如果输出是Status: inactive, 那么不需要进行下面的调整。

注意,下面的调整如果中间出现问题,可能导致防火墙拦截SSH进而无法进行恢复操作。如果出现问题,可以使用阿里云或者腾讯云提供的远程控制台在网页端进行恢复操作。

注意,如果服务器是从早期版本的ubuntu 14.04升级到ubunt 16.04的,那么可能会出现如下警告信息:

原因为存在两个版本的防火墙配置文件 apache2-utils.ufw.profileubunt 16.04) , apache2.2-commonubuntu 14.04) ,这两个配置文件。

我们需要删除早期的防火墙配置文件,如下:

如果服务器上UFW首次启用, 需要手工许可若干常用服务,否则无法远程访问:

当然,也可以直接配置需要开放的端口,但是不推荐,如下:

如果需要删除特定的规则,那么参考如下命令:

打开 OpenVPN 端口并使变化生效

启动OpenVPN

执行:

设置开机自启:

创建客户端配置

生成客户端证书、密钥对

client-mobibrw 为密钥对名称,生成过程中回车选择默认选项即可。

注意,下面这一步一定要输入 y 否则会跳过最后一步,导致生成证书的时候会缺少部分信息。

注意,如果有多个客户端的话,建议为每个客户端生成一份配置文件。

创建客户端配置

执行下列命令,生成客户端配置的基础文件:

然后打开 ~/client-configs/base.conf 文件,修改 remote my-server-1 1194 为服务器公网IP或者域名。 然后更改客户端协议为 tcp:

去掉 usergroup 前的注释:

找到 ca/cert/key,注释掉:

在文件中新增一行:

保存退出文件。

去掉注释后的完整配置为:

创建配置生成脚本

新建 ~/client-configs/make_config.sh 文件,复制如下内容:

针对 ubuntu 20.04.6 LTS,由于OpenVPN版本升级,已经没有上面的命令了,需要调整脚本为如下:

保存并赋予执行权限:

生成客户端配置

执行:

使用此脚本生成一个配置文件方便客户端使用。 注:需要生成客户端密钥后才可使用脚本生成配置文件,client-mobibrw.ovpn 为刚刚生成的客户端密钥名称 生成后的脚本储存在 ~/client-configs/files 目录下,名称为 client-mobibrw.ovpn。将文件下载到本地即可使用了。

为客户端设置固定IP

首先在OpenVPN所在的文件夹内创建ccd文件夹:

然后进入该文件夹并创建与客户端密钥同名的文件:

文件内容如下:

此内容意为固定client-mobibrw客户端的OpenVPN内网IP10.8.0.8

注意,上面的配置在客户端是Windows系统的时候,会报告如下错误:

导致这个错误的原因是 TAP-WIN32 使用默认子网掩码 255.255.255.252 因此一个网段之内只能有两个相邻IP,一个是网关,一个是子网设备。

这个问题在 Linux/macOS 系统上是不存在的,这个是 TAP-WIN32 驱动的限制。

因此,如果系统是 Windows 并且使用 TAP-WIN32 驱动,那么配置的地址只能是如下情况:

或者

或者

前面为设备地址,后面为网关IP. 规律就是 设备地址是 网关地址 +1

客户端命令行使用

首先安装OpenVPN 运行时选择配置为客户端配置文件:

使用此方法可以让家里的电脑或者树莓派等设备实现内网穿透,从而远程连接进行操作。

对于客户端是macOS的设备来说,推荐使用Tunnelblick

服务器上查看连接上的客户端列表,则执行如下命令:"cat /etc/openvpn/openvpn-status.log" 也可能是"cat /var/log/openvpn/openvpn-status.log"

对于Debian/Ubuntu/WDMyCloud等设备,我们把配置文件放到/etc/openvpn/并且重命名为client-mobibrw.conf,(也就是扩展名为 .conf)可以实现开机自动启动连接。

WDMyCloud 查看日志

如果日志中出现

则需要注释掉 

常用的几条客户端命令如下:

对于群晖来说,group nogroup这个用户组是不存在,我们需要注释掉这一行,但是user nobody是存在的。

群晖 DSM 6.2/7.0测试的命令如下:

对于群晖 DSM 6.2/7.0来说,我们把配置文件放到/usr/syno/etc/synovpnclient/openvpn/并且重命名为client-mobibrw.conf,(也就是扩展名为.conf), 然后执行如下命令:

文件内容如下:

DSM 6.2/7.0 中增加计划任务,设定为开机自动运行脚本,如下图:

可以实现开机自动启动连接。

注:该方法只有连接内网机器时会使用OpenVPN代理,平时访问网页等不会走代理,并不是全局代理,节省服务带宽的使用

常见问题

如果运行时候报错(一般发生在ubuntu 20.04系统)

则注释掉 #explicit-exit-notify 1 ,此选项开启只能使用UDP协议

参考链接


发布者

《Ubuntu架设OpenVPN实现内网穿透》上有4条评论

    1. frp 属于后起之秀,目前来说还不是足够成熟,一些平台,比如群晖,自身没有携带,编译安装也比较麻烦。对于标准的Linux服务器来说,frp 算是一个不错的选择。更多的是使用习惯的问题吧。
    1. 这个貌似需要使用专用的代理服务器软件实现,默认情况下,这些开源软件没有实现这么复杂的功能,不过一般都有商业版本来补充这些功能。

      当然,如果用户不多,可以试试docker给每个用户单独部署一个docker进程,每个docker进程映射一个独立的端口出来,用户使用自己的独立docker服务器。

      当然也可以共享一个端口,根据链接地址的不同重定向到不同的用户使用的docker进程上。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注