如果你在大厂工作,或者自己的工作环境完全就是互联网网化的,就可以离开了,这篇文章不适合你。
Web应用发布
如果你在小公司做Web应用开发工作,或者经常以个人的方式或者名义,来开发一些Web方面的应用程序,那可能会有一些困惑和需求,就是希望通过互联网,也可以访问在开发环境中部署的用于开发、调试或者测试的Web应用程序。一个典型的场景就是有时候需要向客户演示Web应用和功能,这时候就不想专门找个公网的环境来部署这个演示程序,因为那样可能会比较复杂,而希望直接使用正在开发和测试的系统和环境。
我们不讨论将Web应用再次部署在云端的情况,只讨论Web应用运行在开发用的主机,就是真实开发和调试的环境的情况。这时,通常有下面几个选项和技术方案:
- 端口映射和发布
对于一般的家庭、个人或者小企业用户,运营商只提供互联网访问和接入的服务。从技术上而言,其实是不完整的。就是只提供了从自己的主机访问互联网的能力,通常情况下,是不能通过互联网来访问内部主机的。
这里通常有两个技术方面的限制,第一是运营商通常使用NAT提供互联网访问,也就是说分配给用户的IP地址并不是真正的互联网IP地址,通常也被称为公网地址,而是运营商的"局域网"IP地址,然后通过网络地址转换(Network Adress Traslate,NAT)技术来共享一个公共的出口IP地址。第二就是即使条件允许,运营商可以给用户分配真正的公网IP,这个IP地址也是动态的,就是说,基本上不能使用IP地址的方式来使用Web应用,需要DNS或者动态DNS。
在家庭和企业内部,通常也是一个共享上网的环境。它们一般都是通过运营商提供的路由器和光猫接入互联网。由于运营商可能为所有上网设备都提供公网IP地址,所以通常是在路由器上,使用NAT技术来实现局域网络设备的共享互联网连接的。
除了使用NAT共享一个公网连接对外访问网络之外,通过对NAT的配置,也可以将内网中的主机端口发布到公网上,这被称为端口映射。这需要在NAT设备上进行相关的操作和设置,将NAT公网IP地址的某一个端口,映射到某一个内网主机的某一个网络端口上。这样,如果有来自外部的网络请求,NAT就可以将请求转发到内网的主机上进行处理。
显然,这个技术方案可能会有两个使用上的限制。一是用户需要有权限调整和设置互联网接入设备,并进行相关的操作,特别是如果使用DHCP,还需要固定主机的IP地址,这些都会改变原有的一些网络设置;二是在运营商那里,有可能并不能理想的直接分配一个真正公网的IP地址,而他们也使用一个更大的NAT网络,这样理论上也需要进行调整和设置,大部分情况下是不可行的。
- VPS主机和隧道
如果运营商根本就不能分配一个公网IP地址,同时也不能在运营商那里申请端口映射的话,就需要自己架构一个公共IP的入口,并且想办法将这个入口能够映射或者转换到内部的Web应用端口之上了,这时通常要用到一个具有公网IP地址的云主机,通常被称为VPS(Virtual Private Server)。这个名字并不是特别重要,比如Amazon提供的云主机通常叫做EC2(Elastic Compute Cloud, 弹性计算云主机),其实也是差不多的东西。笔者认为这里的核心要素有三个,一是可以提供真正(或者等效)的公网IP地址,二是这个主机可以像独立的操作系统环境一样,进行完全的管理和配置,而非仅仅提供一个特定的功能或者服务,三是提供远程管理和访问的途径,比如常用的SSH。
有了VPS之后,还需要一个工具,可以将在公网IP地址上侦听和发布的网络端口,映射或者桥接到内部开发主机之上。比如SSH就提供这样的功能,或者使用其他工具比如frp,它们都可以在本地主机和VPS之间建立一个"隧道",来转发对于VPS网络地址和端口的访问请求,到本地的主机和应用侦听端口之上。
- VPN+反向代理
这个方案同样需要一个公网VPS系统。然后在本地主机和VPS系统间,使用VPN软件(如WireGuard)建立一个小型的内部网络。然后还需要在VPS系统上,安装一个反向代理软件比如Nginx或者HaProxy,将应用映射到本地主机在VPN网络中的地址之上。
端口映射和VPS都是常规的技术方案,它们都有一些限制条件,比如需要运营商分配的公网IP地址,支持端口映射的网络设备和配置,需要购买、租用和管理VPS主机、安装相关的软件等等。
针对这些问题和不便,下面笔者想要来介绍一个新型的网络服务和工具-ngrok,它也可以方便的实现类似的本地Web应用发布的效果。
ngrok
ngrok的官方网站是: ngrok.com/ 。
概述
在其官网中,它这样描述自己的产品和服务:
Unified Ingress Platform for developers,ngrok combines your reverse proxy, firewall, API gateway, and global load balancing to deliver apps and APIs.
开发者的统一入口平台,ngrok集成综合了反向代理、防火墙、API网关和全球负载均衡来提供Web应用和API交付和发布。
这些描述已经阐述的比较清晰。它是一个反向代理工具和服务,但工作方式和普通单纯的反向代理软件如nginx不同,它需要一个客户端程序来连接这个网络服务,这样就只需要本地应用主机可以访问互联网就可以了。此外它还提供了一些扩展的特性如防火墙,负载均衡等等,来提升应用过程的安全和体验。笔者还想补充一点,就是这个系统的使用也是比较简单的,也有很好的管理和监控功能,这个我们在后面的内容可以看到。
现在的ngrok服务,普通开发者可以免费的注册使用,但只能使用一个端点的配置,流量也有限制(2GB/月),这个机制可能可以很好的防止这个服务被滥用,从而提供更好的服务质量和稳定性。对于普通开发和调试,已经基本够用了。如果有多个Web应用需要发布,也可以考虑注册多个账号,或者在本地部署haproxy等使用APP路径进行区分。但如果用于商业,可以考虑购买他们的付费服务。在保证网络带宽和质量的前提下,可以将应用部署在机构的网络之中,同时提供高质量的应用服务。
原理
从官网的内容来看,ngrok虽然声称其主要业务是互联网应用反向代理服务,但基于已经存在一个名为ngrok的软件工具,我们可以合理的推论,ngrok这个网络服务,就是建立在这个同名的ngrok工具和技术基础之上的。整个系统包括以下概念和组成部分:
- 互联网端点
就是对于外部互联网用户而言,最终在互联网访问的服务的地址和路径,而无论真正的Web应用部署在何处(特别是以一个内部网络),或者使用何种技术来实现。
这个端点是由ngrok服务平台自动分配和提供的,当然如果是付费用户,也可以自己定义和关联Web应用的域名。
- ngrok服务和平台
提供端点服务的平台。这里ngrok是作为应用服务平台提供的。用户不需要自己安装和配置ngrok服务,而只需要注册一个账户,获取相关的授权和配置信息即可。
- ngrok客户端
要使用ngrok需要在本地主机或者本地网络内部部署一个ngrok客户端软件。这个软件可以基于配置信息,在客户端和ngrok服务之间建立一个协议隧道和逻辑连接。当外部用户访问互联网端点的时候,就可以将请求导向相关联的隧道和最终的应用服务端口。
- 隧道
ngrok启动之后,就可以在ngrok客户端和服务之间建立一个应用协议级别的网络隧道,来传输请求和响应的网络流量。ngork通过token和相应的加密机制来保证隧道的安全。而且对于Web应用而言,这个过程是完全透明的,无需做任何修改和调整。
笔者感觉,ngrok并不完全是VPN或者网络级别的协议,因为它在启动时,可以选择和指定协议,现有支持的协议包括HTTP、TLS和TCP。这样就提供了很大的灵活性,比如可以使用TCP协议,就可以支持数据库发布和访问。
- 应用程序模块(SDK)
ngrok客户端除了可以除了作为一个Web应用代理的方式为Web应用提供分发的模式之外,还有一个应用程序模块的模式。它可以作为一个应用程序模块(如npm模块)在开发的时候,嵌入到Web应用中。这样在Web应用启动的时候,就可以直接作为一个有机和集成的组成部分,像互联网交付应用了。这样做的好处是可以完全不用考虑Web应用部署和配置的问题,部署在任何地方,都可以直接开展应用。
笔者还有一个感想,现在最主流的开源Web服务器产品应该是nginx,它也可以作为反向代理服务使用。现在nginx也成立了商业公司。其实它来做这种反向代理服务网服务,可能是最合适的,也应该非常有竞争力。
特点和优势
按照其官方的说法,ngrok与传统的反向代理不同,它不完全转发到IP地址,而是通过在应用程序旁边或内部运行的轻量级代理软件,将连接发送到上游服务。这种独特的体系结构与传统模型相比,具有几个重要的优势。
- 独立于环境
ngrok可以让应用程序在任何地方使用任何方式进行工作。用户可以将Web应用和服务运行在标准服务器或者云计算环境中,也可以将其运行在IOT设备和树莓派上,当然,也可以运行在开发者的主机甚至笔记本电脑上,对于使用者而言没有任何差异。
- 统一和一致的入口
ngrok将传统的一堆入口工具整合到一个平台中。在传统上,为应用程序服务创建入口需要将多个不同的软件组件拼接在一起,包括反向代理、负载均衡、API网关、防火墙、交付网络、WAF、缓存层、应用程序中间件、DDoS 防护等,而ngrok可以将这些组件折叠成一个具有统一配置和可观察性的平台。
- 更快投入生产
ngrok可帮助您更快地将应用程序投入生产。
通常情况下,要使做好生产准备,需要进行大量的设置工作。ngrok可以自动完成相关的设置,以便您可以专注于构建应用程序而不是网络配置。
- 可重复使用的应用程序框架
ngrok让Web运营人员不需要再次构建身份验证、流量限制、或其他公共化的功能。这些功能都可以在ngrok上实现。ngrok的模块系统使开发者能够花更少的时间构建通用功能,而花更多的时间为应用程序构建业务和新功能。
- 停止使用网络集成语言。
尽管已经使用高级语言抽象化了开发人员的复杂性,但人们仍然期望软件工程师能够解决晦涩难懂的网络细节。ngrok 抽象了CIDR、端口和TLS证书等低级概念的复杂性,并为您提供了对身份验证和请求路由等应用程序原语的控制。
- 合约控制
ngrok为Web入口平台建立合约化的应用程序控制。
优秀的软件是建立在组件之间明确定义的契约之上的。随着越来越多的业务逻辑被推送到应用程序前面的代理,反向代理和上游应用程序之间的契约变得至关重要。他们之间行为的意外变化会导致事件发生。传统上,该合同是在IT票据中隐式定义的。
ngrok的Agent SDK改变了这一点。相反,应用程序本身通过API 准确定义了它期望入口平台代表其执行哪些操作以及它期望如何接收有关这些行为的信息。
这是一种新的、更安全的编程模型,开发人员可以安全地将附加功能卸载到入口平台,而不必担心合约被破坏。 即用
- 即付即用
与其他未公开定价、只有企业才能负担得起的网络软件不同,任何人只需一张信用卡就可以开始使用 ngrok 的付费功能。ngrok 的定价是公开的、可预测的,您只需按使用量付费
- 消除环境差异错误
开发人员都在测试和部署时经历过在不同的环境中出现故障的痛苦。由于ngrok可以在任何地方使用,因此您可以在本地开发环境中运行它,就像运行它来提供生产服务一样。
- 作为服务
ngrok通过为用户运营全球应用交付网络来减轻他们的运营负担。
全球交付网络可以加速您的应用程序,但操作起来确实很痛苦。与您需要自行配置和运行的可部署网络软件不同,ngrok 是一项完全托管的全球服务。您可以花更少的时间操作网络基础设施和解决丢失的数据包,而将更多的时间用于为客户创造价值。
- 为开发人员而设计
ngrok让开发人员能够通过一流的工具进行控制。包括功能完整丰富的CLI命令;原生语言的SDK;能够自动执行配置任务的HTTP API等等;丰富的文档;方便观察和自动化的程序事件等等。
- 全球化
ngrok为可以为全球客户Web应用程序。它通过部署在全球各地的服务器系统来均衡负载,除了有效的减少TCP和TLS设置往返时间来提高应用程序客户端的访问速度外,ngrok还将应用程序所配置的模块行为推送到其全局边缘,从而将身份验证、转换、负载平衡等功能模块尽可能的靠近用户。
- 网络微域(Micro-Segmetation)
ngrok最终实现了真正的针对不同工作负载并进行隔离的第四层网络安全。
传统的网络架构通常允许应用程序在同一网络上直接相互通信,而无需通过强制执行身份验证和策略的入口网关。这显然可能造成一些网络安全的风险。ngrok为不同的应用程序实现了真正的网络隔离,无需任何复杂的网络策略,因此访问它们的唯一方法是通过其端点URL,即使它们实际是在同一个主机或者系统上相邻运行。
其他选项
在查阅资料的过程中,笔者也发现其实国内也有类似的产品和服务。可能不是完全同类的产品,但应该都是可以解决类似需求或者是解决方案的一个组成部分,这里简单列举和说明一下:
- 花生壳
花生壳被定义为"内网穿透"软件和服务。它也是以客户端软件+网络服务的方式来提供服务。但笔者个人感觉它的产品设计主要还是面向普通个人用户,UI和功能都做的不错,但商业化气息比较浓。一些比较高级的服务和功能收费比较高,另外在中国使用这些网络服务,也会受到很多限制。
- FRP
相比较ngrok或者花生壳而言,frp就是一个DIY的技术方案了。用户需要自行架构frp网络来实现相应的需求。frp分为客户端和服务端,frp服务端(frps)运行在VPS上,接收网络请求;frp客户端(frpc)运行在本地网络,提供流量转发和中继。
frp是一个github托管项目,它的主要程序使用go语言编写,也是一个开源软件。
- Zerotier
ZeroTier是一种软件定义的广域网络(SD-WAN)技术,它可以用于简化企业网络连接和管理。它允许用户通过互联网创建一个虚拟的全球性的"局域网",然后在这个网络中开展应用。这是一个网络层面的解决方案。但它也有一些限制,就是需要使用开放的zerotier网络服务,并且需要预先安装客户端软件。
对于一些比较特别的Web应用发布场景比如跨地域内部测试,演示而言,Zerotier提供了一个比较另类的解决方案。它不是将应用发布到互联网之上,而是将有需求的客户端纳入到局域网之内,可能会适合一些使用场景吧(比如有限的开发网络应用)。类似的方案和思路还包括WireGuard。
安装和使用
本章节我们具体说明一下ngrok的安装和使用过程,让读者有一个更直观清晰的理解。假设我们已经有了一个在本地运行的Web应用,这时需要使用ngrok将其发布到互联网之上。相关的基本操作和过程如下。
注册账号
作为一个网络服务,需要先注册一个用户。在它的官方网站上,可以方便的使用一个电子邮件地址来注册一个用户账号。
获取认证码
成功注册账号,并且登录系统之后,在Your Authtoken页面,就可以获取一个认证码(下图)。这个认证码在配置ngrok软件时需要使用来进行工作,用户需要先记录和保存下来以备后续使用。
下载配置客户端软件
要在本地使用ngrok服务,需要下载并且运行相应的客户端软件,这个软件也是ngrok。以linux系统为例,下载和配置的过程如下:
shell
// 下载软件压缩包
wget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz
// 解压并安装
sudo tar -xvzf ngrok-v3-stable-linux-amd64.tgz -C /usr/local/bin
// 检查安装
which ngrok | xargs ls -l
-rwxr-xr-x 1 root root 24870912 2月 8 03:32 /usr/local/bin/ngrok
// 配置token
ngrok config add-authtoken mytoken
基本上ngrok客户端就是一个单一的可执行文件,这个文件大概24M,位于/usr/local/bin目录中(解压时的设置),可以随时调用执行。
使用config参数,可以为当前用户配置authtoken,这样当ngrok执行时,可以进行用户认证和配置。
启动程序
在正确的安装和配置ngrok之后,可以使用ngrok命令来启动软件(下图):
ngrok http http://localhost:8090
笔者的理解,这个命令可以让ngrok建立一个http隧道,可以将远程HTTP端点上接收到的请求,中继转发到本地的侦听端口,这样就可以使用公网地址来访问这个web应用了。
需要注意的是,这个公网地址是以一个动态的DNS域名的形式提供的。下次启动的地址可能会改变(付费订阅模式应该可以使用固定域名)。
我们还可以看到,ngrok还提供了监控和管理功能,我们可以看到相关的请求和响应性能信息,对于开发者评估应用状态和性能是非常有用的。
作为静态文件服务
通常我们使用ngrok的使用场景是发布Web应用端口。但考虑到都是HTTP协议,理论上我们也可以发布一个通用的Web服务,比如静态的HTML和通用文件服务。一般的想法是我们还需要先使用Nginx这种标准的Web服务器来创建一个Web服务,但其实ngrok提供了可以直接发布文件目录的服务模式,这个特性名为"Serve directory files"。
如果我们想将一个文件夹使用HTTP协议模拟Web服务器发布到公网之上。可以使用以下的命令(windows平台):
ngrok http "file://C:\Users\alan\Directory Name"
相关文档和详情,可以参考其技术文档。
应用集成
ngrok还提供了一个可能会很有意义的功能,叫做Agent SDK,就是可以作为一个模块,集成到应用系统当中。
我们可以看以下代码,应该就比较容易理解这个特性了:
js
const ngrok = require("@ngrok/ngrok");
(async function () {
const listener = await ngrok.forward({
addr: 8080,
authtoken_from_env: true,
});
console.log(`Ingress established at: ${listener.url()}`);
})();
从代码来看和ngrok客户端的工作方式本质上并没有什么差别,也是网络端口监听中继的模式。但使用SDK的好处是不需要单独的部署ngrok,对于运维、部署和管理而言更加简便。现在的Agent SDK支持Go、JS、Python、Rust等系统,很快会支持Java。
小结
本文讨论一个除了NAT端口映射、VPS网络桥接之外的内网Web应用的互联网发布的技术方案:ngrok网络服务。简单探讨了这几种方案的差异,描述了ngrok方案的大致原理和操作过程。