没有SSH的隧道服务(如“ Localtunnel”)如何工作?

Kau*_*l28 5 networking localhost node.js ssh-tunnel localtunnel

我想了解如何将本地IP地址(本地主机)公开给Internet。为此,我已经阅读了[此处]使用SSH进行端口转发的方法。基本上,这是使用SSH从公用服务器路由到我们的本地主机的。

但是我想知道“ LocalTunnel”之类的服务如何工作?在以上文章中,其内容如下:

那里的服务(例如localtunnel)在它们的服务器上创建了一条隧道,可以回到您的开发箱上的端口3000。它的功能几乎与SSH隧道完全相同,但是不需要您拥有服务器。

我试图从它的github仓库中读取代码,我的理解是:

  • 这些服务有一个公开可用的服务器,该服务器生成不同的URL,当我们单击该URL时,它将请求转发到与该URL对应的localhost。

  • 因此,基本上,它像代理服务器一样工作。

这些理解正确吗?如果是,那么我不明白的是这些服务器如何访问我的计算机上运行的某些本地主机?它如何执行请求呢?我在这里想念的是什么?是我引用的代码。

Coo*_*J86 9

TL; DR

远程服务器(即计算机上的localtunnel软件)初始化与中继的连接(即localtunnel.me)作为多路复用代理,当客户端(即Web浏览器)连接时,中继通过附加特殊命令来多路复用远程与客户端之间的连接。具有网络信息的标题。

Browser <--\                   /--> Device
Browser <---- M-PROXY Service ----> Device
Browser <--/                   \--> Device
Run Code Online (Sandbox Code Playgroud)

localtunnel,ngrok和Telebit如何工作

我是Telebit的作者,该公司提供的服务具有与ngrok,localtunnel和libp2p提供的功能类似的功能(以及远程/客户端和中继/服务器自行运行的开源代码)。

尽管我不知道localtunnel如何实现的确切内部原理,但我可以向您解释它的一般执行方式(以及我们的执行方式),并且很可能与他们的执行方式几乎相同。

如果您喜欢录像带,我刚刚在2018年犹他州JS Conf大会上发表了演讲,在此我还谈到了所有其他可能的解决方案:SSH Socksv5代理(您提到),VPN,UPnP,DHT,继电器等:

访问能力:访问您的设备,共享您的资料

幻灯片:http : //telebit.cloud/utahjs2018

您好奇的魔术发生在两个地方:远程套接字和多路复用器

远程客户端如何访问本地主机上的服务器?

1.远程套接字

这很简单。当您运行“远程”(telebit,ngrok和localtunnel在这方面几乎相同)时,实际上是您的计算机发起了请求。

因此,假设中继(在您的情况下为localtunnel代理)使用端口7777 接收来自“远程”(例如您的计算机)的流量,并且套接字号(计算机上随机选择的源地址)为1234:

Devices:  [Your Computer]          (tcp 1234:7777)          [Proxy Server]
Software:    [Remote]          ----------------------->        [Relay]
                                (auth & request 5678)
Run Code Online (Sandbox Code Playgroud)

但是,实际上,连接到您的客户端(例如浏览器,netcat或其他用户代理)也会通过中继发起请求。

Devices:  [Proxy Service]            (tcp 5678)             [Client Computer]
Software:    [Relay]          <------------------------         [netcat]
Run Code Online (Sandbox Code Playgroud)

如果您使用的是TCP端口,则中继服务会保留内部映射,就像NAT

Internal Relay "Routing Table"

Rule:
Socket remote[src:1234]    --- Captures ------>  ALL_INCOMING[dst:5678]

Condition:
Incoming client[dst:5678]  --- MATCHES ------->  ALL_INCOMING[dst:5678]

Therefore:
Incoming client[dst:5678]  --- Forwards To --->  remote[src:1234]
Run Code Online (Sandbox Code Playgroud)

这两个连接都是“传入”连接,但是“南端”上的远程连接被授权接收来自另一个传入源的流量(没有某种形式的授权会话,任何人都可以声明使用该端口或地址并劫持您的流量)。

[Client Computer]  (tcp 5678)       [Proxy Service]      (tcp 1234)   [Your Computer]
   [netcat]      -------------->     <--[Relay]-->     <------------    [remote]
Run Code Online (Sandbox Code Playgroud)

2.多路复用器

您可能已经注意到,上面的描述中存在严重缺陷。如果仅按原样路由流量,则您的计算机(远程)一次只能处理一个连接。如果另一个客户端(浏览器,netcat等)跳上了连接,则您的计算机将无法分辨出哪些数据包来自何处。

Browser <--\                   /--> Device
Browser <---- M-PROXY Service ----> Device
Browser <--/                   \--> Device
Run Code Online (Sandbox Code Playgroud)

本质上,中继(即localtunnel代理)和远程(即您的计算机)的作用是将标头放在客户端要接收的所有数据的前面。它必须与HAProxy的PROXY协议非常相似,但也适用于非本地流量。它可能看起来像这样:

<src-address>,<src-port>,<sni>,<dst-port>,<protocol-guess>,<datalen>
Run Code Online (Sandbox Code Playgroud)

例如

172.2.3.4,1234,example.com,443,https,1024
Run Code Online (Sandbox Code Playgroud)

该信息可以在路由的每个数据包之前或之后发送。

同样,当远程对中继做出响应时,它必须包括该信息,以便中继知道数据包正在响应哪个客户端。

有关详细信息,请参阅https://www.npmjs.com/package/proxy-packer

旁注/ Rant:端口与TLS SNI

我最初使用tcp端口给出的解释是因为它很容易理解。但是,localtunnel,ngrok和telebit都可以使用tls 服务器名指示符(SNI)而不是依赖端口号。

[Client Computer]        (https 443)       [Proxy Service]      (wss 443)   [Your Computer]
 [netcat+openssl]   -------------------->   <--[Relay]-->     <------------    [remote]
 (or web browser)  (sni:xyz.somerelay.com)                 (sni:somerelay.com)
Run Code Online (Sandbox Code Playgroud)

MITM与P2P

还有一些其他方法可以解决此问题(这是我想为Telebit提供一个无耻插件的地方,因为如果您要进行去中心化和点对点,这就是我们的亮点!)

如果仅使用tls sni进行路由(这是我上次检查默认情况下localtunnel和ngrok都默认工作的方式),那么所有流量都将在中继解密

另一种方法需要ACME / Let的Encrypt集成(即Greenlock.js),以使流量保持加密,端到端,将tls流量路由到客户端而不进行解密。出于所有实际目的,此方法用作对等通道(中继仅充当Internet网络上的另一个不透明的“交换机”,不了解流量的内容)。

此外,如果将https同时用于远程服务器(例如,通过Secure WebSockets)和客户端,则客户端看起来就像任何其他类型的https请求一样,不会受到防火墙配置不佳或其他恶劣/不利的网络条件的影响。

现在,基于libp2p构建的解决方案为您提供了虚拟化的对等连接,但是它的间接性要强得多,并且需要通过不受信任的各方进行路由。我不喜欢它,因为它通常速度较慢,并且我认为它的风险更大。我坚信网络联盟将长期战胜匿名化(如libp2p)。(对于我们的用例,我们需要可以被联合的东西-由独立的受信方来运行-这就是为什么我们以这种方式构建解决方案的原因)