Как туннельные сервисы, такие как Localtunnel, работают без SSH?
Я хочу понять, как мой локальный IP-адрес (localhost) может быть подключен к Интернету. Для этого я прочитал [здесь] метод переадресации портов с использованием SSH. Который в основном делает маршрутизацию от общедоступного сервера до нашего локального хоста, используя SSH.
Но мне интересно, как работает сервис типа LocalTunnel? В вышеприведенной статье написано следующее:
Там службы (например, localtunnel) создают туннель от своего сервера до порта 3000 на вашем устройстве разработки. Он работает почти так же, как туннель SSH, но не требует наличия сервера.
Я попытался прочитать код из репозитория GitHub, и я понял:
У этих служб есть общедоступный сервер, который генерирует разные URL-адреса, и когда мы нажимаем этот URL-адрес, он перенаправляет запрос на локальный хост, соответствующий этому URL-адресу.
Так что в основном это работает как прокси-сервер.
Это понимание правильно? Если да, то чего я не понимаю, так это того, как эти серверы имеют доступ к некоторому локальному узлу, работающему на моем компьютере? Как это выполнить запрос к нему? Что мне здесь не хватает? Вот код, на который я ссылался.
1 ответ
TL;DR
Remote (т.е. программное обеспечение localtunnel на вашем компьютере) инициализирует соединение с ретранслятором (то есть localtunnel.me) действует как мультиплексный прокси-сервер, а когда клиенты (т.е. веб-браузеры) подключаются, ретранслятор мультиплексирует соединения между удаленными и клиентами, добавляя специальные Заголовки с сетевой информацией.
Browser <--\ /--> Device
Browser <---- M-PROXY Service ----> Device
Browser <--/ \--> Device
Как работают localtunnel, ngrok и Telebit
Я являюсь автором Telebit, который предоставляет сервис с аналогичными функциями, которые предоставляют ngrok, localtunnel и libp2p (а также с открытым исходным кодом для удаленного / клиентского и ретрансляторного / серверного приложений для его запуска самостоятельно).
Хотя я не знаю точных внутренних особенностей того, как реализован localtunnel, я могу дать вам объяснение того, как это обычно делается (и как мы это делаем), и, скорее всего, оно почти идентично тому, как они это делают.
Если вы предпочитаете видео preso, я только что выступил с докладом об этом на UtahJS Conf 2018, в котором я немного расскажу и обо всех других потенциальных решениях: прокси SSH Socksv5 (которые вы упомянули), VPN, UPnP, DHT, Реле и т.д:
Возможность доступа: доступ к вашим устройствам, поделиться своими вещами
Слайды: http://telebit.cloud/utahjs2018
Волшебство, которое вас интересует, происходит в двух местах: удаленный разъем и мультиплексор.
Как удаленный клиент получает доступ к серверу на моем локальном хосте?
1. Дистанционная розетка
Это довольно просто. Когда вы запускаете "remote" (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
По сути, ретранслятор (т.е. прокси-сервер localtunnel) и удаленный (т.е. ваш компьютер) размещают заголовок перед всеми данными, которые должны быть получены клиентом. Он должен быть чем-то очень похожим на протокол PROXY протокола 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 для более подробной информации.
Sidenote/Rant: Порты против TLS SNI
Первоначальное объяснение я дал, используя порты TCP, потому что это легко понять. Однако localtunnel, ngrok и telebit могут использовать индикатор tls servername (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
Есть еще несколько разных способов сделать это (и именно здесь я хочу дать бесстыдный плагин для телебита, потому что если вы находитесь в децентрализации и одноранговой связи, это то, где мы сияем!)
Если вы используете только tls sni для маршрутизации (именно так localtunnel и ngrok работают по умолчанию в прошлый раз, когда я проверял), весь трафик расшифровывается на ретрансляторе.
Другой путь требует интеграции ACME/Let's Encrypt (то есть Greenlock.js), чтобы трафик оставался зашифрованным, сквозным, направляя трафик tls клиенту, не расшифровывая его. Этот метод функционирует как одноранговый канал для всех практических целей (ретранслятор действует как еще один непрозрачный "коммутатор" в сети Интернет, не подозревая о содержимом трафика).
Кроме того, если https используется как для удаленных (например, через Secure WebSockets), так и для клиентов, тогда клиенты выглядят так же, как и любой другой тип запроса https, и не будут препятствовать плохо настроенным брандмауэрам или другим неблагоприятным / неблагоприятным условиям сети.,
Теперь решения, основанные на libp2p, также предоставляют виртуализированное одноранговое соединение, но оно гораздо более косвенное и требует маршрутизации через ненадежных сторон. Я не фанат этого, потому что это обычно медленнее, и я считаю это более рискованным. Я верю, что сетевая федерация победит анонимность (например, libp2p) в долгосрочной перспективе. (для нашего варианта использования нам нужно было что-то, что могло бы быть объединено - выполнялось независимо доверенными сторонами - вот почему мы создали наше решение так, как мы это сделали)