node.js - 在没有 SSH 的情况下,像 'Localtunnel' 这样的隧道服务如何工作?

标签 node.js networking localhost ssh-tunnel localtunnel

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

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

There services (localtunnel for example) creates a tunnel from their server back to port 3000 on your dev box. It functions pretty much exactly like an SSH tunnel, but doesn’t require that you have a server.



我试过从它的 github 存储库中读取代码,我的理解是:
  • 这些服务有一个公共(public)可用的服务器,它生成不同的 URL,当我们点击该 URL 时,它将请求转发到与该 URL 对应的 localhost。
  • 所以基本上它就像代理服务器一样工作。

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

    最佳答案

    简答 (TL;DR)

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

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

    视频演示

    如果您更喜欢视频播放,我刚刚在 UtahJS Conf 2018 上就​​此发表了演讲,其中我还谈到了所有其他潜在的解决方案:SSH Socksv5 代理(您提到过)、VPN、UPnP、DHT,继电器等:

    Access Ability: Access your Devices, Share your Stuff

    whatever

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

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

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

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

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

    How does a remote client access the server on my localhost?



    1. 远程套接字

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

    因此,想象一下中继(在您的情况下是本地隧道代理)使用端口 7777 从“ Remote ”(如您的计算机)接收流量,并且您的套接字号(您计算机上随机选择的源地址)是 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]
    

    两个连接都是“传入”连接,但“南端”的远程连接被授权接收来自另一个传入源的流量(没有某种形式的授权 session ,任何人都可以声称使用该端口或地址并劫持您的流量)。
    [Client Computer]  (tcp 5678)       [Proxy Service]      (tcp 1234)   [Your Computer]
       [netcat]      -------------->     <--[Relay]-->     <------------    [remote]
    

    2. 多路复用器

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

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

    MITM vs p2p

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

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

    花药方式需要 ACME/Let's Encrypt 集成(即 Greenlock.js ),以便流量 保持加密,端到端 , 将 tls 流量路由到客户端而不对其进行解密。此方法的作用为 点对点用于所有实际目的的 channel (中继只是互联网网络上的另一个不透明的“开关”,不知道流量的内容)。

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

    现在,构建在 libp2p 上的解决方案也为您提供了一个虚拟化的对等连接,但它更加间接,并且需要通过不受信任的方进行路由。我不喜欢它,因为它通常更慢,而且我认为它风险更大。我坚信网络联盟从长远来看会战胜匿名化(如 libp2p)。 (对于我们的用例,我们需要一些可以联合的东西 - 由独立的受信任方运行 - 这就是我们以我们所做的方式构建我们的解决方案的原因)

    关于node.js - 在没有 SSH 的情况下,像 'Localtunnel' 这样的隧道服务如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52596901/

    相关文章:

    .net - Tcpip 监听器套接字 SSL 流如此困惑

    networking - TCP/IP 校验和有多稳健

    linux - 尝试在 OpenShift : cannot patch GhostDriver so that it can bind on the server IP address 上运行 PhantomJS

    javascript - 将 duktape 2.1.0 中的原生 C 模块加载到

    node.js - Nodejs 服务器脚本未知结果

    node.js - 环回中的 'cb' 是什么意思?

    node.js - meteor 中的 gmail 发送 api 失败,错误代码为 400

    c - 何时使用动态 AES 加密和固定 key AES 加密?

    nginx proxy_pass 到本地主机

    html - WordPress 生成的文件用 HTML 编辑