SSH
RaspberryPi

インターネット越しにRaspberry PIにSSH接続したいとき

インターネット越しに、ファイアウォールの内側にいるRaspberryPIなどのSSHサーバに接続したいとき、踏み台サーバを介してトンネルを設定できます。。
ここではGoogle Cloud Platform(以下GCP)で無料枠としてもらえるサーバを踏み台サーバとします。

トンネル設定

1. RasPiからGCPにポートバインディングしたSSH接続

  • -R 転送元ポート:転送先ホスト:転送先ポート
    • 指定したポートを、ローカル↔リモート間でバインドします
  • -N リモートコマンドを実行しません。ポート転送のみをおこないたい場合に便利です。
ssh -i ~/.ssh/{gcpの鍵} {gcpユーザ名}@35.xxx.xxx.xxx -R -N 10020:localhost:22

2. クライアントからGCPへポートを指定したSSH接続

  • -p SSH接続するポートを指定します
# GCPへ接続します
ssh -i ~/.ssh/{gcpの鍵} {gcpユーザ名}@35.xxx.xxx.xxx
# GCP上で、バインディング中のRaspiに接続します
ssh -i ~/.ssh/{rasPiの鍵} {piユーザ名}@localhost -p 10020

SSH Configに設定

上記の設定を~.ssh/config に記述し接続コマンドをシンプルにできます。
またautosshで接続を永続化できます。

  • RasPiの.ssh/configにRemoteForward設定を追加

起動時自動接続を設定(systemd)

1.サービスコマンドファイルを追加

/etc/systemd/system/autossh.service
#
# to install (had trouble getting it to actually start without reboot <shrug>
#
#  sudo cp autossh.service /etc/systemd/system/ ; sudo systemctl enable autossh.service ; sudo reboot

[Unit]
Description=Keep ssh tunnel to specified remote host open
After=network.target

[Service]
Environment="LOCAL_ADDR=localhost"
User=pi

ExecStart=/usr/bin/ssh -NT -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -i ${HOME}/.ssh/key_gcp/{} {ユーザ名}@{ホスト} -R 10020:localhost:22

RestartSec=30
Restart=always

[Install]
WantedBy=multi-user.target
  • 2.反映
sudo systemctl enable autossh.service
  • (接続できないとき) systemdのautossh.serviceの実行時ログを確認する
pi@raspberry-pi:~ $ sudo journalctl -u autossh

[Appendix]RaspberryPI上のWebサーバにアクセス

ダイナミックポートフォワーディングとSOCKSプロキシを設定すると、例えばRasPi上のWebサーバにhttp://localhostでアクセスできます

  1. ssh configファイルにDynamicForward {フォワードIP}:{フォワードポート}を設定
    • ssh -d {フォーワードIP}:{フォーワードポート} ...でも可
  2. SOCKSプロキシを設定
    • (macOSの場合)ネットワーク→詳細→プロキシ→SOCKSプロキシ 
    • 注) 「ネットワーク」パネルの「適用」を押下するまで反映されません

スクリーンショット 2018-04-09 18.42.07.png

RasPi上で実行中のPortainer.ioに、インターネット越しにアクセスしている様子

スクリーンショット 2018-04-09 18.49.43.png

Tips

設定中につまづいた点のメモ

トンネル接続したあと、しばらくすると切断される

トンネル接続したあとしばらくするとWrite failed: ... Broken pipeといったエラーメッセージとコマンドが送信できなくなることがありました
ssh configからタイムアウト値のコメントアウトを外し有効化すると回避できます

ServerAliveInterval 15
ServerAliveCountMax 10

サーバ側も以下コメントアウトを外してリトライ設定を追加

ClientAliveInterval 15 
ClientAliveInterval 10 

autosshを終了したい

pkill -3 autossh

クライアントからRaspberry PIに接続できない

サーバ→RasPiに接続できるか確認します

ssh {ユーザ名}@localhost -p 10020

お手軽に同じようなことを実現したい

公式サイトでリモートアクセスするためのウェブサービスが紹介されています
ACCESS YOUR RASPBERRY PI OVER THE INTERNET

参考

http://www.clear-code.com/blog/2014/9/12.html

https://www.kmc.gr.jp/advent-calendar/ssh/2013/12/09/tunnel2.html

ProxyCommandによるsshの多段接続について

「Write failed: Broken pipe」によりsshが切断された時の対処法

OpenSSH-7.3p1 日本語マニュアルページ (2016/10/15)

Setup autossh script on Raspbian for Raspberry Pi to connect the Raspberry Pi from the Internet via reverse ssh tunnel