LINUX.ORG.RU

Как сделать свой аналог ngrok?

 ngrok


1

1

Всем привет. Есть вот такая штука https://ngrok.com/

Очень удобно показывать что то локальное заказчику сразу с моего компа.

Но по вопросам безопасности и все такое. Есть потребность поднять «что-то свое». У меня есть VPS с доменом и собственно вопрос:

Есть ли что нибудь типа ngrok с открытым кодом, что бы я мог развернуть эту штуку у меня на VPN и + чтобы была CLI приложуха, для моего компа…

Есть ли что нибудь типа ngrok с открытым кодом, что бы я мог развернуть эту штуку у меня на VPN и + чтобы была CLI приложуха, для моего компа…

Ты уже ответил - vpn. Поднимай, скажем, на виртуалку, шарь в сеть и давай людям тыркать.

Bfgeshka ★★★★★
()

На VPS поднимаешь Wireguard сервер и Caddy.

На своём компьютере поднимаешь Wireguard клиент. Придумываешь какую-нибудь приватную подсеть для всего этого.

На Caddy настраиваешь реверс прокси на свой домен на нужный порт. Можешь с поддоменами несколько настроить, к примеру 8080.mydomain.com -> 10.1.2.3:8080 и тд.

В принципе всё. Клиент коннектится к Caddy, та перенаправляет запрос на 10.1.2.3, а это твой комп в wireguard подсети, лишь бы онлайн был в это время.

Ну про безопасность конечно имей в виду, что любой может туда ходить. Как вариант - можешь настроить wildcard сертификат, это посложней будет, но всё возможно. Тогда с ним можешь создавать секретные домены типа qwer1234.mydomain.com, про которые уже никто кроме тебя не узнает. Тут безопасность можно ослабить.

vbr ★★★★
()

Лорчую вариант с SSH-туннелем — дёшево и сердито. Тебе нужна будет только своя VPS [1] c SSH-сервером, у которого:

  • должен быть сохранён твой публичный SSH-ключ;
  • в конфиге должно быть AllowTcpForwarding = yes;
  • в конфиге должно быть GatewayPorts = yes или GatewayPorts = clientspecified;
  • внешний порт (в примерах ниже 8888 и listen_port) должен быть разрешён в фаерволе.

Дальше запускаешь туннель:

$ ssh -R 8888:127.0.0.1:4000 daddy@romalinux.xxx -NT

После этого запросы на romalinux.xxx:8888 будут проксироваться на твою приложуху, локально запущенную на порте 4000.

А если в твоём ЯП есть либы для SSH, то можно их использовать для того, чтобы запускать туннель автоматически при запуске приложения (и убивать при завершении приложения). Например для Elixir можно накалякать работающее решение на двух функциях из стандартной библиотеки Erlang:

defmodule SSHTunnel do
  use GenServer

  require Logger

  def start_link(opts) do
    {server_opts, opts} =
      Keyword.split(opts, [:debug, :name, :timeout, :spawn_opt, :hibernate_after])

    Logger.debug("tunnel opts: #{inspect(opts)}")

    GenServer.start_link(__MODULE__, Map.new(opts), server_opts)
  end

  @impl GenServer
  def init(opts) do
    ssh_host = to_erlang_host(Map.fetch!(opts, :ssh_host))
    ssh_port = opts[:ssh_port] || 22

    ssh_opts =
      case opts do
        %{ssh_user: ssh_user} when is_binary(ssh_user) ->
          [user: to_charlist(ssh_user)]

        _other ->
          []
      end

    listen_host = to_erlang_host(opts[:listen_host] || {0, 0, 0, 0})
    listen_port = opts[:listen_port] || 0

    local_host = to_erlang_host(opts[:local_host] || {127, 0, 0, 1})
    local_port = Map.fetch!(opts, :local_port)

    with {:ok, conn} <- :ssh.connect(ssh_host, ssh_port, ssh_opts),
         {:ok, true_listen_port} <-
           :ssh.tcpip_tunnel_from_server(conn, listen_host, listen_port, local_host, local_port) do
      Logger.info(
        "started TCP tunnel from #{format_host(ssh_host)}:#{true_listen_port} to #{format_host(local_host)}:#{format_host(local_port)}"
      )

      {:ok, conn}
    else
      {:error, error} ->
        Logger.error("failed to connect: #{inspect(error)}")

        {:stop, error}
    end
  end

  defp to_erlang_host(host) when is_binary(host), do: to_charlist(host)
  defp to_erlang_host(host), do: host

  defp format_host(host) when is_tuple(host) and tuple_size(host) in [4, 8] do
    :inet.ntoa(host)
  end

  defp format_host(host), do: host
end

Пример спеки для супервизора, эквивалентный вызову команды ssh выше:

{SSHTunnel, ssh_host: "romalinux.xxx", listen_port: 8888, local_port: 4000, ssh_user: "daddy"}

[1]: если своей VPS нет, то вместо неё уже советовали https://serveo.net/, принцип там тот же.

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 1)