26

我想了解我的本地 IP 地址 (localhost) 如何暴露给 Internet。为此,我在[这里]阅读了一种使用 SSH 进行端口转发的方法。它基本上使用 SSH 从公开可用的服务器路由到我们的本地主机。

但我想知道像“LocalTunnel”这样的服务是如何工作的?在上面的文章中,它是这样写的:

那里的服务(例如 localtunnel)会创建一条从他们的服务器返回到您的开发盒上的端口 3000 的隧道。它的功能与 SSH 隧道非常相似,但不需要您拥有服务器。

我尝试从它的 github 存储库中读取代码,我的理解是:

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

  • 所以基本上它就像代理服务器一样工作。

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

4

1 回答 1

45

简答 (TL;DR)

远程(即您计算机上的本地隧道软件)初始化与中继的连接(即 localtunnel.me)充当多路复用代理,当客户端(即 Web 浏览器)连接时,中继通过附加特殊的带有网络信息的标头。

Browser <--\                   /--> Device
Browser <---- M-PROXY Service ----> Device
Browser <--/                   \--> Device

视频演示

如果你更喜欢视频预览,我刚刚在 UtahJS Conf 2018 上做了一个演讲,其中我也谈到了所有其他潜在的解决方案:SSH Socksv5 代理(你提到的)、VPN、UPnP、DHT、继电器等:

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

任何

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

localtunnel、ngrok 和 Telebit 如何工作(长答案)

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

虽然我不知道 localtunnel 是如何实现的确切内部结构,但我可以解释一下它通常是如何完成的(以及我们是如何做到的),并且很可能与他们的实现方式几乎相同。

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

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

1.远程插座

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

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

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

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

Devices:  [Proxy Service]            (tcp 5678)             [Client Computer]
Software:    [Relay]          <------------------------         [netcat]

如果您使用的是 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]

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

[Client Computer]  (tcp 5678)       [Proxy Service]      (tcp 1234)   [Your Computer]
   [netcat]      -------------->     <--[Relay]-->     <------------    [remote]

2. 多路复用器

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

Browser <--\                   /--> Device
Browser <---- M-PROXY Service ----> Device
Browser <--/                   \--> Device

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

<src-address>,<src-port>,<sni>,<dst-port>,<protocol-guess>,<datalen>

例如

172.2.3.4,1234,example.com,443,https,1024

该信息可以在路由的每个数据包之前准确发送或​​附加到每个数据包。

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

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

旁注/咆哮:端口与 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)

中间人与 p2p

你仍然可以通过几种不同的方式来解决这个问题(这就是我想为 Telebit 提供一个无耻的插件的地方,因为如果你喜欢去中心化和点对点,这就是我们大放异彩的地方!)

如果您只使用 tls sni 进行路由(这是我上次检查时 localtunnel 和 ngrok 的默认工作方式),所有流量都会在中继处解密

Anther 方式需要 ACME/Let's Encrypt 集成(即Greenlock.js),以便流量保持加密,端到端,将 tls 流量路由到客户端而不解密它。这种方法在所有实际用途中都充当对等通道(中继充当 Internet 网络上的另一个不透明“开关”,不知道流量的内容)。

此外,如果远程(例如,通过安全 WebSockets)和客户端都使用 https,那么客户端看起来就像任何其他类型的 https 请求,并且不会受到配置不当的防火墙或其他恶劣/不利的网络条件的阻碍.

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

于 2018-10-02T18:27:21.423 回答