没有 SSH 的情况下,像“Localtunnel”这样的隧道服务如何工作?
Posted
技术标签:
【中文标题】没有 SSH 的情况下,像“Localtunnel”这样的隧道服务如何工作?【英文标题】:How tunneling services like 'Localtunnel' works without SSH? 【发布时间】:2019-03-06 21:43:23 【问题描述】:我想了解我的本地 IP 地址 (localhost) 是如何暴露给 Internet 的。为此,我阅读了[here] 一种使用 SSH 进行端口转发的方法。这基本上是使用 SSH 从公开可用的服务器路由到我们的本地主机。
但我想知道像“LocalTunnel”这样的服务是如何工作的?上面的文章是这样写的:
那里的服务(例如 localtunnel)创建一条从他们的服务器返回到您的开发盒上的端口 3000 的隧道。它的功能与 SSH 隧道非常相似,但不需要您拥有服务器。
我尝试从它的 github 存储库中读取代码,我的理解是:
这些服务有一个公开可用的服务器,它生成不同的 URL,当我们点击该 URL 时,它将请求转发到与该 URL 对应的 localhost。
所以基本上它就像代理服务器一样工作。
这些理解正确吗?如果是,那么 我不明白的是,这些服务器如何访问我计算机上运行的某些本地主机?它如何执行对它的请求?我在这里缺少什么? Here 是我提到的代码。
【问题讨论】:
【参考方案1】:简答 (TL;DR)
Remote(即您计算机上的 localtunnel 软件)初始化与 Relay 的连接(即 localtunnel.me)充当多路复用代理,当客户端(即 Web 浏览器)连接时,Relay 复用远程和客户端之间的连接通过附加带有网络信息的特殊标头。
Browser <--\ /--> Device
Browser <---- M-PROXY Service ----> Device
Browser <--/ \--> Device
视频演示
如果您更喜欢视频预览,我刚刚在 UtahJS Conf 2018 上做了一次演讲,其中我还谈到了所有其他潜在的解决方案:SSH Socksv5 代理(您提到的)、***、UPnP 、DHT、继电器等:
Access Ability: Access your Devices, Share your Stuff
幻灯片:http://telebit.cloud/utahjs2018
localtunnel、ngrok 和 Telebit 如何工作(长答案)
我是Telebit 的作者,它提供的服务具有与 ngrok、localtunnel 和 libp2p 提供的功能相似的服务(以及远程/客户端和中继/服务器的开源代码以自行运行) .
虽然我不知道 localtunnel 如何实现的确切内部结构,但我可以向您解释它一般是如何完成的(以及我们如何 这样做),而且很可能与他们的做法几乎相同。
您好奇的魔法发生在两个地方:远程套接字和多路复用器。
远程客户端如何访问我本地主机上的服务器?
1。远程套接字
这很简单。当您运行“远程”(telebit、ngrok 和 localtunnel 在这方面的工作方式几乎相同)时,实际上是您的计算机发起请求。
因此想象一下,中继(在您的情况下为 localtunnel 代理)使用端口 7777 来接收来自“远程”(如您的计算机)的流量和您的 socket 号码(在您的计算机上随机选择的源地址)是 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 servername indicator (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)
MITM 与 p2p
仍然有几种不同的方法可以解决这个问题(这就是我想为 Telebit 提供一个无耻的插件的地方,因为如果你喜欢去中心化和点对点,这就是我们大放异彩的地方!)
如果您只使用 tls sni 进行路由(这是我上次检查时 localtunnel 和 ngrok 的默认工作方式)所有流量都在中继处解密.
Anther 方式需要 ACME/Let's Encrypt 集成(即Greenlock.js),以便流量保持加密、端到端,无需解密即可将 tls 流量路由到客户端。出于所有实际目的,此方法充当 点对点 通道(中继仅充当 Internet 网络上的另一个不透明“开关”,不知道流量的内容)。
此外,如果 remotes(例如,通过安全 WebSockets)和客户端都使用 https,那么客户端看起来就像任何其他类型的 https 请求,而 不会受到配置不当的防火墙或其他恶劣/不利的网络条件的阻碍。
现在,基于 libp2p 构建的解决方案也为您提供了虚拟化的对等连接,但它更加间接,并且需要通过不受信任的各方进行路由。我不喜欢这种方式,因为它通常速度较慢,而且我认为它的风险更大。我坚信网络联盟将在长期内战胜匿名化(如 libp2p)。 (对于我们的用例,我们需要可以联合的东西——由独立的受信任方运行——这就是我们以我们的方式构建解决方案的原因)
【讨论】:
以上是关于没有 SSH 的情况下,像“Localtunnel”这样的隧道服务如何工作?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 ssh 在没有 -t 的情况下等待我的子 shell,然后用 -t 杀死它们?
是否可以使用 ngrok 或 localtunnel 来测试本地 gRPC 服务器?