Skip to content

MLIT環境 FW配下アクセス問題の調査

問題の概要

MLIT環境(mlit-eng-ai.hy-create.com)でFW(ファイアウォール/プロキシ)配下からアクセスした場合、チャットが正常に表示されない。

症状

  • 症状A(r.minoda型): チャット送信後、JSON.parse: unexpected character at line 1 column 1 エラー。ページ自体は読み込める
  • 症状B(yu.asano型): ページがOpen WebUIスプラッシュ画面("OI")で停止し、アプリが初期化できない
  • 別環境(FW外)からは正常に動作する
  • Metro環境(metro-ai.labs.basisconsulting.co.jp)は正常

環境

項目 Metro MLIT
ドメイン metro-ai.labs.basisconsulting.co.jp mlit-eng-ai.hy-create.com
AWS Account 534036492497 745651872545
Profile h.imura hy-imura
FW有無 なし あり(問題発生)

調査方法

ALBアクセスログの有効化

CoreInfraStackにS3バケットとALBアクセスログ設定を追加し、両環境にデプロイ。

  • S3バケット: {prefix}-v2-alb-logs
  • ログパス: alb-logs/{prefix}/AWSLogs/{account}/elasticloadbalancing/ap-northeast-1/YYYY/MM/DD/
# ログ取得コマンド
aws s3 cp s3://mlit-ai-v2-alb-logs/alb-logs/mlit-ai/AWSLogs/745651872545/elasticloadbalancing/ap-northeast-1/$(date +%Y/%m/%d)/ ./logs/ --recursive --profile hy-imura

# 特定IPのログを抽出
gunzip -c logs/*.gz | grep "203.180.239.93" | sort -k2

# WebSocket 101を検索
gunzip -c logs/*.gz | grep "^wss " | sort -k2

# chat/completionsのレスポンスサイズを確認
gunzip -c logs/*.gz | grep "chat/completions" | awk '{print $2, $9"/"$10, $11"B(recv)", $12"B(sent)"}'

調査結果

2026-01-27 r.minoda (IP: 203.180.239.93, FW内, Firefox/macOS)

chat/completionsリクエスト

JST時刻 ステータス レスポンスサイズ 処理時間 判定
14:14:42 200/200 14,231B 0.166s 正常
14:16:04 200/200 11,343B 0.181s 正常
14:43:00 200/200 246B 0.108s 異常
14:43:31 200/200 9,818B 0.167s 正常
15:25:16 200/200 10,463B 0.551s 正常
15:25:35 200/200 13,093B 0.168s 正常

WebSocket接続 (wss 101)

JST時刻 ステータス 送信 受信
14:14:05 101/101 359B 6,505B
14:14:06 101/101 359B 7,235B
14:14:18 101/101 359B 6,781B
14:43:21 101/101 2,667B 6,779B

15:25セッションではWebSocket接続のログなし(接続中でログ未出力 or 接続失敗)。

異常リクエスト

15:25:08  460/-  0B  GET /api/v1/models/model/profile/image?id=undefined
15:26:04  460/-  0B  GET /api/v1/models/model/profile/image?id=undefined
  • 460: ALBが応答する前にクライアント切断
  • id=undefined: フロントエンドがモデルIDを正しく渡せていない

詳細タイムライン(14:42-14:44 JST)

14:42:48  ページ操作開始(tools, functions, chats取得)
14:42:56  チャット削除
14:43:00  chat/completions → 200 - 246B ★異常(Agenticサーバーに未到達)
14:43:00  get_all_models() 呼び出し
14:43:05  chat/completed → 200(完了通知)
14:43:09  チャット閲覧
14:43:15  チャット削除 → ページ遷移
14:43:20  Ollama接続エラー(host.docker.internal:11434 - 想定内)
14:43:21  WebSocket wss 101 再接続
14:43:21  ページ再読込(GET /)
14:43:27  chat/completions → 200 - 9,818B(正常)
14:43:27  Agentic POST /v1/chat/completions → 200
14:43:29  Agentic Anthropic API → 200

注目点: 14:43:00のchat/completionsは246Bで即座に返却され、Agenticサーバーに到達していない。Open WebUI内部でエラー応答を返している。


2026-01-27 yu.asano (IP: 155.190.49.69, FW内, Edge/Windows)

症状

Open WebUIのスプラッシュ画面("OI"ロゴ)で停止し、アプリケーションが初期化できない。チャット画面に到達できず。

タイムライン

15:54:01  GET / → 302(Cognito認証リダイレクト)
15:54:09  OAuth callback → 302(認証成功)
15:54:10  GET / → 200(ページHTML取得)
15:54:12-17  静的ファイル(loader.js, custom.css, splash.png)→ 全て200
15:54:13-15:55  SvelteKit JSチャンク約150個 → 全て200
15:55:23  _app/version.json → 200
15:55:25  /api/config → 200 (571B)
15:55:26  /manifest.json → 200
15:55:52  /api/version → 200 (207B)
15:56:16  version.json polling → 200
15:57:20  version.json polling → 200
15:58:18  version.json polling → 200
15:59:22  WebSocket wss → 101/101(接続成功)

重要な不在

  • chat/completions = 0件(チャット画面に到達できなかった)
  • /api/v1/ 系API = 0件(アプリ初期化後のAPI呼び出しなし)
  • ページHTML・JSチャンクは全て200で返されているが、SvelteKitアプリが起動しない

プロトコルの差異

項目 r.minoda yu.asano
IP 203.180.239.93 155.190.49.69
プロトコル h2(HTTP/2) https(HTTP/1.1)
ブラウザ Firefox/macOS Edge/Windows
ページ読み込み 成功 失敗(スプラッシュ停止)
chat/completions 到達・一部破損 到達せず
WebSocket 成功 成功

yu.asanoのFW環境ではHTTP/2がHTTP/1.1にダウングレードされている。これがページ初期化失敗の一因の可能性がある。

推定原因

ALBログ上は全リクエストが200で返されているため、FWが以下のいずれかを行っている:

  1. JSファイルの中身を破損 - 約150個のJSチャンクのうち1つでも壊れればSvelteKitは初期化に失敗する
  2. APIレスポンス(/api/config等)の改変 - アプリ初期化に必要なJSON応答が破損
  3. HTTP/2→HTTP/1.1ダウングレードによる副作用 - 多数の並列リクエストの処理順序やヘッダの変化

ユーザー別障害パターンの比較

項目 r.minoda(症状A) yu.asano(症状B)
FW経由IP 203.180.239.93 155.190.49.69
プロトコル h2 (HTTP/2) https (HTTP/1.1)
ブラウザ/OS Firefox/macOS Edge/Windows
ページ読み込み 成功 失敗(スプラッシュ停止)
JSチャンク 正常読み込み ALB上200だが動作せず
chat/completions ALB到達・FWで破損 未到達(ページ初期化失敗)
WebSocket 成功(101) 成功(101)
エラー内容 JSON.parseエラー アプリ起動しない

同じFW配下でも、クライアント環境(ブラウザ/OS/プロトコル)により障害パターンが異なる。


結論: FW/プロキシがレスポンスを改変(破損)している

決定的な証拠

15:25 JSTセッションで、r.minodaがFW配下から2回チャットを送信し、両方ともJSON.parseエラーが発生した。 しかしALBログでは:

JST時刻 ステータス レスポンスサイズ 判定
15:25:16 200/200 10,463B ALB側は正常
15:25:35 200/200 13,093B ALB側は正常

ALB → バックエンド間は完全に正常(200/200、正常なレスポンスサイズ)にもかかわらず、ブラウザでJSON.parseエラーが発生している。

ブラウザ ←→ FW/Proxy ←→ ALB ←→ Open WebUI ←→ Agentic ←→ Anthropic API
              ↑
         ここでレスポンスが改変されている
         (ALBログには正常な応答が記録されているが、
           ブラウザに届く前にFWが内容を変えている)

これはFW/プロキシがALBからのレスポンスを改変していることの確定的な証拠である。

「切断」ではなく「改変/破損」

FWは接続を切断(ブロック)しているのではない。 レスポンスはブラウザに届いているが、中身が壊れている

  • エラーは JSON.parse: unexpected character at line 1 column 1 = レスポンスの最初の1文字目から既にJSON形式でない
  • 接続切断であれば、ネットワークエラーやタイムアウトエラーになるはず
  • 実際にはレスポンスを受信した上でパースに失敗しているため、FWがレスポンスボディを書き換えていると判断できる

FWが行っていると推定される動作

  • SSEストリームのバッファリング: text/event-streamレスポンスをバッファして一括送信→フォーマット破損
  • SSL/TLSインスペクション: HTTPS通信を復号・再暗号化する際にレスポンスボディを改変
  • コンテンツフィルタリング: レスポンスにスクリプトやヘッダを注入
  • Content-Encodingの不整合: 圧縮/展開処理でデータ破損

2種類の障害パターン

FW配下からのアクセスで、クライアント環境により異なる障害が発生:

  • 症状A(r.minoda型): ページは読み込めるが、SSEレスポンス(chat/completions)がFWにより破損。JSON.parseエラー
  • 症状B(yu.asano型): ページ自体が初期化できない。JSチャンクまたはAPIレスポンスがFWにより破損し、SvelteKitアプリが起動しない

HTTP/2で接続できるr.minodaはページ初期化に成功するが、HTTP/1.1にダウングレードされるyu.asanoはページ初期化自体に失敗している。

その他の確認事項

  1. WebSocket (101 Switching Protocols) はFW経由でも成功する - FWはWebSocketをブロックしていない(両ユーザーとも)
  2. Agenticサーバー→Anthropic APIも正常 - バックエンドに到達したリクエストは全て成功
  3. Metro環境は完全に正常 - 27件のWebSocket 101、全chat/completions正常
  4. 14:43:00の246B応答: Open WebUI内部でAgenticに転送せず即座にエラー応答を返したケースも1件あり(27分間空白後の初回リクエスト)
  5. HTTP/2 vs HTTP/1.1: FWがHTTP/2→HTTP/1.1にダウングレードするケースがあり、これが障害の深刻度に影響

追加確認事項

ブラウザDevToolsでの確認(FWの改変内容の特定)

FW配下からアクセスし、ブラウザのDevTools > Networkタブで以下を確認すると、FWが具体的に何をしているかが判明する:

r.minoda(症状A: SSE破損)向け

  1. chat/completions リクエストの Response タブ(先頭数行)- 何が返ってきているか
  2. Response Headers(特にContent-Type, Transfer-Encoding, Content-Encoding)- FWが書き換えていないか
  3. FWが追加したヘッダの有無(Via, X-Forwarded-For等)

yu.asano(症状B: ページ初期化失敗)向け

  1. Console タブのエラーメッセージ(JavaScriptエラーがあるはず)
  2. Network タブで各JSチャンクの Response ボディが正しいJavaScriptか確認
  3. /api/config のレスポンスボディが正しいJSONか確認
  4. Response Headers でFWが Content-Encoding を書き換えていないか確認

参考: Metro環境との構成差異

CDKコード・ECS設定は共通(EnvironmentConfigの値のみ異なる)。 インフラレベルの差異はなく、ネットワーク経路(FWの有無)のみが異なる。


対策案

A. サーバー側対策(実装済み / 実装可能)

→ 詳細は sse-streaming-fix.md

対策 状態 効果
レスポンスヘッダー強化(X-Accel-Buffering: no 等) 実装済み FW/Proxyのバッファリング抑制
チャンクサイズ制御(50文字分割) 実装済み バッファリング時の影響を最小化
Keep-alive間隔短縮(5秒→1秒) 実装済み 接続維持の安定化
SSEイベントID追加 実装済み 順序保証

B. FW側対策(FW管理者への依頼が必要)

  1. text/event-stream レスポンスのバッファリング無効化
  2. mlit-eng-ai.hy-create.com をSSLインスペクション除外対象に追加
  3. WebSocket/SSE接続のアイドルタイムアウトを300秒以上に設定
  4. text/event-stream をWAF検査対象から除外

C. アプリケーション側の回避策

方法 概要 リスク
WebSocket無効化 ENABLE_WEBSOCKET_SUPPORT=false Open WebUI公式は非推奨
SSE → Polling切替 Open WebUIの設定で切替可能であれば リアルタイム性低下
レスポンスの非ストリーミング化 ストリーミングをOFFにする UX低下(一括表示)

関連ドキュメント

調査日

  • 2026-01-27(r.minoda、yu.asano のALBログ分析)
  • 2026-01-28(yu.asano の分析結果追記)