LoginSignup
7
4

More than 5 years have passed since last update.

SORACOM Airのメタデータでautossh

Last updated at Posted at 2016-12-12

この記事は、IoTLT Advent Calendar 2016 の11日目の記事です。
※1日遅れの投稿になってしまってすみません…。

突然ですがみなさん、設置したIoTデバイスのメンテナンスにお困りではありませんか?
Linux搭載でSSHできればあとから何とでもなるので安心ですが、
都合良くグローバルIPを割り当てられないケースも多々あると思います。

今回、お仕事でOpenBlocks IoT+SORACOM Airを遠隔地に設置してメンテナンスが必要な案件に関わったので、
その際につくった簡単なシェルスクリプトをご紹介します。

soracom_autossh

GitHubで公開しています。

クラスメソッド様のSoracom Airで繋がったデバイスにリモートからSSHするを参考に、
記事の最後で言及されている「Soracom Air のユーザーデータでリモートサーバ情報を連携」を(データ構造は違いますが)実現しています。

使用方法はREADMEをご参照下さい。

やっていること

SORACOM Airのメタデータサービスでは、SIMの情報(Subscriber情報)とユーザデータ(任意の文字列を設定できる)が取得できます。
soracom_autosshでは、ユーザデータで「どのSIMが」「どのサーバに」「どの秘密鍵」でSSHポートフォワードするかという情報を持たせておきます。

ユーザデータのデータ構造は下記の通りです。
{SSHでログインしたいLinuxデバイスのSORACOM Air IMSI}は、imsis配下に複数指定可能です。

{
  "ssh":{
    "imsis":{
      "{SSHでログインしたいLinuxデバイスのSORACOM Air IMSI}":{
        "portForwardParam":"{任意のポート番号}:localhost:22 {リモートサーバのユーザー名}@{リモートサーバのグローバルIPアドレス}",
        "privateKey":"{リモートサーバのSSH秘密鍵}"
      }
    }
  }
}

まず、SIMの情報を取得してユーザデータと照らし合わせ、
自分が接続すべきSSH情報がユーザデータにあるかどうか調べます。

soracom_autossh.sh
# 自分のIMSIと該当するSSH情報を取得
IMSI=`curl -s http://metadata.soracom.io/v1/subscriber | jq .imsi`
if [ $? -ne 0 ]; then
  echo "failed to get own imsi"
  exit 1
fi

SSH_INFO=`curl -s http://metadata.soracom.io/v1/userdata | jq -r .ssh.imsis[${IMSI}]`
if [ $? -ne 0 ]; then
  echo "failed to get userdata"
  exit 1
fi

自分が接続すべきSSH情報が存在し、かつ前回取得した内容と異なる場合のみ、
秘密鍵をユーザデータからファイルに書き出し、autosshを起動します。

soracom_autossh.sh
if [ "$SSH_INFO" != "null" ]; then
  # 自分のSSH情報があれば、前回取得したSSH情報との差分チェック
  if diff -q $SSH_INFO_FILE $SSH_INFO_FILE_OLD > /dev/null 2>&1; then
    # do nothing
    echo "do nothing" 
  else
    # 前回取得したSSH情報との差分があれば、秘密鍵を書き出してautossh開始

    # autosshが起動済みなら終了
    exit_autossh
    delete_privatekey

    echo $SSH_INFO | jq -r .privateKey > $SSH_PRIVATEKEY_FILE
    chmod 600 $SSH_PRIVATEKEY_FILE
    AUTOSSH_PIDFILE=$AUTOSSH_PIDFILE \
                   autossh -M 0 -o StrictHostKeyChecking=no \
                   -o UserKnownHostsFile=/dev/null \
                   -o ServerAliveInterval=60 \
                   -o ServerAliveCountMax=3 \
                   -o ExitOnForwardFailure=yes \
                   -i $SSH_PRIVATEKEY_FILE \
                   -N \
                   -f \
                   -R `echo $SSH_INFO | jq -r .portForwardParam` &
    echo "started autossh"
  fi
else
  # 自分のSSH情報が無い場合、autosshが起動済みなら終了
  exit_autossh
  delete_privatekey
fi

soracom_autossh.shはcronなどでの定期実行を想定しており、
もし自分が接続すべきSSH情報が無い場合、起動したautosshを終了するようになっています。

実際の運用例

あらかじめsoracom_autossh.shをcronで5分間隔起動するようにしておき、通常時はユーザデータを空にします。
メンテナンスの必要性があるときだけSSHポートフォワード先となるAWS EC2のインスタンスを立ち上げ、
ユーザデータにメンテナンスしたいIoTデバイスとSSH情報を書いておき、IoTデバイスがSSHポートフォワードしてくるのを待ちます。

最後に

これでいつでもSSHできるので、何かあったときでも安心ですね。(トラブル起きないのが一番ですが…)

7
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4