InfraGuard

IP接続

サーバーごとのリモートピア IP をポート強度ドットで示すホストビュー。接続内訳・ロールアップ履歴・geo/ASN・評判・ブロック用ディープリンクを備えた IP 調査ポップアップ付き。

概要 — 何をする画面か

IP接続 は インフラ ▸ 接続とトラフィック の2番目の画面です(host view)。ポート接続 が「ポート → サーバー」を軸にするのに対し、この画面は 「サーバー(ホスト) → リモートピア IP」 を軸にします。各サーバーカードには、そのサーバーに現在接続しているリモート IP が接続の強さ順に並び、IP ごとに 監視対象ポート別のセッション強度ドット を表示します。目的は、どの IP がどのサーバーのどのポートに、どれだけ強く接続しているかを一目で把握することです。

ピア IP をクリックすると共有の IP 調査ポップアップ が開き、その IP の接続内訳(どのサーバー / ポート / TCP 状態 / セッション数)、ロールアップの接続履歴スパークライン、geo/ASN/ISP のエンリッチメント、外部の評判リンク、ブロックリスト へのブロック用ディープリンクを、すべて1か所で確認できます。

すべてのデータはレガシーのトラフィック DB(legacy_glory)から 読み取り専用 で取得します。この画面は一切書き込みを行いません — ブロックのような書き込み操作は、ポップアップのディープリンク経由で ブロックリスト 画面に引き渡され、書き込みはそちらで行われます。

こんなときに使う

画面構成

ヒーロー · タイマー

右上には、表示窓を決める タイマー切り替え(1分 / 5分 / 1時間)、最新スナップショットのタイムスタンプ、手動更新ボタンがあります。タイマーは、最新スナップショットを基点とするクエリ窓の長さです。

タイマー クエリ窓
1(既定) 最新スナップショットの1分間のみ
5 最新スナップショットから直近5分
60 最新スナップショットから直近60分

選択したタイマーは localStorage['infr:timer:traffic-ips'] に保存され、次回以降の訪問にも引き継がれます。許可されるのは 1/5/60 のみで、それ以外の値は 1 に強制されます。

強度の凡例 + サーバーチップ

サーバー(ホスト)カード

選択したサーバーごとに1枚のカード。ヘッダーにホスト名とピア数、本体はテーブルです。

カードはグリップでドラッグ並べ替えができ(順序は infr:order:traffic-ips に保存)、row-span masonry で再配置され、20件ずつページングされます。

ポート強度ドットの色

セッション数 トークン 色 意味
0 none 薄色 このポートでは未接続
1–9 good 緑 低い強度
10–49 warn 黄 中程度の強度
50+ crit 赤 高い強度

IP 調査ポップアップ

共有ミックスイン mixins/ip_detail.js +パーシャル infra/partials/ip-detail-modal.blade.php によって動作します。2つのモードがあります。

  1. sources モード — (サーバー, ポート) の窓におけるソース IP の一覧。ポート接続 の SRC サークルから入ります。
  2. investigate モード(この画面の既定の入口) — 単一 IP の詳細調査。ピアの行をクリックして入ります。

investigate モードが表示する内容:

領域 内容 ソース
サマリー KPI 合計セッション数 · サーバー数 · ポート数 · 初回/最終観測 ipSeenSpan()(保持期間全体の MIN/MAX(created_at))
Geo 国 · 都市 · ASN · ISP ip_info_loop(ipEnrichment())
接続履歴 粒度(5min / 1hour / 1day)のスパークライン ロールアップテーブル(ipHistory())
接続内訳 サーバー × ポート × TCP 状態のセッション · リモートポート · 初回/最終 traffic_session_ct(ipBreakdown())

ポップアップ下部のアクション(investigate): IP をコピー · IP を表示(?src_ip= でこのページ上で再調査)· 評判 ↗(外部の AbuseIPDB、新しいタブ)· IP をブロック(?add= で ブロックリスト へディープリンク)。

ポップアップの 評判 ↗ ボタンは、外部の abuseipdb.com/check/… を新しいタブで開く単なるリンクです。信頼度ゲージと通報履歴をコンソール内に表示する アプリ内の評判ポップアップ はセキュリティ画面の機能です — IP評判 を参照してください。

使い方

基本の流れ

  1. タイマー(1/5/60分)で窓を設定します。短いほど「今まさに接続中」に近くなります。
  2. サーバーチップ で対象のサーバーに絞り込みます(既定はすべて)。
  3. サーバーカード上で、赤い強度ドット(50件以上のセッション)を持つピアや、複数のポートにまたがる ピアを探します。
  4. 疑わしいピアの行をクリック して調査ポップアップを開きます。
  5. ポップアップでは 接続内訳 でどのサーバー/ポート/状態に接続したかを確認し、履歴 で持続性(単発か反復か)を測り、geo/ASN で発信元を把握します。
  6. 必要であれば 評判 ↗ で外部の通報履歴を確認し、悪性であれば IP をブロック で ブロックリスト に引き渡します。

履歴の粒度を切り替える

ポップアップの履歴セクションで粒度を切り替えると、参照するロールアップテーブルが変わります。既定の粒度は 時間単位(1hour) で、密度と速度のバランスが最も良い設定です。

5min    → traffic_session_ct_5min   · 個別 IP · 最新スナップショットから −6h の窓
1hour   → traffic_session_ct_1hour  · 個別 IP · 最新スナップショットから −3d の窓   (既定)
1day    → traffic_session_ct_1day   · /24 ブロック · 最新スナップショットから −120d の窓

日次(1day)の履歴は、個別の IP ではなくその IP の /24 ブロック(先頭3オクテット、256 IP)で集計されます — ロールアップのコレクターが _1day を C クラス単位で保存しているためです。そこでポップアップは、スコープを明示するために 211.224.128.0/24 のような CIDR スコープラベル を表示します。5min と 1hour は個別の IP をそのまま使います。

ディープリンク

/infra/traffic/ips?src_ip=203.0.113.10
/infra/traffic/ips?servers=glory,blue

ポーリング

ページは 30秒ごと に /infra/traffic/ips/live をポーリングして自動更新します(Reverb ではありません — コレクターは Laravel の外側で DB に書き込むため、ポーリングが妥当な選択です)。更新時、すべてが選択されていた場合は新たに現れたサーバーを自動的に含め、消滅したサーバーは選択から外します。

データソース

窓の基点

表示窓は アプリの now() ではなく、データの最新スナップショット(MAX(snapshot_ts))を基点とします。コレクターの保存時刻はアプリの時刻より最大で約9時間ずれることがあるため、now() を基準にした窓はデータの範囲外に落ちて何も表示されなくなります。

ホストビューのクエリ(ipPeers)

-- TrafficRepository::ipPeers(パラメータバインド)
SELECT server_name, remote_ip, local_port, SUM(session_count) AS total_sessions
  FROM traffic_session_ct
 WHERE snapshot_ts BETWEEN :min AND :max
   AND local_port IN (:ports)          -- OpsPolicy::monitoredPorts()
 GROUP BY server_name, remote_ip, local_port;

monitored ports はハードコードされていません — 運用ポリシー の infra_monitored_ports(CSV)から取得されます。ipsData() の結果は 20秒 キャッシュされます(キー infr:traffic:ips:v1:{timer}:{ports})。

調査ポップアップのクエリ

メソッド テーブル 処理内容
ipSeenSpan() traffic_session_ct MIN/MAX(created_at) = 実際の観測期間(保持期間は約8時間)、MAX(snapshot_ts) = その IP 自身の最新バッチ(内訳の基点)
ipBreakdown() traffic_session_ct サーバー×ポート×状態ごとのセッション合計 · リモートポート · 初回/最終(LIMIT 200)
ipHistory() ロールアップ3種 粒度ごとのセッション履歴(LIMIT 400)
ipEnrichment() ip_info_loop 国 · 都市 · ASN · ISP(存在しない場合は null で graceful)

接続内訳は、全体の最新窓ではなく、その IP 自身の最新スナップショットバッチを基点とします。 これは意図的な設計です。今は接続していないが過去にアクセスしてきた IP についても、最後に観測された時点から再構成して分布を表示できるようにするためです。

ロールアップのインデックスに関する注意(性能上の要点)

ipHistory() は常に direction IN ('inbound','outbound') を明示します。

-- _1day は複合インデックス t_ip(direction, remote_ip) を使う。
-- direction を明示しないと created_at の範囲だけをスキャンして 12秒以上かかる。
-- 明示するとインデックスが効いて約 20ms になる(2026-08-06 実測)。
SELECT created_at, SUM(session_count) AS sessions
  FROM traffic_session_ct_1day
 WHERE direction IN ('inbound','outbound')
   AND remote_ip = :cclass_key           -- 日次は /24 の先頭3オクテットのキーを使う
   AND created_at >= :since
 GROUP BY created_at
 ORDER BY created_at
 LIMIT 400;

ロールアップは巨大なので(_5min ≈ 209M · _1hour ≈ 112M · _1day ≈ 24M)、狭い created_at >= の窓と LIMIT が必須です。ポップアップの結果はキャッシュで保護されます: investigate は25秒、sources は20秒。

アクセス権限

トラブルシューティングと FAQ

カードが空で「この窓にピアがありません」しか表示されない。 最新スナップショットに、監視対象ポート上の接続が1件もないという意味です。(1) タイマーを 5 または 60 に広げる、(2) 実際のサービスポートが 運用ポリシー の infra_monitored_ports に登録されているか確認する、(3) 最近のスナップショットが traffic_session_ct に入っているか(コレクター check_ct.js)を確認する、の順に切り分けてください。

すべてが空で、スナップショットのタイムスタンプも表示されない。 legacy_glory 接続、あるいは traffic_session_ct 自体が空である可能性が高いです。.env の legacy_glory DB 認証情報と、トラフィックコレクターが動作しているかを確認してください。クエリが失敗した場合、ペイロードには error:true が含まれます。

日次の履歴だけが「この /24 ブロックの日次ロールアップ履歴がありません」と表示される。 日次の集計は1日ほど遅れることがあり、キーは /24 ブロックです。まず 5min と時間単位の粒度を確認してください。そのブロックにまだロールアップがない場合、これは想定どおりの動作です。

IP をクリックしたのに接続内訳が空になる。 その IP は直近のスナップショットにはセッションがなく、過去の観測のみが存在します。サマリー KPI の初回/最終観測と接続履歴で過去の活動を確認してください(内訳はその IP の最後のスナップショットバッチから再構成されます)。

ポップアップの「評判 ↗」がインライン表示ではなく新しいタブを開く。 これは意図した動作です。このトラフィックのポップアップは外部の AbuseIPDB リンクを使います。信頼度ゲージと通報履歴をコンソール内で見るには、セキュリティ画面の アプリ内評判ポップアップ を使ってください。

強度ドットの色は何で決まりますか。 ポート別の セッション数 バケットです — 1–9 は緑 · 10–49 は黄 · 50以上は赤 · 0 は薄いドット。列として表示されるのは監視対象ポートの先頭8つのみです。

関連項目

IP 연결 — 서버별 원격 peer
IP 연결 — 서버별 원격 peer