ChrisKim
Do not go gentle into that good night.
颢天

通过 OpenVPN 安全地进行服务器运维

从建站以来,我的网站核心服务器的运维面板都是直接暴露在公网的。尽管启用了面板的所有登入验证功能,但是将运维面板暴露在公网仍然是极其危险的。本篇文章将会分享保护管理面板的一种简单方式,即通过 OpenVPN 来访问内网服务。

warning 特别声明
本文应用 VPN(虚拟专用网络)技术进行服务器内网访问,不包含使用 VPN 绕过防火墙审查等非法用途。另外,该技术方案适用于中国大陆内服务器运维,若涉及境外服务器不建议使用该方案。

1 必要性

首先需要解释一下为什么有必要这么大费周章:

运维面板具有极高权限

列举几种常见面板:宝塔面板是拥有服务器 root 权限的,portainer 掌握了 docker 的管理权限,Proxmox VE 的面板的权限那基本上是服务器的完全控制,phpMyAdmin 掌握了 MySQL 的管理权限。

面板有着如此高的权限,一旦高权限的面板被非法访问,那么就几乎拥有了服务器的完全控制权,风险极高。

面板鉴权方式较弱

对于一些考虑过公网访问的面板例如宝塔面板,设计了许多鉴权与防护机制,或许能够一定程度抵抗攻击(但是以往仍然出现过重大安全漏洞). 大多数面板它们的鉴权方式就是简单的 Web 登录框,防护强度较低。甚至有些面板根本就没有考虑过公网访问,例如 portainer 官方就称其内置的鉴权机制是非生产级别的,绝对不建议将其开放到公网。

因此,对于这下鉴权方式较弱的面板,如果将它们开放到公网使用,有很大的安全隐患。

2 防护方式

我目前的网站核心服务器使用宝塔面板等运维面板,我家里的服务器使用 PVE 虚拟化,同时运行了很多不愿意公开的私有的 Web 服务。我的需求是使用一种方式保护上述服务的访问安全性。

对于上述我这种个人用户的使用场景,我了解各种方案后,认为使用 VPN 来保护是最方便与适合的方式。

这种方式的原理也很简单,对于不想暴露的服务(例如高权限管理面板、私人 Web 服务),那就使用防火墙或安全组阻止外网对它们的访问。然后部署一个 VPN 服务器,在连接 VPN 后相当于进入了服务器的内网环境,这样就能访问到这些服务了。

VPN 技术是企业级的、成熟的加密通讯技术。我选用的是开源的 OpenVPN,代码开源可查,同时其本身也具有很强的安全性。因此给这些服务外面套一层 VPN,不管它们本身的安不安全,整体是安全的就行了。

3 OpenVPN 服务器部署

我们这里使用的是 OpenVPN 的自动安装脚本,大家可能认为脚本安装并不能保证安全性。但实际上,OpenVPN 的安全性是由 RSA 技术提供的,安装脚本每次安装都会现场生成 RSA 密钥,安全性是有保障的。使用脚本只是方便部署操作,对于我们这种个人应用场景,脚本提供的默认设置已经足够使用。

该脚本支持 Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS, Fedora 系统。需要注意,如果你用的是虚拟化容器,需要给容器开启 TUN/TAP.

安装脚本开源在 GitHub 上,仓库链接:

3.1 下载脚本

通过 wget 从 GitHub 上下载脚本,如果服务器访问 GitHub 困难,可以本地下载好再传上去。

wget https://raw.githubusercontent.com/Nyr/openvpn-install/master/openvpn-install.sh -O openvpn-install.sh

3.2 运行脚本

使用 root 权限运行脚本:

sudo bash openvpn-install.sh

首先会询问要绑定哪个 IPv4 地址,我这里 1 是物理网卡的,2 是 docker 的虚拟网卡,选择自己的物理网卡:

Welcome to this OpenVPN road warrior installer!

Which IPv4 address should be used?
     1) 172.19.179.51
     2) 172.17.0.1
IPv4 address [1]:

接下来需要输入自己的服务器公网 IP,默认脚本已经识别出来了回车即可。如果想要用域名代替 IP 的话,也可以手动输入解析到服务器的域名。

This server is behind NAT. What is the public IPv4 address or hostname?
Public IPv4 address / hostname [***.***.***.***]:

接下来一步就是选择传输协议,虽然脚本建议我们选择 UDP,但是我建议大家选择 TCP,原因是 UDP 包很容易被运营商 QoS 限速。我也试过选择 UDP,在我这种网络环境,其连接稳定性与速度均不如 TCP。

Which protocol should OpenVPN use?
   1) UDP (recommended)
   2) TCP
Protocol [1]: 2

接下来选择 OpenVPN 的运行端口,默认就行。如果发现端口不可用,可以自己设定一个合适的端口。

What port should OpenVPN listen to?
Port [1194]:

接下来选择客户端的 DNS 服务器,选合适的就行,我选择的是 Google 的 8.8.8.8.

Select a DNS server for the clients:
   1) Current system resolvers
   2) Google
   3) 1.1.1.1
   4) OpenDNS
   5) Quad9
   6) AdGuard
DNS server [1]: 2

接下来给第一个客户端命名,随意就行。之后可以随意增删新的客户端。

Enter a name for the first client:
Name [client]:

接下来应该就会提示你已经准备好安装了,按任意键确认安装,Ctrl + C 取消安装。耐心等待片刻就能完成安装了。

完成安装后,运行目录下会生成一个 客户端名.ovpn 的文件,该文件就是客户端的连接配置了,服务器信息和密钥都存在里面,将其下载到本地。

另外如果要对客户端进行增加修改,或者是卸载 OpenVPN,再次运行脚本,选择对应选项即可。

3.3 放行防火墙

脚本会处理好服务器系统上的防火墙,但是如果你的 IDC 有外部防火墙比如安全组的话,那还需要调整安全组配置。

具体就是放通安全组对应协议对应端口,如果是按我的来的话,就是放通 TCP 协议的 1194 端口。

4 安装 OpenVPN 客户端

OpenVPN 有所有主流平台的客户端,在官网即可下载:https://openvpn.net/client/

不过需要注意的是,由于众所周知的原因,iOS 的 App Store 国区并无此 APP,需要使用外区账号进行下载。

下载好后安装即可,其默认开启自启,在 Settings 中的 Launch Options 选择 None 关闭开机自启。

5 启动 VPN 连接

安装客户端后将会关联 .ovpn 文件,双击即可导入,也可以拖入程序内导入。然后启用该链接,出现绿色的 CONNECTED 即连接完成。

https://assets.zouht.com/img/blog/3573-01.webp

此时,就可以直接访问云服务器的内网服务了。例如我的服务器内网 IP 是 172.19.179.50,在浏览器访问 172.19.179.50:9000 即可直接访问到我的 portainer 面板。

https://assets.zouht.com/img/blog/3573-02.webp

如果觉得内网 IP 太难记,也可以给内网 IP 解析一个域名,例如我就给我的服务器内网 IP 解析了 cn-shanghai-internal.chriskim.top 这个域名。

6 配置 VPN 分流(选做)

如果使用上面的配置,启用 VPN 后,我们会发现我们所有的网络流量都走 VPN 了。这会导致网页加载速度变慢,同时也会浪费服务器的带宽资源。我们希望只有服务器的内网网段走 VPN,其他都直链。

要配置 VPN 分流,我们需要修改客户端的配置文件,我们使用文本编辑器打开客户端 .ovpn 文件,在合适位置添加下面两条配置参数。

route-nopull
route [网络地址] [子网掩码] vpn_gateway

第一行 route-nopull 取消了 OpenVPN 默认的全局路由。

第二行 route ... vpn_gateway 指定了属于对应网段的地址通过 VPN 路由,不属于对应网段的不走 VPN 路由。

这两个值可以通过在服务器上使用 ifconfig 查询得到,找到物理网卡的 inet 和 netmask,子网掩码就是 netmask,网络地址就是 inet 按位与 netmask.

例如 inet 172.19.179.51 netmask 255.255.240.0,那么网络地址就是 172.19.176.0,子网掩码 255.255.240.0(其实就是 172.19.176.0/20)

修改好后保存,然后再把这个 .ovpn 文件导入,启用后可以发现正常上网不走 VPN,仅服务器内网地址走 VPN。

7 网段冲突问题(选做)

如果你上面操作能够正常连接,说明你没有这个问题。该问题一般出在 VPN 连接到自己家局域网时,因为 IDC 的内网网段一般用的 A 类或者 B 类地址。

我们一般的家用路由器的网段都默认是 192.168.0.0/24 或 192.168.1.0/24,如果恰好客户端处于的网段和家里局域网的网段一模一样,那么连接 VPN 就要出问题了。因为根本不知道这个发往 192.168.0.x 的数据包究竟是给客户端所在局域网设备的,还是给 VPN 那段的局域网设备的。

这种情况的最简单的解决方案就是改网段,让两边的网段不同即可。比如我最开始宿舍和家里的路由器均是 192.168.0.0/24 网段,我最后把家里改成了 192.168.16.0/24,宿舍改成了 192.168.6.0/24,完美解决这个问题。

本文链接:https://www.zouht.com/3573.html
本文使用:CC BY-NC-SA 4.0 许可
# # # #
首页      教程      通过 OpenVPN 安全地进行服务器运维

发表回复

textsms
account_circle
email

颢天

通过 OpenVPN 安全地进行服务器运维
从建站以来,我的网站核心服务器的运维面板都是直接暴露在公网的。尽管启用了面板的所有登入验证功能,但是将运维面板暴露在公网仍然是极其危险的。本篇文章将会分享保护管理面板的一种简…
扫描二维码继续阅读
2023-11-06