Часто оказывается необходимым дать доступ из Интернета к каким-либо портам своего компьютера, расположенного за NAT провайдера. Но популярный ранее сервис ngrok стал IMHO фактически непригоден в бесплатной версии. Как же быть? Сделаем свой ngrok, разместив его на своей же VPS-ке (да, Ваш сервер в Интернете необходим, без него никак). Опишу, как это вышло у меня.

image

Итак, имеем VPS на Ubuntu Linux 14.04.1. Заходим в консоль через SSH и действуем по списку.
1. Ставим последние обновления для системы.

apt-get update
apt-get -y upgrade

2. Установим необходимые пакеты.

apt-get install build-essential mercurial git

система mercurial требуется для сборки ngrok

3. Устанавливаем последнюю (1.8.3) версию языка Go (Golang) — ngrok написан именно на нем.

apt-get golang — так делать не нужно, так как не гарантируется установка последней версии языка

wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
tar -xvf go1.8.3.linux-amd64.tar.gz
mv go /usr/local
export GOROOT=/usr/local/go
export GOPATH=/home/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH

Примечание. Команды export окажут влияние только на текущую сессию.

Проверяем:

go version -> go version go1.8.3 linux/amd64


4. Клонируем исходный код ngrok.

git clone https://github.com/inconshreveable/ngrok.git ngrok
cd ngrok

5. Создаем требуемые поддомены для Вашей VPS — A-записи с именами ngrok, 1.ngrok, 2.ngrok и т.п., указывающие на IP-адрес VPS (1, 2 — желаемые субдомены). И да, просто ngrok тоже нужен!

6. Генерируем самоподписанный SSL-сертификат (необходим, так как ngrok создает туннель через TLS).

openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=ngrok.domain.com" -days 5000 -out rootCA.pem
openssl genrsa -out device.key 2048
openssl req -new -key device.key -subj "/CN=ngrok.domain.com" -out device.csr
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000

5000 — срок действия сертификата в днях (можно заменить, например, на 10000)
domain.com — домен Вашей VPS

Копируем нужные для компиляции файлы в директорию assets:

cp rootCA.pem assets/client/tls/ngrokroot.crt
cp device.crt assets/server/tls/snakeoil.crt 
cp device.key assets/server/tls/snakeoil.key

7. Компилируем сервер и клиент для Linux.

make release-server release-client

Копируем полученный файл сервера ngrokd из директории bin в нужную папку.

8. Компилируем сервер (на всякий случАй)) и клиент для 32-разрядной Windows.

make clean
GOOS=windows GOARCH=386 make release-server release-client

(для 64-битной версии меняем 386 на amd64).

Копируем файл клиента ngrok.exe с VPS из папки bin/windows_386 на клиентский (домашний) компьютер.

9. Копируем файлы device.key, device.crt, device.csr в директорию, куда мы скопировали исполнимый файл сервера ngrokd.

Устанавливаем требуемые атрибуты файла сервера:

chmod +x ngrokd

Запускаем сервер (например, через утилиту screen).

screen -S ngrok
./ngrokd -tlsKey=device.key -tlsCrt=device.crt -domain=ngrok.domain.com -httpAddr=:<b>8080</b> -httpsAddr=:8081

domain.com — домен Вашей VPS
8080 — порт для HTTP-запросов
8081 — порт для HTTPS-запросов
(порты, естественно, должны быть свободны)

Жмем CTRL+A+D для выхода из созданного «экрана».

10. Создаем на клиенте (домашнем компьютере) файл конфигурации ngrok.cfg в той же директории, куда мы скопировали ngrok.exe, с содержимым:

server_addr: ngrok.domain.com:4443
trust_host_root_certs: false

4443 — порт по умолчанию, на котором сервер ngrok слушает запросы (этот порт должен быть открыт на Вашей VPS)
domain.com — домен Вашей VPS
false — ведь сертификат самоподписанный

11. Ждем, пока изменения в DNS-записях достигнут Вашего провайдера (с DNS-серверами Google, например, будет быстрее), пингуя нужный адрес.

ping ngrok.domain.com

domain.com — домен Вашей VPS

12. Запускаем простейший Web-сервер на 80-м порту (HTTP) Вашего домашнего компьютера (например, на Ruby c WEBRick).

13. Запускаем на домашнем компьютере клиент ngrok с выводом протокола.

ngrok.exe -log=stdout -config=ngrok.cfg -subdomain=1 80

1 — желаемый субдомен для этого домашнего компьютера
80 — порт нашего Web-сервера, выставляемого в Интернет

14. Проверяем работу, заходя с другого компьютера на наш Web-сервер по адресу:

http://1.ngrok.domain.com:8080

8080 — заданный на шаге 9 порт для HTTP-запросов
domain.com — домен Вашей VPS

Если Web-сервер не будет запущен, получим сообщение:

Tunnel http://1.ngrok.domain.com:8080 unavailable
Unable to initiate connection to 127.0.0.1:80. A web server must be running on port 127.0.0.1:80 to complete the tunnel.

Вот такие дела! Надеюсь, кому-то пригодится.
Поделиться с друзьями
-->

Комментарии (40)


  1. pwrlnd
    09.07.2017 13:57
    +2

    SSH port forwarding не справится с такой задачей? Просто и из коробки. А если надо быстро и надёжно, то тогда уж OpenVPN можно поднять.


    1. ed007
      09.07.2017 14:05

      А разве надо хоть кому не быстро и не надежно?


      1. pwrlnd
        09.07.2017 14:10
        +1

        не быстро и не надежно

        Скорость и стабильность — понятие относительные. Прокинуть порт WEB-сервера для демонстрации проекта или получить доступ к RDP во внутренней сети — будет вполне достаточно SSH. Если же речь идёт об одновременной работе десятков людей через это соединение, то лучше выбрать OpenVPN или что-то подобное.


        1. ed007
          09.07.2017 14:14

          Мне просто резанула глаза эта фраза, если так сказать на переговорах — клиент потерян. (По крайней мере в EU)


          1. pwrlnd
            09.07.2017 14:42

            Зачем на переговорах клиенту объяснять технические детали вашей dev-среды? Уверен, что клиенту интересна релизная часть.


    1. dbond
      09.07.2017 15:22

      OpenVPN не работает за провайдерским натом, например у ТТК.


      1. pwrlnd
        09.07.2017 15:32

        Какая связь? Если доступ в интернет есть, то OpenVPN точно будет работать — NAT ему не мешает. Либо не в ту сторону тоннель строите. Для тяжелых случаев даже есть режим TCP.


        1. dbond
          09.07.2017 15:45

          У ТТК OpenVPN работает только на статическом айпишнике. По словам ТП это особенности их NAT.


          1. pwrlnd
            09.07.2017 15:56
            +2

            Если бы был такой особенный NAT, то клиенты завалили бы поддержку жалобами. Одни бы жаловались на торренты, другие на неработающий DNS от Google, а третьи бы не смогли играть в свою любимую игру онлайн.

            Если уж предположить, что UDP специально был порезан, то OpenVPN в режиме TCP точно бы заработал, так как это соединение ничем не отличается от того, которое устанавливает браузер для загрузки сайта.


            1. dbond
              09.07.2017 16:06

              Я жаловался ))) им как с гуся вода. У них помимо глюков впн за 2 последних недели 3 блэкаута было, причем один из них весь рабочий день. ТП молчит как рыба об лёд, отнекивается общими фразами. Причем и сервер и клиент у ТТК в одном городе. Сервер на статическом IP, клиент на динамическом. Не работает, пишет «TLS handshake failed.», но стоит у клиента воткнуть в роутер кабель от Ростелекома или Мегафона, все начинает работать как часики.


              1. pwrlnd
                09.07.2017 16:46

                До сих пор присутствует такая проблема? У меня прямо спортивный интерес возник — посмотреть, что это ТТК там сделали, что так ювелирно вставляют палки в колеса.


                1. dbond
                  09.07.2017 16:56

                  Сейчас поменял настройки с UDP на TCP. Порт 8080. Не работает! Пишет «TCP: connect to [AF_INET]XX.XX.XX.XX:8080 failed, will try again in 5 seconds.»


                  1. pwrlnd
                    09.07.2017 17:02

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


                    1. dbond
                      09.07.2017 17:04

                      Я создал ещё один экземпляр сервера. Через Мегафон работает. Через ТТК — нет.


                      1. pwrlnd
                        09.07.2017 17:15

                        тогда трафик надо с интерфейса снять и посмотреть что происходит


                        1. dbond
                          09.07.2017 17:49

                          Посмотрел вайршарком, уходят тсп пакеты с портов 49758 (при каждой попытке происходит инкремент номера порта) на адрес сервера порт 8080. На сервере tcpdump входящих пакетов не видит.


                          1. pwrlnd
                            09.07.2017 17:55

                            А на сервере сидите по ssh с этой же машины?


                            1. dbond
                              09.07.2017 17:56

                              со второго компа но через другого провайдера.


                              1. pwrlnd
                                09.07.2017 17:59

                                То есть вы через ТТК не можете подключиться по ssh к своему серверу?


                                1. dbond
                                  09.07.2017 18:05

                                  У меня ssh закрыт. pfSence рулится через веб-интерфейс.


                                  1. pwrlnd
                                    09.07.2017 18:10

                                    Хорошо, через ТТК на веб-интерфейс вы можете зайти из дома?


                                    1. dbond
                                      09.07.2017 18:13

                                      не пробовал, у меня все входящие закрыты кроме портов ВПН


                                      1. pwrlnd
                                        09.07.2017 18:16

                                        Тогда стоит открыть и посмотреть. А на счёт OpenVPN — скорее всего, дело в настройках файерволла на сервере.


                                        1. dbond
                                          09.07.2017 18:19

                                          Там все верно. от других провайдеров работает!


                                          1. pwrlnd
                                            09.07.2017 18:25

                                            Не факт — ТТК может натить своих клиентов с адреса, который входит в подсеть, в которой находится сервер с его шлюзом. И правила на сервере могут быть для этой подсети указаны другие. Это как пример — комбинации могут быть другие.

                                            PS: По факту у вас проблема только внутри сети ТТК, скорее всего. Если косяк не у вас, а у ТТК, то пробелма не в нате, а в маршрутизации.


                                            1. dbond
                                              09.07.2017 18:31

                                              Не вижу я веб-интерфейс своего сервера именно из ТТК! Нда, сам не догадался очевидное проверить. Спасибо! Буду с ними бодаться.


                                    1. dbond
                                      09.07.2017 18:14

                                      Попробую открыть, посмотрю.


                            1. dbond
                              09.07.2017 17:59

                              Андроид и ios клиенты тоже не коннектятся когда подключены к домашнему вайфаю.


      1. dartraiden
        09.07.2017 16:00

        SoftEther VPN умеет пробивать NAT, если мне не изменяет память.


      1. SolarW
        09.07.2017 16:09

        В наших краях у провайдеров предоставляющего доступ без реальных айпишек частенько не работает PPTP из-за того, что не NAT'ят GRE.

        P.S. Да, я в курсе что PPTP древность которую надо заменять на другие способы. Но иногда его более чем хватает.


        1. pwrlnd
          09.07.2017 16:38

          Да, с GRE есть такая проблема. У меня даже есть подозрение, что dbond путает обычный VPN (PPTP или L2TP) с OpenVPN. Десять лет назад у меня было около 1500 клиентов, более половины использовало OpenVPN для доступа. Не было случаев, когда OpenVPN не работал: были случаи, когда у клиента был только прокси для доступа в интернет — даже в режиме работы через прокси OpenVPN показал себя отлично.


          1. dbond
            09.07.2017 16:41

            Не путаю. Со стороны сервера pfsence. Там эта фича практически из коробки. И экспорт клиентов очень удобен. Даже бухи в состоянии дома запустить.


  1. gudvinr
    09.07.2017 15:22
    +5

    Это уже не "бесплатный туннель", если нужен VPS.


    Какой смысл в ngrok (причём старой версии) в этом случае, если есть старый-добрый ssh forwarding, как выше сказали?
    Проще скрипт написать, который будет делать тоже самое без лишних слоёв.


    В качестве альтернативы можно использовать localtunnel.


    ИМХО конечно, но и бесплатного плана для ngrok вполне достаточно для IoT проектов или чтобы потестировать что-либо на локальной машине за NAT. В остальных случаях так или иначе понадобится отдельный сервер с выделенным адресом.
    Слабо могу представить, для чего нужны ресурсы сверх того, что предлагают в бесплатном плане, при таких юзкейсах.


    Возможно, я и не прав, но тогда было бы интересно узнать зачем люди это используют.


  1. amarao
    09.07.2017 20:22
    +1

    ssh -CD 1080 ip-address

    Появляется socks-proxy на порту 127.0.0.1:1080

    всё остальное содержимое статьи — зачем?


    1. redmanmale
      10.07.2017 12:56

      Или ssh -L 8080:127.0.0.1:8080 user@ip-address-vps -N.
      Пробрасываем локальный порт (слева) на удалённый порт (справа).


  1. saboteur_kiev
    09.07.2017 21:17
    +5

    Слово «бесплатный» следует убрать из названия статьи.


  1. justhabrauser
    10.07.2017 00:50
    -1

    Чем бы дитя не тешилось — только бы руки на одеяле держало.
    (а за make убивают вообще-то)
    Но таки да — вариант.


  1. bigbrotherwatchingyou
    10.07.2017 08:33
    +1

    Статью можно назвать «Когда линуксоиду нечем заняться...» Таким в проктологи надо идти, а не админить и программить


  1. ABATAPA
    10.07.2017 08:36

    OpenVPN c Pritunl на хостинге за 100 руб. поднимается буквально несколькими командами. Дальше несколько кликов — и вот уже есть конфиг, который «едят» 99% клиентов под все платформы.


  1. Anonym
    10.07.2017 13:45
    +1

    apt-get install ngrok-server уже не работает?