Бывает ситуация, когда нужно отдебажить сложный кейс на удаленной машине, но доступ к серверу есть только под VPN с ограничениями по открытым портам. В статье хочу поделиться с коллегами небольшим «ресерчем» на тему удаленной отладки через SSH под VPN, дабы сэкономить драгоценное время на настройке. Сочту миссию выполненной, если кому-то пригодится данный ман.

Спойлер
Сервер был развернут на Ubuntu, соответственно далее все серверные настройки будут под Ubuntu. На локальной машине — Mac, но здесь нам понадобится только SSH-клиент и IDE с отладчиком под xdebug, поэтому настройки относительно универсальные.

Вводные


Итак, есть удаленный сервер за защищенным контуром. На сервере в докере поднят микросервис с включенным xdebug. Есть доступ снаружи только по SSH и через VPN.

Цель


Цель: запустить удаленную отладку микросервиса локально через xdebug.

Поехали…

1. Настраиваем sshd на удаленном сервере


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

Вот здесь нужен root. Будем считать, что он у Вас есть :-)

sudo echo "GatewayPorts yes" >> /etc/ssh/sshd_config
sudo service ssh restart

2. Узнаем адрес хостовой машины в сети docker


Поскольку xdebug запускается в докере и подключается сам к локальной машине (а в моем случае этот IP не резолвится, т.к. подключение под VPN), полезно узнать IP хостовой машины в сети docker. Это можно сделать с помощью команды (выполняем на сервере):

ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+'

Предположим команда выдала «172.17.0.1»

3. Прописываем IP удаленного хоста в настройки xdebug в контейнере


Пример замены через sed, но можно и ручками в редакторе, кому как удобнее:

sed -i 's/xdebug.remote_host=.*/xdebug.remote_host=172.17.0.1/' /usr/local/etc/php/conf.d/xdebug.ini

Не отходя от кассы прописываем «правильный» порт для отладки. В моем случае микросервис поднят на связке nginx & php-fpm и обычно порт 9000 занят под php-fpm, в связи с чем использую для отладки порт 9001.

sed -i 's/xdebug.remote_port=.*/xdebug.remote_port=9001/' /usr/local/etc/php/conf.d/xdebug.ini

Здесь же стоит проверить, что удаленная отладка, в принципе, включена: «xdebug.remote_enable=1»

grep xdebug.remote_enable /usr/local/etc/php/conf.d/xdebug.ini

Обычно эти настройки зашиваются в Dockerfile или маунтятся через volume.

На сервере все готово. Теперь переносимся на локальную машину строить тоннель.

4. Пробрасываем SSH-тоннель на удаленный сервер


Тоннель поднимается командой (выполняем на локальной машине):

SSH -R 9001:0.0.0.0:9001 user@remote_server

В этом месте звучит магическая музыка. Основная настройка выполнена, дальше только отладочная среда.

Настрока IDE


Обычно я использую vscode, поэтому отладчик через port listening запускается без проблем. Приведу пример конфига для vscode (просто добавьте узел в launch.json):

        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9001,
            "cwd": "${workspaceFolder}",
            "pathMappings": {
                "/repo": "${workspaceRoot}"
            }
        },

«pathMappings» — правило мэппинга директорий локальной и удаленной машин, где "/repo" — директория с отлаживаемым кодом в докере. Нужно, чтобы отладчик смог сориентироваться в файлах и точках останова.

P.S. Ну что, потестим?


Запускаем на локальной машине неткат и прислушиваемся:

nc -l 9001

Запускаем в докере однолинейный скрипт и печатем:

php -r 'print("Hi!" . PHP_EOL);'

На локальной машине мы должны увидеть позывные xdebug:

<?xml version="1.0" encoding="iso-8859-1"?>
<init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug"...

Ура! Все готово.

Теперь можно в IDE отлаживать любимый код на удаленной машине. В описанном методе есть очевидный минус: реконфигурация sshd на сервере. Возможно, есть более «тихий» способ. В любом случае буду рад вашим комментариям и советам.

Спасибо за внимание!

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


  1. disco878
    04.06.2019 13:08

    Хорошая статья, не подскажите вы случайно не ZOCterminal используете?


    1. infinum1 Автор
      04.06.2019 13:11

      Спасибо! Использую iTerm консоль и дефолтный ssh-клиент под Mac.


  1. Duti_Fruti
    04.06.2019 19:34

    Могу ошибаться но можно:
    xdebug.remote_connect_back = 1
    Чтоб не указывать хост, мало ли сменится.
    И порт это порт на машине где IDE, она поднимает и xdebug к ней стучится. Странно что он у вас конфликтует с php на сервере.


    1. infinum1 Автор
      05.06.2019 13:49

      Да, remote_connect_back можно использовать, если отладка идет на прямых запросах к сервису. Но этот вариант не отработает, если, к примеру, запускать тест в контейнере.
      Про порт на машине, в целом, соглашусь с Вами. Однако в моем случае включен «проброс» портов в докере и конфликт может происходить на хостовой машине, поэтому проще будет порты разнести.