Аналоги ngrok на linux

Обновлено: 03.07.2024

ngrok — это сервис, позволяющий создавать туннели на локальный компьютер пользователя. Иными словами, резервируется публичный адрес, все обращения по которому пробрасываются на локальный порт.

К сожалению, с 2016 года поддержка open-source версии клиента (ngrok v1) прекращена, и чтобы воспользоваться сервисом, нужно запустить закрытую версию (ngrok v2), что во многих случаях неприемлемо. Данная статья описывает процесс изучения протокола, используемого официальным клиентом, и создания альтернативного открытого клиента.

А нужно ли оно? Альтернативы ngrok

Как ни странно, у данного сервиса очень мало альтернатив. Конкретно, три:

Serveo is temporarily disabled due to phishing.

Serveo will return in a few days with a few new restrictions to help dissuade abuse. Thanks for your patience!

Попробуем прослушать трафик официального приложения с помощью mitmproxy:

Видимо, клиент использует certificate pinning с самоподписанным сертификатом. Попробуем игнорировать ошибку:

Google по запросу «illegal WNDINC frame length» выдает библиотеку для Go для мультиплексирования TCP-соединений. Эта же библиотека упоминается в issue с призывом открыть исходники ngrok v2.

Библиотека muxado

Проверим, действительно ли ngrok использует библиотеку muxado:

Из вывода этой команды можно сделать несколько выводов (простите за тавтологию):

  1. ngrok действительно использует данную библиотеку.
  2. Автор не пытался как-либо обфусцировать исполняемый файл, так как в нем оставлены символы.

Также заметим, что ошибка от сервера была получена по защищенному (TLS) соединению, что означает, что протокол muxado используется внутри TLS-сессии. Это позволяет предположить, что поверх muxado данные передаются открытым текстом, так как дополнительное шифрование было бы избыточным. Таким образом, чтобы снять незашифрованный дамп траффика, достаточно перехватить вызовы (*stream).Read и (*stream).Write.

Прежде чем пытаться перехватывать вызовы, нужно понять, как передаются интересующие нас параметры. Для этого напишем простую программу на Go, использующую библиотеку (в качестве принимающей стороны будет выступать netcat):

Итак, для перехвата траффика нас интересуют:

  • Уникальный идентификатор потока (нужен для того, чтобы различать несколько одновременно активных потоков).
  • Указатель на буфер с данными.
  • Длина буфера с данными.

Осталось понять, где именно на стеке лежат нужные нам значения. Для этого воспользуемся gdb и выведем состояние стека на момент вызова функции.

Первый элемент данного массива — адрес возврата, и в передаче аргументов он принимать участие не может. Два последних, очевидно, представляют из себя адрес массива и его длину; так как указатель на поток идет в списке аргументов первым, логично предположить, что именно он находится во второй ячейке. Его можно (с оговорками) использовать в качестве уникального идентификатора потока.

Итак, теперь мы знаем, как расположены в памяти аргументы функции (*stream).Write (для (*stream).Read всё точно так же, так как у функций одинаковый прототип). Осталось реализовать сам перехват.

При попытке вызвать ngrok с данным хуком получаем краш следующего вида:

Тут нас ждет неожиданное препятствие в лице goroutines. Дело в том, что стек под горутины выделяется динамически: при недостатке места в существующем стеке он выделяется заново в другом месте, и текущее содержимое копируется. К сожалению, функции, генерируемые gcc, сохраняют старый указатель стека в регистре rbp (т.н. frame pointer), и при возврате из такой функции указатель стека начинает указывать на уже освобожденный старый стек (use-after-free). Таким образом, C тут не помощник.

Напишем скрипт для gdb, который будет распечатывать все передаваемые данные:

Это работает, но для полноценного дампа нужно сохранять и принимаемые данные. И тут возникает несколько проблем:

  • Чтобы прочитать принятые данные, нужно дождаться, пока функция завершит выполнение. Эта проблема решается установкой breakpoint'а на инструкцию ret.
  • Функция может считать меньше данных, чем планировалось, при этом количество реально считанных байт — одно из возвращаемых значений функции. Нужно понять, как передаются возвращаемые значения. (Также тривиально, достаточно распечатать стек после выполнения функции. Нужное число лежит по адресу $rsp+48).
  • Третья, и самая главная проблема. Вывод gdb не предназначен для автоматического парсинга (в качестве примера см. распечатку из раздела ABI), поэтому полученные таким образом дампы пригодны только для визуального анализа. (На самом деле это не проблема, так как протокол крайне прост и распознается с первого взгляда).

Открыв бинарник ngrok objdump'ом, можно заметить, что между секциями .text и .rodata присутствует зазор в 0xc10=3088 байт:

Этот же зазор присутствует и в самом файле, там пустое пространство заполнено нулевыми байтами. Это позволяет изменить записанный в файле размер сегмента, содержащего секцию .text (поиск/замена в hex-редакторе), и добавить в пустое пространство код для логгирования вызовов.

Инструкция относительного перехода на архитектуре x86_64 занимает 5 байт: опкод (E9) + смещение до конечного адреса (signed int). Так как размер исполняемого файла ngrok сильно меньше 2 гигабайт, эта инструкция позволяет передать управление в любую точку секции .text, в том числе в наш новый код.

Первая инструкция обоих функций занимает 9 байт, так что первые 5 байт инструкции можно заменить на инструкцию перехода:

Для вызова оригинальной функции достаточно выполнить исходную инструкцию и перейти по адресу func+9

С инструкцией ret в функции (*stream).Read все куда интереснее:

Инструкция ret (записана как retq, в противовес retf) занимает всего 1 байт, при этом следующая за ней инструкция является jump target'ом, поэтому изменять ее нельзя. Однако на саму инструкцию ret переход нигде не производится, поэтому ничто не мешает заменить ее на переход вместе с предыдущей инструкцией (после перехода, естественно, ее придется выполнить).

Таким образом, теперь у нас есть работающий инструмент для снятия дампов траффика с ngrok. Проверим его в действии!

Из этого дампа прекрасно видно внутреннее устройство протокола:

  • Очевидно, что потоки авторизации и создания туннеля инициируются клиентом, а потоки с собственно подключениями — сервером. Этого нет в логах, но это очевидно по соображениям здравого смысла.
  • В начале каждого потока передается 32-битное число — тип потока. Это 0 для авторизации, 1 для создания туннеля и 3 для входящих соединений.
  • Поток с типом -1 — heartbeat. Инициатор соединения периодически отправляет туда случайные 4 байта и ожидает получить их же на выходе. Таких потока создается 2 в обоих направлениях.
  • При получении входящего соединения передается 32-битный тип 3, 64-битное число L (little-endian) и JSON-объект длины L байт, описывающий соединение. После этого по соединению передаются сырые данные без каких-либо служебных пакетов.

Заключение

Так как muxado — open-source библиотека, протокол мультиплексирования можно изучить по исходникам. Приводить его здесь не имеет смысла.

Результатом работы стали библиотека на Python для работы с протоколом ngrok, и альтернативный консольный клиент, использующий данную библиотеку. GitHub

Найти местоположение устройства при помощи Социальной Инженерии

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md




Доступно в

Концепция Seeker проста, подобно тому, как мы размещаем фишинговые страницы для получения учетных данных, почему бы не разместить поддельную страницу, которая запрашивает ваше местоположение, как многие популярные веб-сайты, основанные на местоположении. Читать больше в блоге thewhiteh4t . Seeker Hosts является фальшивым веб-сайтом на встроенном PHP-сервере и использует ngrok для создания ссылки, которую мы будем перенаправлять к цели, веб-сайт запрашивает разрешение на местоположение и, если цель позволяет, мы можем получить:

  • Долгота
  • Широта
  • Точность
  • Высота - Не всегда доступно
  • Напрвление - Доступно, если пользователь движется
  • Скорость - Доступно, если пользователь движется

Наряду с информацией о местоположении мы также получаем информацию об устройстве без каких-либо разрешений:

  • Операционная система
  • Платформа
  • Количество ядер в CPU
  • Количество RAM - Приблизительные Результаты
  • Разрешение экрана
  • Информация о GPU
  • Данные браузера
  • Публичный IP-адрес

Этот инструмент является проверкой концепции и предназначен только для образовательных целей. Seeker показывает, какие данные может собирать вредоносный веб-сайт о вас и ваших устройствах, и почему вы не должны нажимать на случайные ссылки и разрешать критические разрешения, такие как местоположение и т.д.

Чем это отличается от IP GeoLocation

Другие инструменты и сервисы предлагают IP-геолокацию, которая НЕ является точной и не дает определения местоположения цели, а является приблизительным местоположением провайдера.

Seeker использует HTML API и получает разрешение на местоположение, а затем захватывает долготу и широту с помощью GPS оборудования, которое присутствует в устройстве, поэтому Seeker лучше всего работает со смартфонами, если отсутствует GPS-оборудование, например, на ноутбуке, Seeker откатится к IP-геолокации или будет искать кэшированные координаты.

Как правило, если пользователь принимает разрешение на определение местоположения, точность полученной информации составляет с точностью приблизительно до 30 метров, точность зависит от устройства.

The best free alternative to ngrok is Pagekite, which is also Open Source. If that doesn't suit you, our users have ranked more than 25 alternatives to ngrok and many of them is free so hopefully you can find a suitable replacement. Other interesting free alternatives to ngrok are Portmap.io (Freemium), sish (Free, Open Source), LocalXpose (Freemium) and beame-insta-ssl (Free, Open Source).

Pagekite

  • Freemium • Open Source
  • Mac
  • Windows
  • Linux
  • Android
  • BSD
Bring your localhost servers on-line. PageKite is software that gives your localhost servers names and makes them globally visible. It works with any computer and any Internet connection.
Pagekite vs ngrok opinions
Most users think Pagekite is a great alternative to ngrok.

Portmap.io

  • Freemium • Proprietary
  • Mac
  • Windows
  • Linux
Port forwarding service for exposing your local PC to Internet from behind firewall or without real IP address. Uses OpenVPN or SSH encrypted tunnel from localhost to Portmap.io. Most users think sish is a great alternative to ngrok.

LocalXpose

  • Freemium • Proprietary
  • Mac
  • Windows
  • Linux
  • Android
  • iPhone
LocalXpose vs ngrok opinions
Most users think LocalXpose is a great alternative to ngrok. Its free and support mutiple tunnels and GUI is good

beame-insta-ssl

  • Free • Open Source
  • Mac
  • Windows
  • Linux
  • Online
beame-insta-ssl is open-source and free to use! It makes it easy for any web developer to make use of encryption - and get secure communications.

2020-12 - The project is discontinued

Most users think beame-insta-ssl is a great alternative to ngrok.

Beeceptor

  • Freemium • Proprietary
  • Online
  • Software as a Service (SaaS)
Build a mock Rest API endpoint in seconds. Helps you in UI development, Webhooks, simulating delays, simulating exceptions and server errors, performance test, etc.

Packetriot

  • Freemium • Proprietary
  • Mac
  • Windows
  • Linux
  • Self-Hosted
Packetriot makes it simple to expose services and data on local and private networks to the Internet. You can serve static websites, dynamic web applications, test single-sign-on work-flows or build webhooks.

playit.gg

Making it easy to play games with friends since March 2020.
  • Freemium • Proprietary
  • Self-Hosted
  • Software as a Service (SaaS)

AlternativeTo is a free service that helps you find better alternatives to the products you love and hate.

Follow us on Facebook, Twitter or Instagram or chat with us on Discord. This is build Docker_20211119.5 .

Что такое Ngrok, наверное знает каждый разработчик web приложений, и многие им пользуются.

Присоединившись к новому большому проекту, над которым работают десятки разработчиков и QA специалистов, я столкнулся с тем, что разработка ведется удаленно на специально выделенных серверах.

А т.к. я уже несколько лет разработку приложений веду исключительно в докере, я никак не мог адаптироваться к текущему подходу.

Думаю все, кто более менее освоил работу в докере, уже не мыслят как можно разрабатывать без него. Причин на это много. Конечно, как и везде у докера есть своя цена и это тоже уже много раз обсуждалось.

Итак, новый проект не похож на предыдущие. Он имеет много зависимостей с другими сервисами, как внутренними так и внешними.

Большое количество внешних интерграций порождало проблему связи локального приложения с внешним миром. И если объединить внутренние сервисы используя docker netwokr не вызывало каких либо проблем, то необходимость связать внешний сервис уже требовал дополнительных инструментов.

Интеграции платежных систем всегда подразумевает, что будут callback (notification).

При такой необходимости, часто выбирают Ngrok. Хорошее решение, но в удобном варианте - платное. Особенно это ощущается, когда разработчиков много.

Т.к. Ngrok не подходил, первое что пришло в голову, создать виртуалку, на нее завести домен, и создавать ssh туннель с ним.

где Dockerfile callback-tunnel выглядел вот так

Данный подход решал проброс callback запросов от внешних провайдеров, но он был не надежный. Иногда при жестком разрыве соединения, порт на виртуалке оставался занятым. При совместной разработки необходимо было договариваться, кто какой порт будет использовать. Короче, решение такое себе, костыль.

Дальше - больше, при локальной разработке, бывает необходимость проверить приложение на другом устройстве, например на телефоне или планшете, или в определенной версии браузера поведение фронта не адекватное. И снова мысли об Ngrok.

В какой то момент мне попался список бесплатных инструментов решающих данную проблему. Сам список уже не найду, но один инструмент меня сильно заинтересовал, и я решил попробовать.

Fast Reverse Proxy

Сервер написан на Go
JS, Vue для Dashboard

Схема


Как поднимал

Подготовил на github репозиторий

Создал дроплет на Digital Ocean (5$ docker)

Установил туда nginx

Настроил nginx, он выступает как первый proxy server. Можно обойтись без него, но мне так было проще

Создал .env из .env-example и прописал необходимые переменные

запустил client-ский docker-compose

В зависимости от того какой указал REVERSE_PROXY_PERSONAL_ALIAS, будет мой URL.

В моем примере есть 3 хоста (обычно нужно для проекта), и в зависимости какой PERSONAL_ALIAS указан, будут доступны по URLs. К примеру PERSONAL_ALIAS=project, тогда

настройки для client proxy (proxy это контейнер)

Выполняя docker-compose up, вы поднимаете проект + proxy client и связываете все вместе. Соответственно, выполняя docker-compose down вы "тушите" проект вместе с проксированием

Читайте также: