米国・ドイツ・日本の3拠点でT-Potを動かし、拠点によって届く通信に違いがあるのかを見ていました。
最初からLLM関連のハニーポットを作るつもりだったわけではありません。T-Potのログを確認していると、11434番ポートへの通信が目に入りました。11434番はOllamaが標準で使用するポートです。そこへ来ている通信は、公開されたOllamaを探しているだけなのか、モデル一覧を取得しようとしているのか、それとも実際に推論を実行しようとしているのでしょうか。
この疑問から米国サーバーで試作を始め、対象がOllama以外にも広がったため、現在は PromptPot という名前で公開しています。以下は、配備版v0.1.0で実際に観測した記録です。
送信元IP、外部の配布先URL、資格情報らしき値、実行可能なペイロード全文は掲載しません。
T-Potの11434番ログが気になった
11434番だけを抽出した最初の調査結果は、2026年7月2日20時54分JSTに保存しています。この時点ではPromptPotはまだありません。
| 拠点 | T-Pot上の11434関連イベント | 復元できたHTTPイベント | HTTP POST |
|---|---|---|---|
| 米国 | 73,024 | 3,990 | 0 |
| ドイツ | 46,722 | 2,702 | 0 |
| 日本 | 19 | 0 | 0 |
このT-Potイベント数は複数のイベント種別を含むため、後述するPromptPotのHTTPリクエスト数とは直接比較できません。
復元できたHTTP通信はすべてGETでした。/api/tags、/api/v1/version、/など、Ollamaに関係するパスもありました。一方、推論APIに見えるパスへの通信もメソッドはGETで、POSTのbodyや実際のプロンプトは残っていませんでした。
この時点では、11434番が探索されていることまでは分かりましたが、公開されたLLMを実際に使おうとしているのかは分かりませんでした。
11434番では何をしようとしているのか
Ollamaの公式APIドキュメントでは、APIの標準URLはhttp://localhost:11434/apiです。モデル一覧はGET /api/tags、生成はPOST /api/generate、チャットはPOST /api/chatで扱われます。
そこで、次の違いを見たいと考えました。
- ポートが開いているかだけを確認しているのか
-
/api/tagsや/api/versionからサービスやモデルを確認しているのか -
/api/generateや/api/chatへbody付きでPOSTしているのか -
/api/pullや/api/createなど、モデル管理まで試しているのか
既存のT-PotログではPOST bodyを確認できなかったため、11434番でOllamaに似たHTTP応答を返し、bodyを含むリクエストをJSONLへ保存する小さなサーバーを追加することにしました。
米国サーバーで小さく試した
最初は米国のT-PotだけにOllamaPotというコンテナを追加しました。既存のハニーポットは止めず、11434番の競合を確認してから、そのポートだけをコンテナへ割り当てました。
保存されている最初のOllamaPotログは2026年7月2日23時54分JSTです。これは設置日時ではなく、管理用テストを含む最初の記録時刻です。初期試作の正確なsource revisionは残っておらず、途中のログでは/api/psが404になっているものもありました。
この段階で確認したかったのは、OllamaらしいGETへ応答できることと、次のようなPOSTがbody付きで残ることでした。
GET /api/tags
GET /api/version
POST /api/generate
その後、1234、8000、7860、8188番でもAI周辺サービスに関係するパスが見えてきました。サービスごとにコンテナを増やすと管理しにくいため、1コンテナで5つのリスナーを持つ構成に変更し、名前もOllamaPotからPromptPotへ変えました。
PromptPotの構成
3拠点に配備したv0.1.0は、1つのPythonプロセスからポートごとにThreadingHTTPServerを起動します。実際のモデル、GPU、APIキーは使用していません。
| ポート | プロファイル | 模倣対象 |
|---|---|---|
| 11434 | ollama |
Ollama API |
| 1234 | lmstudio |
LM Studio / OpenAI互換API |
| 8000 | vllm |
vLLM / FastAPI系OpenAI互換API |
| 7860 | gradio |
Gradio系HTTP API |
| 8188 | comfyui |
ComfyUI HTTP API |
MCPとLangflowは実装済みプロファイルではなく、関連パスを集計時に分類したものです。
v0.1.0は、モデル一覧、version、health、生成・チャットなどへ静的な応答を返します。GETはプロファイル別ですが、POSTの一部は5ポートで共通処理されています。生成テキストは空で、モデル推論、ダウンロード、受信コードの実行、外向き通信は行いません。
1 HTTPリクエストを1 JSONLイベントとして、接続元、method、URL、User-Agent、status、body、model、prompt、messagesなどを保存します。JSONLはbind mountしたT-Potホスト側のログディレクトリへ書き、LogstashからElasticsearchへ取り込みました。
3拠点のログを集計し直した
対象期間と除外条件
2026年7月12日02時45分JSTに、3拠点からraw JSONLとElasticsearch文書を回収しました。今回の主集計は、Elasticsearchへ索引されていた外部イベント7,426件です。
- Elasticsearch上の最初の外部イベント: 2026年7月3日05時14分53秒JST
- Elasticsearch上の最後の外部イベント: 2026年7月12日02時38分02秒JST
- 対象: 3拠点のPromptPotと、米国で先に動かしたOllamaPot
- 除外: 管理元、センサー自身、loopback、Docker bridgeからの通信
- 除外前のElasticsearch文書: 7,478件
- 除外後の外部イベント: 7,426件
米国のOllamaPotについて、外部イベントとして残ったのは1件でした。集計ではOllamaプロファイルへ含めています。
各拠点の公開開始時刻は揃っていないため、国別件数をそのまま拠点差として比較することはしていません。
プロファイル別の件数
| プロファイル | ポート | 全イベント | POST/PUT | 推論イベント |
|---|---|---|---|---|
| Ollama | 11434 | 5,143 | 2,639 | 2,476 |
| vLLM | 8000 | 1,689 | 247 | 71 |
| LM Studio | 1234 | 422 | 59 | 0 |
| Gradio | 7860 | 108 | 33 | 0 |
| ComfyUI | 8188 | 64 | 0 | 0 |
| 合計 | 7,426 | 2,978 | 2,547 |
Ollamaプロファイルは全イベントの69.3%、推論イベントの97.2%でした。
全体では1,713セッションあり、そのうち推論イベントを含むものは236セッションでした。
推論より前に何が記録されていたか
推論セッション236件について、最初の推論イベントより前に、定義済みの探索GETまたはHEADがあるかを調べました。
- 先行する探索GET/HEADがあった: 207セッション(87.7%)
- 先行探索が記録されなかった: 29セッション(12.3%)
- 207セッションすべてで、推論と同じポート・プロファイルへの先行リクエストがあった
- 207セッション中205件では、先行探索の少なくとも1件がHTTP 200だった
- 残る2件では、先行探索として分類したリクエストへの応答は200ではなかった
矢印はセッション内の観測時刻順を表します。
先行していたパスの主なものは、/v1/modelsが150回、/api/tagsが68回、/api/versionが47回、/api/psが7回でした。これはパスの出現回数で、互いに排他的なセッション数ではありません。
実際に記録されたセッションの一つでは、先頭部分が次の順序でした。送信元は匿名化しています。User-Agentはaxios/1.18.1でした。
GET /v1/models
POST /v1/chat/completions
POST /v1/chat/completions
GET /v1/models
POST /v1/chat/completions
同じ並びは時間を空けて繰り返されていました。先にモデル一覧を確認してから推論しているようにも見えますが、最初から決められた順序を実行している可能性もあります。
実際に送られたプロンプト
2,547推論イベントのうち、prompt、messages、必要に応じてbodyから作った分析用テキストが空でなかったものは2,529件でした。特に多かった完全一致の例は次の通りです。
| 回数 | 実際の内容 |
|---|---|
| 588 | system: Today is April 27, 2026. | user: In one short English sentence: who built you, what is 17 times 23? |
| 437 | Return exactly this text and nothing else: LAYERCLOUD_AI_TEST_OK |
| 206 | hi |
| 145 | Answer only with the number: 7 What is 3 + 4? |
| 145 | Reply with exactly one word: blue |
| 145 | What is your model name? If unknown, answer exactly: unknown |
588回のプロンプトはドイツ拠点で記録され、匿名化した2つの送信元IPから、deepseek-r1:8bとqwen2.5:7bへ294回ずつ送られていました。
固定文字列、簡単な計算、モデル名の回答を求める内容が多く、可用性確認やフィンガープリントに使われていそうです。
Ollama以外の関連パスも届いた
MCPと思われる通信
MCP関連として分類したイベントは120件でした。
| 項目 | 件数 |
|---|---|
| GET | 24 |
| POST | 96 |
| 30分セッション | 41 |
/mcp |
41 |
/jsonrpc |
31 |
/ |
31 |
/sse |
11 |
/mcp-sse |
6 |
96件のPOSTは、すべてJSON-RPCのinitializeでした。93件のbodyではclientInfo.nameにCensysInspect/1.1を含み、protocolVersionは2025-03-26でした。残り3件は2025-06-18を宣言していました。これらのversionはMCP 2025-03-26 LifecycleとMCP 2025-06-18 Lifecycleに存在します。
body内ではCensysInspect/1.1を名乗っていました。
tools/list、resources/list、tools/callは観測されていません。v0.1.0はMCPを実装していないため、initializeには404を返していました。
LangflowのAPIと似た通信
Langflow関連として分類したイベントは27件で、POST 25件、GET 2件でした。4つの匿名化した送信元IP、5セッションに分かれていました。
| パス | 件数 |
|---|---|
/api/v1/auto_login |
12 |
/api/v1/validate/code |
7 |
/api/v1/flows/ または /api/v1/flows
|
7 |
/api/v1/runs |
1 |
同一の匿名化した送信元とUser-Agentによる8リクエストの並びが、ドイツ、米国、日本の3拠点で記録されていました。bodyには次の種類が含まれていました。
- shellを用いた外部ファイルの取得・実行
- Windows Installer形式のファイル取得・実行
- Pythonを用いた外部ファイルの取得・実行
- 認証状態やflow作成に関係する入力
外部URL、コマンド、資格情報らしき値は省略しています。
/api/v1/validate/codeは、CVE-2025-3248 / GHSA-rvqx-wpfh-mfx7で問題となったLangflow APIと一致します。パスとペイロードの形も、既知のLangflow向け試行とよく似ていました。
同じ送信元は404の後も同じリクエスト列を繰り返していました。
そのほかの候補API
Ollamaのモデル管理に関係するイベントは80件あり、そのうち41件は実装済みのPOST /api/showでした。ほかにAnthropic Messages互換が13件、Open WebUI固有パスが1件ありました。
現在の応答では見えなかった部分
v0.1.0では、MCP、Langflow、Anthropic Messagesと一部のモデル管理APIへ404を返します。受信コードは実行せず、外向き通信も行いません。
そのため、MCPのinitializeに成功応答を返した後や、Langflowらしいtokenやflow情報を返した後に、どのような通信が続くのかはまだ観測できていません。
また、未対応POSTのログstatusが200になる不具合があるため、今回の分析ではソースコードとローカルでの再現結果も使って応答を確認しました。現在のmainではこの不具合を修正しています。
これからどこまで実装するか迷っている
PromptPotはMIT Licenseで公開しています。
T-Potのような汎用基盤や、MCP専用のwaspholeを置き換えるものではありません。PromptPotは、実モデルを動かさず、1コンテナで複数のAIサービス用ポートを観測する範囲に絞っています。
今回のログからは、次の実装候補が残りました。
- status記録修正のリリース
- Ollamaモデル管理APIへの応答
- MCPの
initializeへの最小応答 - Langflow向けの偽tokenやflow状態
- Anthropic Messages互換API
ただ、対応するAPIを増やすほどよいとも限りません。MCPだけを深く実装するなら専用ハニーポットとの差が小さくなり、広く浅く対応しすぎると、PromptPotが何を観測するためのものなのか分かりにくくなります。
自分の3拠点だけでは観測環境も偏ります。別のネットワークで試してくれる人や、レスポンスfixture、テスト、MCP・Langflow周り、T-PotやKibanaとの連携を一緒に見てくれる人がいれば助かります。
手順はCONTRIBUTING.md、候補はROADMAP.mdとIssuesに置いています。
付録: v0.1.0をローカルで確認する
観測時と同じ公開イメージはghcr.io/ta-061/promptpot:0.1.0です。最初は外部公開せず、localhostだけへbindします。
mkdir -p log
docker run --rm --name promptpot \
-p 127.0.0.1:11434:11434 \
-p 127.0.0.1:1234:1234 \
-p 127.0.0.1:8000:8000 \
-p 127.0.0.1:7860:7860 \
-p 127.0.0.1:8188:8188 \
-v "$PWD/log:/data/honeypots/log" \
ghcr.io/ta-061/promptpot:0.1.0
別のターミナルから、Ollama形式のGETとPOSTを確認します。
curl -s http://127.0.0.1:11434/api/tags | jq
curl -s http://127.0.0.1:11434/api/generate \
-H 'Content-Type: application/json' \
-d '{"model":"qwen2.5:7b","prompt":"hello","stream":false}' | jq
生成レスポンスのresponseは空文字列です。ログは次の場所へ1行1JSONで保存されます。
tail -n 1 log/promptpot.log | jq
インターネットへ公開する場合は、管理ポートを公開せず、機密情報のない隔離環境を使用します。また、T-Pot上で既に使われているポートと、ログ保存先の永続化を先に確認します。