自宅に置いたラズパイ(つまり、NATの内側にあるのでインターネット側からは直接は見えないところにある。)を外からsshでログインできるようにしてみました。いろいろと応用できそうなので、ここに記録を残します。
概要
外からsshでログインできるクラウドの仮想マシンを用意して、それを経由してラズパイにアクセスできるようにします。
ラズパイが起動したら、そのクラウドの仮想マシンにSSHのトンネルを作るようにしておきます。
これで、いつでもクラウドの仮想マシンからラズパイにsshでログインできるようになります。
(気が向いたら図を描く)
準備
今回はクラウドの仮想マシンとしてAWSを使いました。
pemファイルでログインできるようにしておき、そのpemファイルをラズパイに置きます。
また、その仮想マシンのパブリックのIPアドレスは固定になるように設定しました。
ここではその仮想マシンをaws001
と呼ぶことにします。
アクセスに使用するpemファイルを aws001.pem
とします。
IPアドレスは18.217.14.xx
とします。
ユーザーIDは ubuntu
とします。
その仮想マシンには以下のようにすればログインできます。
ssh -i aws001.pem ubuntu@18.217.14.xx
ラズパイ側ではユーザー pi のパスワードをpasswd
コマンドを使用してデフォルトのものから変更しておきます。
aws001.pem はパーミッションが適切でないとsshコマンドがエラーになるので、以下を実行しておきます。
chmod 400 aws001.pem
ラズパイ側に置くスクリプト
#!/bin/sh
KEYFILE=aws001.pem
USER=ubuntu
HOST=18.217.14.xx
REMOTE_PORT=2022
[ -r $KEYFILE ] || exit 1
SSH_CONFIG="\
-o ServerAliveInterval=20 \
-o ServerAliveCountMax=2 \
-o ConnectTimeout=10 \
-o ExitOnForwardFailure=yes \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
"
while :; do
sleep 10
echo "Make ssh tunnel" |logger -t ssh_tunnel
ssh -i $KEYFILE $USER@$HOST -R $REMOTE_PORT:127.0.0.1:22 -N $SSH_CONFIG
echo "Disconnected ssh tunnel. Exit code:" $? |logger -t ssh_tunnel
done
logger はsyslogにメッセージを出すコマンドです。
sshのタイムアウトの時間などは必要に応じて調整してください。
このスクリプトを起動時に実行するために、/etc/rc.local に以下を追加します。
[ -x /root/ssh_tunnel/ssh_tunnel ] && (cd /root/ssh_tunnel; ./ssh_tunnel )&
AWSのVMからラズパイにログインする
ssh -p 2022 pi@localhost
多段ssh
Host aws001
User ubuntu
IdentityFile ~/.ssh/aws001.pem
Host rpi
HostName localhost
Port 2022
User pi
ProxyCommand ssh -W %h:%p aws001
このように ~/.ssh/config
に書いておけば、AWSを経由してラズパイにログインするのがコマンド一発でできます。
ssh rpi
同様にしてsftpやscpも使えるのでファイルのコピーも楽になります。
補足
最初はautosshコマンドでできるかと思ったのですが、うまくいかないケースがありました。
sshでログインしている最中に、ラズパイの電源を落として再起動させたときに、まだsshのコネクションが切れていない状態で新たにsshトンネルを作ろうとするとautosshコマンドが終了してしまうようでした。そのためautosshコマンドを繰り返し実行するようにしたのですが、それなら単純にsshコマンドを繰り返すのとたいして変わらないということになり、今のかたちになりました。