Настройка SSH-тунеля

Есть сервер master с базой данных. Есть другой сервер slave, на котором надо настроить репликацию базы данных. И есть проблема: на сервере master закрыты все порты, кроме 22 (ssh).

Как одно из решений можно сделать тунель по SSH от сервера slave до сервера master, и внутри этого тунеля пересылать пакеты для репликации базы.

В самом простом случае ssh-тунель создается командой:

ssh -L 33060:localhost:3306 -i /home/user/.ssh/id_rsa -f -N user@slave.domain

где

  • f - выполнять в фоне.
  • i - путь до ключа, по которому будет происходить авторизация на сервере master.
  • N - не выполнять никаких команд. Я так понимаю, если вдруг в сценариях logon на сервере master заданы какие-то команды - выполнение их пропускается.
  • L - задаёт port forwarding. В данном случае, локальный порт 33060 на сервере slave мапится на локальный порт 3306 на сервере master.

Используя только эту команду нужно следить за работоспособностью этого ssh-тунеля. Для автоматизации этого процесса есть утилита autossh, которая следит за тем, что тунель работает, и в противном слуае запускает его заново.

autossh -M 0 -o ServerAliveInterval 30 -o ServerAliveCountMax 3 -L 33060:localhost:3306 -i /home/user/.ssh/id_rsa -N user@slave.domain

где

  • M - задает порт мониторинга. По этим портам происходит проверка работоспособности тунеля. 0 отключит мониторинг, а autossh перезапустит ssh только при выходе из ssh.
  • o - задание дополнительных опций.
  • L - маппинг портов.
  • i - путь к ключу, по которому будет происходить авторизация при подключении к серверу master.
  • N - не выполнять команд при подключении.
  • f - выполнять в фоне. Этот параметр не передается в ssh, а выполнение в фоне обеспечивает сама утилита autossh.

Но эту команду придется выполнять всякий раз после перезагрузки системы. Теперь надо настроить запуск этой команды при загрузке системы. Это можно сделать используя systemd.

  1. Создаем сервис. Для этого создаем файл
    sudo vi /etc/systemd/system/autossh-mysql-tunnel.service
    

    со следующим содержанием

    [Unit]
    Description=AutoSSH tunnel service everythingcli MySQL on local port 5000
    After=network.target
       
    [Service]
    Environment="AUTOSSH_GATETIME=0"
    ExecStart=/usr/bin/autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -N -L 33060:localhost:3306 -i /home/user/.ssh/id_rsa user@slave.domain
       
    [Install]
    WantedBy=multi-user.target
    

    Параметр -f можно не использовать, так как systemd не понимает этот параметр.

  2. Перезагружаем systemd, чтобы сервис стал доступен:
    sudo systemctl daemon-reload
    
  3. Запускаем сервис и помещаем его в автозагрузку:
    sudo systemctl start autossh-mysql-tunnel.service
    sudo systemctl enable autossh-mysql-tunnel.service
    
  4. Проверить статус можно с помощью команды:
    sudo systemctl status autossh-mysql-tunnel
    

    В результате, должны получить примерно такой вывод:

    ●  autossh-mysql-tunnel.service - AutoSSH tunnel service for  MySQL on local port 33066
         Loaded: loaded (/etc/systemd/system/autossh-mysql-tunnel.service; enabled; vendor preset: enabled)
         Active: active (running) since Thu 2019-02-28 16:10:49 MSK; 5h 2min ago
       Main PID: 1076 (autossh)
          Tasks: 2
         Memory: 5.6M
            CPU: 5.528s
         CGroup: /system.slice/autossh-mysql-tunnel.service
                 ├─1076 /usr/lib/autossh/autossh -M 0 -o ServerAliveInterval 30 -o ServerAliveCountMax 3 -L 33060:localhost:3306 -i /home/user/.ssh/id_rsa -N user@slave.domain
                 └─1092 /usr/bin/ssh -o ServerAliveInterval 30 -o ServerAliveCountMax 3 -L 33060:localhost:3306 -i /home/user/.ssh/id_rsa -N user@slave.domain
    

Полезные ссылки:

  1. StackOverflow
  2. Creating a persistent ssh tunnel in Ubuntu
  3. Start AutoSSH on Boot
  4. Магия SSH
  5. SSH TUNNELLING FOR FUN AND PROFIT: AUTOSSH
Евгений Вдовенко
Евгений Вдовенко

Физик по образованию, занимаюсь веб-разработкой на PHP с 2013 года. Нравится ковырятся в Zend Framework/Expressive и Joomla CMS/Framework. В процессе разборок с Python. Подумываю посмотреть Go. Считаю PostgreSQL крутым продуктом и внедряю его везде, где могу.