接続しているネットワークの変化をトリガとして、任意のスクリプトを実行する方法 - 例えばSSHトンネルの掘り直し

いままで、

  • 小さいターミナルでこんな感じでSSHのトンネルを掘って
    • while true; do rebuild-ssh-config; ssh -N -o "BatchMode yes" -L ... -R ... TUNNELHOST; echo retry; sleep 3; done
  • ネットワークが変わった場合(会社に着いたとか家に着いたとか)、手動でkillall sshしてトンネルのsshプロセスを殺して掘り直す

ということをやっていたのですが、

を読んで、ネットワークが変わったタイミングでスクリプトを実行する方法を知った(id:typester++)ので、この手法を使って自動的にkillall sshするのと、あとついでに、ターミナルの中で実行してたsshプロセスを、AppleScriptでラップしてログイン項目から実行するようにしてみました。

これで、OS起動したら自動的にSSHトンネルが掘られるし、場所移動してMacBookのふたを開ければ(接続ネットワークが変わってるので)自動的にトンネルが掘り直されるようになり、手間いらずになりました。

以下詳細。

シェルスクリプトのアプリケーション化(AppleScriptでラップする)

  • /Users/hirose31/bin/proxyirori
#!/bin/bash

while true; do
  rebuild-ssh-config
  ssh -N -o "BatchMode yes" \
    -L XXXX:XX.XX.XX.XX:XXXX \
    -L XXXX:XX.XX.XX.XX:XXXX \
    TUNNELHOST
  echo retry
  sleep 3
done

ちなみに、rebuild-ssh-config は今接続しているネットワークに応じて ~/.ssh/config を生成するスクリプトです。

なんで生成しているかというと、例えば、家のマシンにSSHするにしても、ネットワーク的な場所によってIPやポート番号が異なるのですが、

  • 自宅: 自宅LANのプライベートアドレス
  • 会社: フレッツドットネット経由で接続できるようにしているので、IPv6なアドレス
  • そのほか(イーモバとか): 自宅のグローバルアドレスの(22ではない)とあるポート

その差異を ~/.ssh/config で吸収して、いつでもどこにいても、同じ名前ssh JITAKU_HOST でSSHできるようにしています。

  • /Applications/proxyirori.scpt

スクリプトエディタ」でこんな感じの内容のを作って、

do shell script "/Users/hirose31/bin/proxyirori > /dev/null 2>&1 &"

「別名で保存」で

    • フォーマット: アプリケーション
    • オプション: ■実行専用にチェック、□初期画面と□実行後、自動的に終了しないはチェックしない

を選んで、/Applications/proxyirori.app として保存。

参考:

あと、既にdaemontools入れているなら、OS起動時実行と、自動的な起動し直しはdaemontoolsでできるので、そっち使った方がいいと思います。

ネットワーク変更時のトリガ

typesterさんのエントリほぼそのままです。

  • ~/Library/LaunchAgents/org.irori.proxyirori.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
          "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>org.irori.proxyirori</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/bin/killall</string>
      <string>ssh</string>
    </array>
    <key>RunAtLoad</key>
    <false/>
    <key>StandardErrorPath</key>
    <string>/dev/null</string><!-- <string>/tmp/error</string> -->
    <key>StandardOutPath</key>
    <string>/dev/null</string>
    <key>WatchPaths</key>
    <array>
      <string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
      <string>/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist</string>
    </array>
  </dict>
</plist>

で、

launchctl list | grep irori
launchctl load ~/Library/LaunchAgents/org.irori.proxyirori.plist
launchctl list | grep irori

確認してませんが、有線のネットワークの抜挿で/Library/Preferences/SystemConfiguration/NetworkInterfaces.plistが変化しそうだったので、監視対象に入れてます。