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

У меня есть много удаленных Raspberry, использующих NAT внутри своих локальных сетей, и один Raspberry, который я использую как сервер, доступный из Интернета.

Я внедрил на своем веб-сайте систему для отправки удаленным Raspberries одиночных команд.

Каждый удаленный Raspberry каждую минуту (crontab) проверяет наличие доступных команд, и если он есть, он загружает команду, создает исполняемый файл и запускает его. Вот код файла crontab:

#! /bin/bash

sudo wget -c --output-document=ipdiscover.php "www.myserver.com/checkforcommands.php";

comando=$(cat ipdiscover.php);

sudo rm "/esegui.sh";

echo "#! /bin/bash" >> /esegui.sh;
echo "" >> /esegui.sh;
echo -e $comando >> /esegui.sh;
echo "exit 0" >> /esegui.sh;

sudo chmod +x /esegui.sh;

sudo /esegui.sh;

sudo rm "ipdiscover.php";

sudo date >>/tmp/crontest.txt;

Эта система работает очень хорошо, но я не могу использовать ее для установки обратного туннеля.

Если на удаленном сервере я запускаю этот код:

sudo /usr/bin/ssh -gNnT -R 2222:localhost:22 pi@publicserverIP;

тогда все работает правильно, но если я запускаю его из скрипта crontab, он не работает.

Я создал сертификаты без пароля и отправил его с удаленной Raspberry на сервер, чтобы не иметь доступа к логину.

1 ответ1

0

Вам не нужно запускать команды из cron через sudo .

Создайте такой скрипт, как этот ниже, и поместите его в домашний каталог пользователя, который установит обратное SSH-соединение с вашим сервером:

#!/bin/sh

### reverseSSHscript.sh ###

### (use public key authentication, so you don't need 
### to enter password for your server)
PrivateKeyToAccessCentralServer='/path/to/the/private/ssh/ServerKey.pem'

(
/usr/bin/nohup     \ 
 /usr/bin/ssh -gNnT \
  -i "${PrivateKeyToAccessCentralServer}" \
  -o ExitOnForwardFailure=yes     \
  -o ServerAliveInterval=60       \
  -o ServerAliveCountMax=1        \
  -o TCPKeepAlive=no              \
  -o UserKnownHostsFile=/dev/null \
  -o StrictHostKeyChecking=no     \
  -o CheckHostIP=no               \
  -R 2222:localhost:22 pi@publicserverIP
) &

Затем создайте задачу cron для ее запуска:

echo "@reboot User /path2the_script_shown_above/reverseSSHscript.sh" |
   sudo tee /etc/cron.d/reverseSSH2home

Тогда это должно работать.
Кстати, вы можете запустить этот скрипт под каким-то User ограниченными правами, а не с root чтобы быть в безопасности.

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

Периодически запускайте также некоторые дополнительные проверки cron, чтобы проверить, работает ли порт обратного соединения на вашем сервере; что-то вроде этого:

chkRemPort() {
    # Connect to intermediate host and check if remote forwarded port is alive
    echo $(/usr/bin/ssh -4 -f -q        \
        -o BatchMode=yes                \
        -o UserKnownHostsFile=/dev/null \
        -o StrictHostKeyChecking=no     \
        -o CheckHostIP=no               \
        -i /path/to/the/private/ssh/ServerKey.pem      \
        pi@publicserverIP               \
        /bin/nc -w 3 -zv localhost 2222 2>&1 | /bin/grep succeeded > /dev/null ;    \
        [ $? -eq 0 ] && { echo 'OK'; } || { echo 'FAILED'; }; exit; )
}

Если проверка не удалась, попробуйте установить новый обратный сеанс на вашем сервере.

PS
Обратные порты на каждом Raspberry Pi должны быть разными, чтобы избежать конфликта между портами на вашем сервере

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .