Автоматическое восстановление ssh туннеля

Описание задачи:

Автоматически восстанавливать ssh соединение при разрыве

Решение:

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

Вся работа проводится из под пользователя, под которым будет устанавливаться сессия SSH для проброса портов.

  1. Убедиться что необходимые для обмена ключи есть (файлики id_rsa.pub и/или id_dsa.pub), выполнив команду

    ls –al ~/.ssh/

  2. Вывод команды:

    -rw------- 1 user132 users   672 2008-12-13 01:13 id_dsa
    -rw-r--r-- 1 user132 users   604 2008-12-13 01:13 id_dsa.pub 
    -rw------- 1 user132 users  1675 2008-12-12 20:55 id_rsa 
    -rw-r--r-- 1 user132 users   396 2008-12-12 20:55 id_rsa.pub 
    -rw-r--r-- 1 user132 users 13564 2008-12-10 18:59 known_hosts 
    

    Если их нет – то выполнить последовательно 2 команды, нажимаю просто Enter погда происходит запрос на пароль для ssh-ключей

    ssh-keygen -t rsa

    Вывод:

    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/user132/.ssh/id_rsa): 
    Created directory '/home/user132/.ssh'. 
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in /home/user132/.ssh/id_rsa. 
    Your public key has been saved in /home/user132/.ssh/id_rsa.pub. 
    The key fingerprint is: fc:d7:c5:17:8a:0c:c7:63:72:61:7c:18:79:d0:86:73
    

    ssh-keygen -t dsa

    Вывод:

     
    Generating public/private dsa key pair.     
    Enter file in which to save the key (/home/user132/.ssh/id_dsa):     
    Enter passphrase (empty for no passphrase):     
    Enter same passphrase again:     
    Your identification has been saved in /home/user132/.ssh/id_dsa     
    Your public key has been saved in /home/user132/.ssh/id_dsa.pub.     
    The key fingerprint is:     32:97:fd:fb:30:0a:f2:87:76:a5:45:e5:d2:62:35:d6
    

  3. Далее небходимо экспортировать публичные ключи на удаленную машину:

    МЕТОД 1 (простой): На клиентской машине (с которой инициируется ssh-сессия) под пользователем из под которого предполагается выполнять проброс портов выполнить команду:

    ssh-copy-id -i ~/.ssh/id_rsa.pub  -l <remote_login> <remote_host>

    где:

    <remote_login> – имя удаленного пользователя, под которым выполняется проброс портов
    <remote_host> – удаленный хост (c mysql)

    и ввести пароль
    Если по какой-либо причине в системе не найдена команда ssh-copy-id придется выполнить операцию вручную (МЕТОД 2)

    МЕТОД 2 (сложный): залогиниться по ssh на удаленный сервер выполнив команду:

    ssh -l  <remote_login> <remote_host>

    и введя пароль, скопировать содержимое файла

    ~/.ssh/id_rsa.pub

    с клиента на сервер дописав его в конец файла ~/.ssh/authorized_keys .

    Если файла authorized_keys нет, его необходимо создать с правами 600 в каталоге ~/.ssh и владельцем <remote_login>.
    команды:

    cd ~/.ssh  
    touch authorized_keys  
    chmod 600 authorized_keys

    вот примерное содержание файла ~/.ssh/authorized_keys :

    ssh-rsa AAAA7Hz<одна_длинная_строка>ZGHhTQn72Jk0XslFLkTzYvwQ== user132@some_host
    

    Далее закрыть текущую сессию ssh на <remote_host> и попробовать залогиниться без пароля просто набрав в командной сроке:

    ssh -l <remote_host> <remote_host>

 

Если все прошло удачно приступим к правке скрипта по проверке статуса туннеля необходимо поправить слежующий скрипт:

 
#!/bin/sh 

#-*-Perl-*- 
exec perl -w -x $0 "$@"  
#!perl 
use IO::Socket;  
my $sock = new IO::Socket::INET (
     PeerAddr => 'localhost',
     PeerPort => 'some_port1',
     Proto => 'tcp',
     );  

my @children; 
unless ($sock) {
     print "No socket avialble!\nTrying to reopen socket...\n";
     my $child = fork;
     exec("ssh -t -t -t -l <remote_user> <remote_host> -L <some_port1>:server2:<some_port2>") 
          if     $child == 0; 
     }  
print "OK!\n"; 
close($sock); 
exit 0; 

где:

<remote_login>

– имя удаленного пользователя, под которым выполняется проброс портов

<remote_host>

– удаленный хост (c mysql)

<some_port1>,<some_port2>

- порт, пробрасываемый и локальный

далее добавить запись в crontab:

crontab -e
*/3  * * * *  /путь/до/скрипта/check_ssh.pl

Раз в 3 минуты будет происходить проверка , и если нет проброса, то будет запускаться новый ssh

Все готово.