Viele Tage lang habe ich mich gefragt, wie man den Aufbau eines Reverse-Tunnels automatisieren kann.
Ich habe viele Remote-Raspberry-Computer, die NAT in ihren LANs verwenden, und einen Raspberry, den ich als Server verwende und der über das Internet erreichbar ist.
Ich habe auf meiner Website ein System implementiert, um einzelne Befehle an entfernte Himbeeren zu senden.
Jeder Remote-Raspberry prüft jede Minute (Crontab), ob Befehle verfügbar sind. Wenn einer vorhanden ist, lädt er den Befehl herunter, erstellt eine ausführbare Datei und führt sie aus. Hier ist der Code der Crontab-Datei:
#! /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;
Dieses System funktioniert sehr gut, ich kann damit jedoch keinen Reverse-Tunnel einrichten.
Wenn ich auf dem Remote-Server diesen Code ausführe:
sudo /usr/bin/ssh -gNnT -R 2222:localhost:22 pi@publicserverIP;
dann funktioniert alles richtig, aber wenn ich es vom Crontab-Skript aus ausführe, funktioniert es nicht.
Ich habe die Zertifikate ohne Passwort erstellt und sie vom Remote-Raspberry an den Server gesendet, um keinen Login-Zugriff zu ermöglichen.
Antwort1
Sie müssen keine Befehle über cron
ausführen sudo
.
Erstellen Sie ein Skript wie das folgende und platzieren Sie es im Home-Verzeichnis des Benutzers, der die umgekehrte SSH-Verbindung zu Ihrem Server herstellen wird:
#!/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
) &
Erstellen Sie dann die Cron-Aufgabe, um es auszuführen:
echo "@reboot User /path2the_script_shown_above/reverseSSHscript.sh" |
sudo tee /etc/cron.d/reverseSSH2home
Dann sollte es funktionieren.
Übrigens möchten Sie dieses Skript sicherheitshalber vielleicht unter „eingeschränkt“ statt „ User
als“ ausführen.root
Sie müssen außerdem eine Logik implementieren, reverseSSHscript.sh
die überprüft, ob die Verbindung bereits hergestellt wurde, um die Erstellung mehrerer Sitzungen zu verhindern.
Führen Sie außerdem in regelmäßigen Abständen einige zusätzliche Prüfungen von Cron aus, um zu testen, ob der Rückverbindungsport auf Ihrem Server noch aktiv ist. Dies könnte etwa so aussehen:
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; )
}
Wenn die Prüfung fehlgeschlagen ist, versuchen Sie, eine neue Reverse-Sitzung zu Ihrem Server herzustellen.
PS:
Die umgekehrten Ports auf jedem Raspberry Pi sollten unterschiedlich sein, um Konflikte zwischen den Ports auf Ihrem Server zu vermeiden.