2026-07-08 の「リモートホストIP制限」インシデントを受けた v2 アーキテクチャの全面解説。
← サイトトップへ戻る
旧構成(v1)は自宅/事務所のPCとその回線から毎朝、西松屋オンラインストア本体
(www.24028-net.jp)の在庫確認ページを 131品番 × 最大3回再試行 × 並列6接続で
取得していました。西松屋のECプラットフォーム(ebisumart系)のWAFがこれをbotと判定し、
回線のグローバルIP単位で制限(403「リモートホストIPが制限されています」)を発動。
ブラウザでの通常閲覧まで同じエラーになりました。
〜2026-07-11。制限の原因となった構成
2026-07-11〜。ローカルPCと本体サイトを経路から排除
| レイヤ | v1(旧) | v2(現行) |
|---|---|---|
| スケジューラ | Windows タスクスケジューラ(PC電源依存) | Durable Object Alarm(SQLiteバックエンド。cronトリガー枠を消費せず、単一スレッド実行で二重起動が構造的に不可能) |
| データ取得 | ローカルNode.js。本体サイト在庫ページを131品番×並列6でスクレイプ | Worker上の共有パイプライン src/pipeline.mjs。検索APIのみ(json_grouping)。色×サイズ実在庫は仕様上取得不能になったためデザイン単位表示に変更 |
| データ保存 | ローカルファイル → 毎朝 wrangler で全量再デプロイ | Workers KV。ステップ成功時のみ上書き(last-good保持) |
| 配信 | Cloudflare Pages(静的のみ) | Pages + Pages Functions(/api/* をKVから配信、画像プロキシ、RSS)+ Cache API |
| フロント | 単一リスト(Tシャツのみ) | 3タブ(お揃いTシャツ / ¥1,000以下パンツ・レギンス / 他ブランド)+ SEO(JSON-LD/OGP/sitemap) + アフィリエイト基盤 |
| 監視 | deploy.log(ローカル。誰も見ず4日間障害に気づけなかった) | 公開 /api/status.json(毎tick更新・ステップ別成否とfetch数) |
| コード管理 | なし(ローカルのみ) | GitHub公開リポジトリ(シークレット非含有) |
制限の原因は「ローカル回線 → 本体サイトへの大量アクセス」。v2のコードには www.24028-net.jp へサーバー側からfetchする処理が1行も存在しません(GitHubで全コード検証可能)。旧タスクスケジューラも無効化済み。原因行為が物理的に発生し得ません。
v2が使う nishimatsuya-f-s.snva.jp は検索SaaS(NaviPlus)で、制限を発動したebisumart WAF(本体サイト)とは別ホスト・別基盤。実際、IP制限の発動中もこのAPIは一貫して200を返し続けています(ローカルからもCloudflareからも確認済み)。
v1: 数百リクエスト/日・並列6。→ v2: 1日1回・合計約60リクエスト・直列・150ms間隔。さらに1実行あたりfetch予算40でハードストップ、各fetch15秒タイムアウト。暴走してもWorkersの実行時間・サブリクエスト上限が二重の天井になります。
更新はCloudflareのデータセンターから実行され、自宅/事務所の回線IPはもう更新処理に一切使われません。この回線からは今後「普通に閲覧するだけ」なので、制限を再発・延長させる要因がありません(現在の制限も待てば解除される見込み)。
仮に将来どこかがブロック・障害になっても、失敗したステップは前日データを配信し続け、他ステップは独立して更新されます。サイトが止まったり空になったりはしません。実例: H&MはCloudflareからブロックされるため自動スキップで運用中。
実行結果は毎朝 /api/status.json に公開され、誰でも「今日も制限されずに完走したこと」を確認できます(下のライブ証跡がその実データです)。
以下は静的な文章ではなく、いまこの瞬間に /api/status.json と各データの生成時刻を読み込んで表示しています。
日付と全ステップ✓が毎日進んでいくこと自体が「Cloudflare側の処理が制限を受けていない」ことの継続的な実証になります。
(※将来にわたる外部サイト仕様の不変までは誰にも保証できないため、本サイトは「証明」を静的な断言ではなく毎日検証可能な公開データで提供する方針です)
| ステップ | 結果 | 外部fetch数 | 内容 |
|---|---|---|---|
| tshirt | ✓ 成功 | 9 | お揃いTシャツ 54デザイン生成 |
| cheap | ✓ 成功 | 7 | ¥1,000以下 378件(パンツ286・レギンス92) |
| uniqlo | ✓ 成功 | 37 | セール品自動選定(¥790) |
| corners | ✓ 成功 | 6 | ZARA(6)・ヒラキ(6)。H&Mは自動スキップ(設計どおり) |
| feed | ✓ 成功 | 0 | RSSフィード生成 |
| 合計 | 59 | v1の在庫検証だけで最低131×1〜3回だったものを1/10以下に削減 | |
| 事象 | 挙動 | サイトへの影響 |
|---|---|---|
| 検索APIが一時エラー | 3回再試行 → 2tick失敗で当該ステップをスキップ | 前日データを配信継続(last-good) |
| fetch予算(40/回)を使い切る | 失敗扱いにせず90秒後の次tickで同ステップから再開 | 更新が数分遅れるだけ |
| 他ブランドサイトのブロック/構造変更 | そのブランドのみ自動スキップ(実例: H&M・GAP) | 該当コーナーが非表示になるだけ |
| 生成結果が0件(上流異常) | 安全弁が発動しKVを上書きしない | 前日データを配信継続 |
| 想定外エラーでAlarm処理が失敗 | 10分後に再Alarmを自動設定(チェーンを絶やさない) | 自動リカバリ |
📊 実行ステータス: /api/status.json/
📦 データ鮮度: /api/cheap.json の generatedAt/
📡 RSS: /api/feed.xml/
💻 全ソースコード: github.com/shimanto/kyoudai-coorde