0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Nmap を GUI で回して「怪しい端末」を可視化するツールを作った話 – rogue-finder

Posted at

Nmap を GUI で回して「怪しい端末」を可視化するツールを作った話 – rogue-finder

社内ネットワークや自宅の LAN に、**いつの間にか増えた「誰のものか分からない端末」**ってありませんか?

  • いつの間にか生えている Wi-Fi ルーター
  • 情報システムは知らない NAS
  • 放置された Windows 機・Raspberry Pi
  • シャドー IT 的なクラウドゲートウェイ

こういった 「Rogue(不正/未管理)な端末」をどう見つけるか は、ゼロトラストや ASM(Attack Surface Management)が叫ばれる昨今でも、現場レベルでは結構な手作業だったりします。

そこで今回は、Nmap をベースに LAN 上のホストをディスカバリして、「怪しさスコア」でソートしてくれる GUI ツールを作りました。

名前はそのまま rogue-finder です。


この記事で書くこと

  • なぜ rogue-finder を作ったのか(問題意識)
  • ツールの概要と特徴
  • 「怪しさスコア」の設計(何をどう点数化しているか)
  • 実際の使い方(Nmap CLI に馴染みがなくても触れるレベルで)
  • 実装のポイント(PySide6 / multiprocessing / nmap --script safe 連携)
  • 今後の拡張アイディア

なぜ作ったか – Nmap + 表計算の限界

ネットワーク上の未管理端末を見つけるだけなら、正直 Nmap だけでも十分です。

nmap -sn 192.168.0.0/24
nmap -O -p 22,80,443,445,3389 192.168.0.0/24

…といったコマンドでスキャンして、結果を CSV に落として Excel やスプレッドシートで整理する、という運用をしている方も多いと思います。

ただ、実務でやってみると次のようなところでつまずきがちです。

  • コマンドライン前提のため、Nmap に不慣れなメンバーには渡しにくい
  • 照合・ソート・色付けなどを 毎回 Excel / Spreadsheet でやり直す
  • 「どのホストから優先的に見るべきか」が 人の感覚に依存してしまう

「nmap の出力 → 表計算で加工 → 怪しそうなものに目視でフラグ」というフローを自動化したい

というのが最初のモチベーションです。


rogue-finder とは

一言でいうと

Nmap を GUI からたたいて、ホストの「怪しさスコア」を自動で付けてくれる軽量ツール

です。

README の定義を要約すると、こんな感じのツールです:

  • Python / PySide6 製の クロスプラットフォーム GUI アプリ
  • ローカルにインストール済みの nmap コマンドを 外部プロセスとして呼び出す
  • ICMP / ポートスキャン / OS 推定の 3 フェーズで軽量ディスカバリ
  • 結果を独自ルールでスコアリングし、High / Medium / Low の優先度に分類
  • その場で nmap --script safe を単一ホストごとに叩ける診断ボタン付き
  • 結果は CSV / JSON / テキストレポートとしてエクスポート可能

商用スキャナに全部を任せるのではなく、その前段階として「どこにスキャナを当てるべきか」を整理するための前処理ツール、という位置づけです。


アーキテクチャ概要

中身は「ローカル GUI + マルチプロセス + nmap サブプロセス」というシンプルな構成です。

GUI (PySide6)
 └─ ScanManager
     └─ Worker (multiprocessing, ProcessPoolExecutor)
         └─ nmap subprocess
             ├─ XML parser
             └─ Rating engine
                 └─ Result table (GUI にバインド)

なぜ Nmap を「同梱」せず外部プロセスにしたか

  • Nmap は NPSL ライセンスの都合もあり、アプリにバンドルせず外部コマンドとして扱う方が OSS として公開しやすい
  • OS ごとに最適な Nmap の配布形態(公式インストーラ / Homebrew など)があるため、そこは各 OS のエコシステムに任せたい

という理由から、あくまで

  • rogue-finder: Nmap のフロントエンド & スコアリングエンジン
  • Nmap 本体: ユーザーが OS 標準の方法でインストールしたものを利用

という役割分担にしています。


スコアリング(怪しさレーティング)の考え方

ディスカバリで集めた情報をそのまま一覧で眺めても、結局「どこから見るか」で迷ってしまいます。

そこで rogue-finder では、以下のような要素をもとに 「怪しさスコア (0〜∞)」を付ける簡易ルールを定義しています:

  • ICMP 応答の有無
  • 開いているポートの種類
  • OS 推定の結果
  • 特定のポートの組み合わせ
  • 高番ポートの開放状況

1. ICMP 応答

  • ping に 応答があるホストは +2 点
    → 「ちゃんと動いている何かがある」ので監視対象。

2. ポート危険度

代表的にはこんなイメージで加点しています(ざっくり):

  • SMB / RDP / FTP など、攻撃対象になりやすいサービスが開いている: +2

    • 例: 21, 445, 3389, 5985
  • Redis / Memcached / MQ / DB など、インターネット側に出ていると危ない系: +2

  • Web 系の高番ポート: +1

    • 例: 3000, 8000, 8080, 8888 など

「開いていれば即アウト」という意味ではなく、優先的に調査対象にしたいサービスに点数を乗せていくイメージです。

3. OS 推定

nmap -O の結果から OS を大まかに分類し、以下のようなイメージで点数を足しています:

  • Windows / SOHO ルータ / IoT 機器など → +3
  • 古めの Linux → +2
  • サーバ用途の Linux(ちゃんと管理されていそうなもの) → +1
  • 不明だが何かしら動いている → +1

家庭用ルータや IoT デバイス、古い OS は、脆弱性や設定不備が残りやすいため高めに加点します。

4. ポートの組み合わせ

1ポートだけ見ても分からない「雰囲気」を、組み合わせルールで補正しています。

例:

  • 223306 / 5432 がセット → 「手元の管理用 Linux + DB かも」→ +2
  • 33891433 がセット → 「RDP + SQL Server」→ +2
  • 8080 + 5672 + 15672 → 「Web 管理画面付き MQ」→ +3

など、「よくある怪しげな役割」をスコアに乗せています。

5. 高番ポート

  • 50000 など、特定の高番ポートが開いている場合に +1
    → 一部製品固有の管理ポートなどをターゲットにしています。

6. 優先度へのマッピング

最後に、合計スコアからシンプルに優先度を割り当てています:

スコア 優先度 ざっくりした意味
8 以上 High 「真っ先に見るべき」
5〜7 Medium 「順番を付けて調べたい」
4 以下 Low 「今すぐでなくても良いが記録はする」

GUI 上では、この優先度に応じて 行の色を変えてハイライトしているので、High だけざっと目を通す、といった使い方ができます。


実際の使い方

1. インストール

前提

  • Python 3.11+
  • Nmap がインストール済みで PATH に通っていること

Windows の例:

  1. 公式サイト から Nmap をインストール
  2. インストーラの指示に従って進め、インストール後にターミナルを再起動

macOS の例:

brew install nmap

rogue-finder のセットアップ

git clone https://github.com/unagi/rogue-finder.git
cd rogue-finder
pip install -r requirements.txt

2. 起動

python -m nmap_gui.main
# 詳細ログを見たいときは
python -m nmap_gui.main --debug

PyInstaller で固めたバイナリも GitHub Releases に置いているので、Python を意識したくない人はそちらを使ってもらうこともできます。

※ Windows 初回起動時は SmartScreen、macOS では Gatekeeper の警告が出るので、信頼する場合は明示的に許可してください。

3. スキャンの流れ

GUI 上での基本操作は次の通りです。

  1. 対象 IP / CIDR を入力

    • 例: 192.168.0.0/2410.0.0.1-10.0.0.50 など、複数行やカンマ区切りもサポート
  2. 実行したい スキャンフェーズを選択(ICMP / Ports / OS)

  3. Start ボタンでスキャン開始

    • 内部では ProcessPoolExecutor で並列に nmap を回しています
  4. 結果テーブルにホスト一覧が表示され、スコアに応じて色分け

  5. 怪しそうなホストから順に、

    • Safe Script ボタンで nmap --script safe を実行
    • 診断結果をダイアログで確認しつつ、必要に応じて テキストレポートを保存
  6. 必要に応じて CSV / JSON にエクスポートし、他システムや Excel での分析に流す

Safe Script 診断の動き

Safe Script ボタンを押すと、そのホストに対して

nmap --script safe <target> ...

を実行します。

  • 実行中は 他の Safe Script ボタンとディスカバリ Start/Stop を無効化し、常に単一ジョブに制限
  • コマンド・開始/終了時刻・stdout/stderr などのログをダイアログで表示
  • そのまま safe-scan_<target>_<timestamp>.txt というファイル名で保存可能
  • 実行時間は -T4 前提の 2 分を基準にした擬似プログレスバーで表示し、実測平均が長くなったら動的に基準を伸ばす

Nmap に不慣れなメンバーに「このボタン押すと安全系スクリプトだけ走るよ」と渡せるのが地味に便利です。


実装ハイライト

1. GUI: PySide6 ベース

src/nmap_gui/gui.py で PySide6 のウィジェットを構築し、以下を扱います:

  • 入力フォーム(ターゲット IP / CIDR)
  • スキャンフェーズのチェックボックス
  • Start / Stop ボタン
  • 結果テーブル(ソート / 色付け)
  • Safe Script ボタンと診断ダイアログ

GUI スレッドとスキャン処理スレッドを切り離すことで、スキャン中でも UI が固まらないようにしています。

2. スキャンマネージャ: multiprocessing + ProcessPoolExecutor

src/nmap_gui/scan_manager.py は GUI とワーカープロセスの橋渡しを行い、以下を担当します:

  • スキャンジョブのキュー管理
  • ProcessPoolExecutor による並列実行
  • 途中キャンセル時のプロセス終了処理
  • 結果のマージと GUI への反映

CLI で nmap を単発実行するのと違い、GUI では「途中でやめたい」「今どこまで終わっているか知りたい」という要求があるため、ここをちゃんと整理するだけでも価値が出ます。

3. Nmap ラッパと XML パーサ

src/nmap_gui/nmap_runner.py では

  • subprocess での nmap 実行
  • XML 出力のパース
  • エラー・タイムアウトハンドリング

をひとまとめにし、上位層は「ターゲット」「モード」を指定するだけで済むようにしています。

4. レーティングエンジン

src/nmap_gui/rating.py にスコアリングロジックを閉じ込めておくことで、

  • ルールの追加・変更
  • ポートや OS 分類の微調整

を、GUI やスキャン部分に手を入れずに行えるようにしています。

たとえば、擬似コード的にはこんな構造です:

def rate_host(host):
    score = 0

    if host.icmp_alive:
        score += 2

    score += score_open_ports(host.open_ports)
    score += score_os(host.os_guess)
    score += score_combinations(host.open_ports)
    score += score_high_ports(host.open_ports)

    priority = classify_priority(score)
    return score, priority

こうしておくと、今後

  • 特定ベンダ機器向けのルール追加
  • 組織固有ポートの「要注意扱い」

なども比較的扱いやすくなります。

5. CI / リリースフロー

GitHub Actions で PyInstaller ビルドを回し、

  • main ブランチへの push で Windows 向けバイナリビルド
  • タグ(v1.0.0 など)を push すると Windows / macOS 向けバイナリを両方ビルド

というフローを組んでいます。
生成物は GitHub Actions のアーティファクトとしてアップロードされるので、そのまま Release に添付すれば配布形態として十分使える形になります。


今後の拡張アイディア

仕様書にも書いていますが、今後はこんな拡張を考えています:

  • SQLite への結果保存

    • 定期スキャンを蓄積して、後から検索・分析できるように
  • 差分検出

    • 「前回スキャンから増えたホスト」「ポート構成が変わったホスト」のみを抽出
  • ダークテーマ対応

    • 夜の監視室フレンドリーな UI に
  • CMDB / 資産管理との連携

    • 既知ホスト群との照合により、本当の意味での「Rogue 端末」を炙り出す

まとめ

  • rogue-finder は、Nmap の結果を GUI で扱いつつ「怪しさスコア」で並べてくれる軽量ツールです
  • ICMP 応答、開いているポート、OS 推定、ポートの組み合わせ、高番ポートなどを元にスコアリングし、どこから見るべきかの優先度を自動で決めてくれます
  • GUI ベースなので、コマンドラインに馴染みのないメンバーにも渡しやすく、nmap --script safe のワンクリック診断など「現場で実際に使う」ことを意識して作っています
  • まだシンプルなツールですが、資産管理や商用スキャナの前処理として、ちょうど良い立ち位置を目指しています

もし興味があれば、ぜひ試してフィードバックをもらえると嬉しいです 🙏

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?