何日もの間、リバース トンネルの確立を自動化する方法を考えていました。
私は、LAN 内で NAT を使用しているリモート Raspberry を多数所有しており、インターネットからアクセス可能なサーバーとして使用している Raspberry を 1 台所有しています。
私は自分のウェブサイトに、リモートの Raspberry に単一のコマンドを送信するシステムを実装しました。
すべてのリモート 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
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 の逆ポートは異なる必要があります。