按:本文是少数派会员内容《异地网络远程访问指北》系列文章的上篇,介绍了各类隧道协议的区别和选择、三种基本的链路形式,以及为自行搭建隧道所需的前期准备。
前言
近些年来,随着家庭网络速度的不断升级,不少人都会选择在家庭内部部署文件共享、媒体播放等网络服务。这不仅绕开那些高价难用的商业服务,而且在隐私和数据安全上更可控。但这些部署在家庭内部的服务,如何才能在户外安全可靠地访问到呢?
而随着疫情反反复复,居家办公日渐成为常态。但不少企业内部的协同工具(如 OA、ERP 系统)也位于本地局域网内部。可如果成员在不同地点办公,又应该如何保证他们都能继续使用这些工具呢?
你可能听说过这些办法:通过公网 IP 直接对端连接、第三方或自部署的内网穿透服务。但这些方法或多或少都有自己的局限。
公网 IP 是指在网关上配置端口转发,是目前比较热门的方案。但在没有对外网访问进行限制的情况下,这种方法不安全:HTTP 协议明文传输、弱密码、单一鉴权都容易成为局域网的漏洞。同时,如果局域网内需要对外开放的服务较多,端口转发功能便显得力不从心。
至于使用服务器作为中转,市面上有成熟的服务,如向日葵、公云、威联通 myQNAPCloud、群晖 QuickConnect 等,使用相对方便;但对传输带宽与稳定性有要求的话,往往需要额外付费。此外,由于数据需要经过第三方中转,会造成一些用户的顾虑,对于有信息安全要求的企业应用也不可行。
事实上,通过自行搭建隧道网络,就能低成本且更安全地从外部网络访问内网服务。本文的目的,就是对比并介绍数种隧道网络的特点,并介绍其搭建方式。
敬请注意:
- 本文介绍的方法和工具应在遵守相关法规和服务条款的前提下使用。
- 本文假定读者对网络原理、常见网络协议,以及 Linux 环境下的终端操作有基础了解。
- 文中演示以较常用的 Ubuntu 20.04 LTS 系统为准,其他发行版可以参照适用。
各类隧道协议的选择
传统方法最大的问题就是安全性,因此我们在选择协议的时候须以安全为第一位;其次链路的速度以及稳定性也是需要考虑的范畴,综合考虑这几点,我们选择了以下这些协议来搭建加密网络链路。
隧道协议类型 | 适用平台 | 安全性 | 速度 [注 1] | 连接稳定性 | 需要公网 IP | 防火墙友好度 |
---|---|---|---|---|---|---|
L2TP/IPsec [注 2] | 非常广泛 | 较高 | 中等 | 较稳定 | 是 | 中等 |
IKEv2/IPsec [注 3] | 非常广泛 | 较高 | 中等 | 较稳定 | 服务器侧需要 | 好 |
ZeroTier | 需要安装 | 较高 | 快 [注 4] | 稳定 | 否 | 好 |
WireGuard | 需要安装 | 高 | 非常快 | 稳定 | 是 | 较好 |
OpenConnect | 需要安装 | 高 | 中等 | 稳定 | 服务器侧需要 | 较好 |
注:
- 本表中的协议均使用 UDP 建立连接隧道,但一般情下 UDP 流量优先级较低,且大部分运营商还会对 UDP 额外进行 QoS(速度限制),因此表中速度不一定适用于所有网络环境。
- 有时也写作「L2TP over IPsec」(例如在 macOS 中);这里的 IPsec 通常使用 IKEv1 协议。
- 有时也写作「IPsec with IKEv2」或简写作「IKEv2」(例如在 macOS 中)。
- ZeroTier 在无法建立链路时,会使用 ZeroTier 官方服务器进行中转,此时连接速度可能非常慢,但我们可以通过自建中转服务器解决。
三种基本链路形式
在搭建隧道之前,我们还需要简单理解一下链路建立的三种基本形式:Point-to-Point(点到点)、Point-to-Site(点到站点)和 Site-to-Site(站点到站点)
Point-to-Point
Point-to-Point 即在客户端与服务器之间建立链路,客户端只能访问服务器,而不能访问服务器所在的局域网资源,但 Point-to-Point 是其他连接形式的基础。下文中提到的 ZeroTier 与 WireGuard 在没有配置路由表以及防火墙规则情况下,均为 Point-to-Point 连接形式。
Point-to-Site
Point-to-Site 则是在 Point-to-Point 的基础上扩展而来,这种模式下服务端将会是网关或者配置过路由表以及防火墙规则的服务器。这样只要与服务器建立连接,再由服务器转发流量,即可以实现访问服务器所在的局域网内所有资源的效果。
Site-to-Site
Site-to-Site 则是在 Point-to-Point 基础上继续扩展而来,两边服务器均作为网关/透明网关转发流量,实现两个局域网的互相访问。
其他更复杂的形式诸如 Point-to-Site-Site,均为以上结构拓展而来,本文不做详细解释。比如 Tailscale 主打的功能就是 Point-to-Site-Site,可以较为简单地整合需要建立链路的多个网络资源。
前期准备
有了对远程访问的基础认识以后,我们还需要检查自己的所在的网络环境是否适合部署加密隧道,如路由器/网关是否支持所需功能,是否具有公网 IP 等,请按照网络链路逐步检查客户端、客户端一侧的网关、服务端、服务端一侧的网关。
本地路由器/网关
服务端程序架设会分三种情况:
- 服务端程序架设在本地局域网出口网关
- 服务端程序架设在本地局域网内
- 服务端程序架设在公网服务器,由本地网关背后的设备主动去连
如果你打算「服务端程序架设在本地局域网出口网关」一般无需设置,路由系统会自动在防火墙入方向开放协议所需端口。
如果你打算「服务端程序架设在本地局域网内」需要在局域网网关设置端口转发,以便处于内网的服务端程序能顺利收到请求,一般而言需要开放如下端口:
- L2TP/IPsec:
1701
、500
和4500
UDP 端口 - IKEv2/IPsec:
500
和4500
UDP 端口 - ZeroTier、WireGuard、OpenConnect:需要视具体配置而定
如果你打算「服务端程序架设在本地局域网内」,为稳妥起见请检查光猫或路由器中的「高级 NAT 配置」或「ALG 配置」是否已启用对这类协议的支持,具体详见下图:
当然这些操作主要是由某些历史原因造成的,目前来看,多数消费级网关已能正确识别并自动处理。另外,如果你正在使用某些公共场所提供的网络,却发现怎么也连不上自己那一切正常的服务器,极有可能是网络提供者在网关上关闭了对图中所示协议的支持,此时你应考虑将流量切换至蜂窝网络,或换用其它对 NAT 更友好的协议(ZeroTier、WireGuard、OpenConnect、IKEv2)进行远程访问。
对于大部分场景来说,搭建 Point-to-Point 已经足够使用。如果想要搭建 Point-to-Site 或者是 Site-to-Site 链路,本地路由器/网关还需要支持基础的防火墙配置与静态路由设置。需要搭建这些形式的链路时,请在路由器的后台页面查看是否支持相关功能,如果不支持的话只能选择 ZeroTier 这类不需要配置的服务。
公网 IP/DDNS/VPS 服务器
开始搭建之前,还需要检查选择的方案是否对公网 IP 有要求,绝大多数协议只要求服务端或客户端中一方的网络有公网 IP。而如果选择使用家宽侧作为服务端,那么还需要对动态的公网 IP 做好 DDNS 解析,避免因为 IP 变更导致连接掉线,DDNS 设置部分此处不做过多赘述。
当然如果服务端与客户端的网络都不具备公网 IP,也可以选择 ZeroTier 这类不需要公网 IP 的服务,或者购买 VPS 作为隧道网络的服务端。
开启 IP 转发
因为服务端是 Linux 系统,我们需要调整内核设置并对防火墙进行设置,也就是打开 IP 转发功能。
打开 IP 转发之后,服务器就可以像路由器一样,将数据从一个网络发送到另一个网络,比如你在户外想要访问家中 192.168.1.0/24 这个网段的地址时,Linux 内核就可以帮你转发请求,并将结果返回给你的客户端。
# 开启 IPv4 流量转发
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
# 开启 IPv6 流量转发
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
# 立即生效
sudo sysctl -p /etc/sysctl.conf
需要注意的是,假如打算使用 Site-to-Site 的链路链接方案,那么两侧的网关均需进行该设置。
修改防火墙规则
后文中我们将会给 Linux 主机配置一系列用于加密链路的端口,如果不配置防火墙规则,从本地的发送的请求就无法被正确处理。
# 转发 VPN 流量,<VPN PORT> 需要依据实际情况动态修改
iptables -A FORWARD -i <VPN PORT> -j ACCEPT
# 转发物理网口,<INTERNAL_IP_INTERFACE> 需要依据实际情况动态修改
iptables -t nat -A POSTROUTING -o <INTERNAL_IP_INTERFACE> -j MASQUERADE
# 转发物理网口流量到服务网口
iptables -A FORWARD -i <VPN PORT> -o <INTERNAL_IP_INTERFACE> -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i <INTERNAL_IP_INTERFACE> -o <VPN PORT> -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i <VPN PORT> -o <VPN PORT> -j ACCEPT
# 丢弃所有不想要的流量
iptables -A FORWARD -i <VPN PORT> -j DROP
保存防火墙配置,开机时自动加载;以 Ubuntu 系统中的 iptables 防火墙为例:
# 安装 iptables 持久化插件
sudo apt install iptables-persistent -y
# 保存当前配置,测试没有问题后再保存
sudo iptables-save > /etc/iptables/rules.v4
安装 Docker-CE
本文中的大部分方案将通过 Docker 安装服务端,相比于传统的方法,Docker 配置简单,在不同系统之间部署方法相似,不同容器之间互相隔离不会产生影响。如果已有部署好的 Docker,可跳过这一步骤。
# 根据需要清除原有系统中的 Docker 环境
sudo apt remove docker docker-engine docker.io containerd runc -y
# 获取最新的 apt 仓库列表
sudo apt update
# 安装依赖包
sudo apt install apt-transport-https ca-certificates curl gnupg2 lsb-release software-properties-common -y
完成依赖包的安装后,接着运行 Docker 自动安装脚本,并通过阿里云镜像源获取文件。
curl -fsSL https://get.docker.com | sudo bash -s docker --mirror Aliyun
安装完成后,使用 docker version
命令校验 Docker 是否安装与配置成功。
路由器中的静态路由设置
如果你打算选择「服务端程序架设在本地局域网内」的方案,那么还需要在主网关中建立静态路由规则。这一步的目的是让所有通向远程网段的流量找到对应的服务器,需要找到路由器中的静态路由设置,再一条新建规则即可完成静态路由的设置。
设置完成以后,你在本地网段发送的针对另一个子网地址的请求,都会被路由器转发到指定的 Linux 主机上进行处理。
在接下来的中篇中,我们将介绍 L2TP/IPsec、IKEv2/IPsec 这两种相对传统的隧道解决方案的搭建步骤。