ローカル環境のサーバで Webhook を受け取る方法

  • 6
    いいね
  • 0
    コメント

Slack の Custom Slash Commands とかを開発しようとすると、Slack サーバからの Webhook を受け取れるサーバを用意しないといけないので、ローカル環境のみで開発をすることが難しい。

今回は、SSH のリモートフォワードを利用してリモートサーバで受け取った Webhook をローカル環境のサーバにフォワーディングする仕組みについて書く。

前置き

SSH リモートフォワードを行うと、ローカル環境のサーバがインターネットからアクセスできる状態になるため、開発中のアプリケーションの動作確認等で使う場合は注意して欲しい。

リモートサーバを立てる

Webhook を受け取ってローカル環境に流すためのリモートサーバを立てる。

インターネットからアクセスできて sshd が動けばあとはなんでも良い。

今回は AWS で Amazon Linux の t.nano インスタンスを立てて、セキュリティグループで TCP, port: 3000, source: 0.0.0.0/0 のインバウンドトラフィックを許可した。

テキトーな HTTP サーバをローカル環境に立てる

検証のためにテキトーな HTTP サーバを作る。

ローカル環境で以下のようなテキトーな HTML ファイルを作って、

index.html
<!doctype html>
<html>
  <body>
    This is local HTML file!
  </body>
</html>

Python 3 の HTTP モジュールを使って HTTP サーバを起動する。1

$ python3 -m http.server 4000

これでローカル環境から http://localhost:4000/ でページにアクセスできるようになったと思う。

SSH トンネルを作る

SSH トンネル (ポートフォワーディング) には「ローカルフォワード」と「リモートフォワード」の二種類があり、今回の用途では「リモートフォワード」を利用する。

ポートフォワーディングについては以下の記事が詳しい。
sshポートフォワーディング - Qiita

リモートフォワードをするコマンドはこんな感じ。

$ ssh -R 3000:localhost:4000 -N <user>@<host>

-N は「SSH 接続時にコマンドを実行しない」オプション。
バックグラウンドで起動したい場合は -f オプションを追加する。

-R オプションでリモートフォワードの設定をしていて、この場合は「リモート側のポート 3000 をローカル側の localhost:4000 にフォワーディングする」という意味になる。

sshd の GatewayPorts を設定する

sshd のデフォルト設定では、リモートフォワード時にループバックアドレス 127.0.0.1 がバインドされるため2、このままではインターネットからアクセスすることができない。

リモートフォワード時のバインドアドレスを変更するには sshd の GatewayPorts の設定を変更する。

GatewayPorts の値 効果
yes ワイルドカードアドレス 0.0.0.0 をバインドする
clientspecified バインドアドレスをクライアント側で指定できる
no (default) ループバックアドレス 127.0.0.1 をバインドする

Webhook が飛んでくるアドレスが分かっているなら clientspecified を指定してそのアドレスのみをバインドすることでよりセキュアにできると思うが、Slack API の場合は IP Range が固定されていない3とのことなのでこの方法は使えなかった。

開発中のサーバがインターネットに晒されることをそれほど気にしないのであれば yes を指定すれば問題ない。

設定を変更したあとは sshd を再起動する。

インターネットからアクセスしてみる

http://<リモートサーバ>:3000/ にアクセスしてみて、ローカル環境のサーバに繋がれば正常にリモートフォワードできている。


  1. Python 2 を使う場合は http.server の代わりに SimpleHTTPServer を使うとできる 

  2. man sshd_configGatewayPorts の項目を参照 

  3. https://twitter.com/slackapi/status/567110311476350976