概要 — 何をする画面か
IP接続 は インフラ ▸ 接続とトラフィック の2番目の画面です(host view)。ポート接続 が「ポート → サーバー」を軸にするのに対し、この画面は 「サーバー(ホスト) → リモートピア IP」 を軸にします。各サーバーカードには、そのサーバーに現在接続しているリモート IP が接続の強さ順に並び、IP ごとに 監視対象ポート別のセッション強度ドット を表示します。目的は、どの IP がどのサーバーのどのポートに、どれだけ強く接続しているかを一目で把握することです。
ピア IP をクリックすると共有の IP 調査ポップアップ が開き、その IP の接続内訳(どのサーバー / ポート / TCP 状態 / セッション数)、ロールアップの接続履歴スパークライン、geo/ASN/ISP のエンリッチメント、外部の評判リンク、ブロックリスト へのブロック用ディープリンクを、すべて1か所で確認できます。
- ルート:
/infra/traffic/ips(ページ)·/infra/traffic/ips/live(ポーリング JSON)·/infra/traffic/ip-detail(調査 JSON) - コントローラー:
App\Http\Controllers\Infra\TrafficController@ips - ビルダー:
App\Services\Traffic\SessionQueryService::ipsData()+ipDetail() - ソースクエリ:
App\Repositories\TrafficRepository(レガシーのlegacy_glory接続、読み取り専用) - ソーステーブル:
traffic_session_ct(+ロールアップtraffic_session_ct_5min/_1hour/_1day、エンリッチメントip_info_loop)
すべてのデータはレガシーのトラフィック DB(
legacy_glory)から 読み取り専用 で取得します。この画面は一切書き込みを行いません — ブロックのような書き込み操作は、ポップアップのディープリンク経由で ブロックリスト 画面に引き渡され、書き込みはそちらで行われます。
こんなときに使う
- リモートピアの数が異常に多い サーバーを検出する(スキャン、ボットネット、クローラーの殺到)。
- 1つの IP が 複数のサーバー/ポートに同時に接続する 横展開パターンを捕捉する。
- IDS/ファイアウォールの警報で浮上した IP を トラフィックの側面から 追跡する(実際にどのサーバー・ポート・状態にセッションがあったのか)。
- ブロックを判断する前に、その IP の 接続量・履歴・geo・評判 を確認する。
- ポート接続 の SRC サークルから到達したソース IP を掘り下げる。
画面構成
ヒーロー · タイマー
右上には、表示窓を決める タイマー切り替え(1分 / 5分 / 1時間)、最新スナップショットのタイムスタンプ、手動更新ボタンがあります。タイマーは、最新スナップショットを基点とするクエリ窓の長さです。
| タイマー | クエリ窓 |
|---|---|
1(既定) |
最新スナップショットの1分間のみ |
5 |
最新スナップショットから直近5分 |
60 |
最新スナップショットから直近60分 |
選択したタイマーは localStorage['infr:timer:traffic-ips'] に保存され、次回以降の訪問にも引き継がれます。許可されるのは 1/5/60 のみで、それ以外の値は 1 に強制されます。
強度の凡例 + サーバーチップ
- 強度の凡例: ドットの色はポート別のセッション数バケットを表します —
1–9(good)·10–49(warn)·50+(crit)。 - サーバーチップ: どのサーバー(ホスト)を表示するかのフィルターです。既定はすべて選択 で、チップのフィルターは セッション限り(localStorage には保存しません)なので、新規訪問では全選択に戻ります。
[All]チップで全選択/全解除を切り替えます。
サーバー(ホスト)カード
選択したサーバーごとに1枚のカード。ヘッダーにホスト名とピア数、本体はテーブルです。
- 行(ピア) = リモート IP 1件。列は
Remote IP·Total(合計セッション数)· その後に 監視対象ポート別の強度ドット(監視対象ポートの先頭8つ)。 - ピアは 合計接続(セッション)数の降順 に並び、サーバーごとに最大 100 件まで表示されます。
- 強度ドットは、そのピアが各ポートで保持しているセッション数を色で表します(表を参照)。
- 行をクリックすると、その IP の調査ポップアップが開きます。
カードはグリップでドラッグ並べ替えができ(順序は 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つのモードがあります。
- sources モード — (サーバー, ポート) の窓におけるソース IP の一覧。ポート接続 の SRC サークルから入ります。
- 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/5/60分)で窓を設定します。短いほど「今まさに接続中」に近くなります。
- サーバーチップ で対象のサーバーに絞り込みます(既定はすべて)。
- サーバーカード上で、赤い強度ドット(50件以上のセッション)を持つピアや、複数のポートにまたがる ピアを探します。
- 疑わしいピアの行をクリック して調査ポップアップを開きます。
- ポップアップでは 接続内訳 でどのサーバー/ポート/状態に接続したかを確認し、履歴 で持続性(単発か反復か)を測り、geo/ASN で発信元を把握します。
- 必要であれば 評判 ↗ で外部の通報履歴を確認し、悪性であれば 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 をそのまま使います。
ディープリンク
?src_ip=203.0.113.10— ページ読み込み時に、その IP の調査ポップアップを自動的に開きます(他の画面や警報から遷移してきた場合に使用)。?alias=…/?servers=…/?server=…— サーバーチップのフィルターを事前適用します(カンマ/スペース区切り、大文字小文字を区別しない 一致)。この訪問限りで、保存はされません。
/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秒。
アクセス権限
- この画面はインフラの役割領域に属します(最小
user_level1)— 読み取り専用 なので、ログインしていれば誰でも(demo=1)閲覧できます。 - ページ、
/live、/ip-detailはいずれもinfr.auth(ログイン)配下にあり、追加のレベルゲートはありません。 - ここでは書き込みは発生しません。 ポップアップの IP をブロック は ブロックリスト 画面へのディープリンクであり、実際のブロック(
blacklist_infoへの書き込み)はuser_level2以上+監査ログとともにそちらで実行されます。
トラブルシューティングと 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つのみです。
関連項目
- ポート接続 — ポート → サーバーの PORT OVERVIEW(状態バー、SRC サークル)
- トラフィック(ネットワーク I/O) — サーバー別の in/out バイト数とパケットスループット
- ブロックリスト・評判 — ポップアップの「IP をブロック」ディープリンクの遷移先(書き込み+監査)
- IP評判 — コンソール内の AbuseIPDB 信頼度ゲージのポップアップ
- 運用ポリシー — 監視対象ポート(
infra_monitored_ports)の設定 - 警報 — しきい値超過時に担当者へ SMS/メールを送信
