はじめに:ポートスキャンで見えない「ステルス機器」たち
LAN内ネットワークの端末調査をするとき、多くの人は nmap や Ping スイープを使います。
しかし、次のような経験はないでしょうか?
- 「Pingに応答しない(ICMP無効)設定のMacBookやプリンタが見つからない」
- 「IPとMACアドレスは分かったが、それが『会議室のスマートTV』なのか『誰かの私用スマホ』なのか分からない」
- 「ポートスキャンをかけると、LAN内のUTMやセキュリティ機器がアラートを吹き出して大騒ぎになる」
ネットワーク機器やスマートデバイスの多くは、通常のスキャンに対して閉じていますが、「自分から周囲に存在をアピールするパケット」 を定期的に撒き散らしています。
それが mDNS(Multicast DNS / Bonjour / Avahi) と SSDP(Simple Service Discovery Protocol / UPnP) です。
本記事では、ポートを叩いて回るアクティブスキャンではなく、マルチキャスト通信をわずか数秒受信(パッシブ待機)するだけで、ホスト名・モデル名・提供サービスを暴き出すPython探索スクリプト を紹介します。
1. mDNS探索の仕組み(ポート5353 / 224.0.0.251)
AppleのBonjourに代表されるmDNSは、同一L2セグメント内の機器同士がDNSサーバーなしで名前解決やサービス発見を行う仕組みです。
スキャナーから 224.0.0.251:5353 宛てに 「どんなサービスがありますか?(_services._dns-sd._udp.local)」 というクエリを1発投げるだけで、LAN内の機器が一斉に応答を返してくれます。
- プリンタなら:
_ipp._tcp.local(インターネット印刷プロトコル) - Mac/iOSなら:
_airplay._tcp.local,_companion-link._tcp.local - ファイルサーバーなら:
_smb._tcp.local - スマートスピーカーなら:
_googlecast._tcp.local
2. Pythonによる軽量mDNSスキャナーの実装
外部の重いライブラリを入れずとも、Pythonの標準 socket モジュールだけでマルチキャスト送受信が可能です。(手軽に扱うなら zeroconf ライブラリを使うと数行で書けます)
💻 コア実装・設定スニペット(抜粋)
# コア実装ロジック(要点抜粋)
from zeroconf import Zeroconf, ServiceBrowser
import time
class DeviceListener:
def __init__(self):
self.found_devices = []
def remove_service(self, zeroconf, type, name):
pass
def add_service(self, zeroconf, type, name):
info = zeroconf.get_service_info(type, name)
if info:
addresses = [f"{socket.inet_ntoa(addr)}" for addr in info.addresses]
server = info.server
props = {k.decode('utf-8', 'ignore'): v.decode('utf-8', 'ignore') if isinstance(v, bytes) else v
for k, v in info.properties.items()}
device_info = {
"name": name,
"type": type,
"server": server,
"ip": addresses[0] if addresses else "unknown",
"port": info.port,
"properties": props
}
print(f"[+] 発見: {name} ({device_info['ip']}:{info.port}) -> モデル: {props.get('model', 'N/A')}")
self.found_devices.append(device_info)
import socket
def scan_mdns_devices(timeout_seconds: int = 5):
zeroconf = Zeroconf()
listener = DeviceListener()
# 探索対象の主要サービスタイプ
target_services = [
"_ipp._tcp.local.", # プリンタ
"_airplay._tcp.local.", # Apple機器
"_googlecast._tcp.local.", # Chromecast / Smart TV
"_smb._tcp.local.", # NAS / Windows共有
"_workstation._tcp.local." # Linux / Ubuntu
]
browser = ServiceBrowser(zeroconf, target_services, listener)
print(f"[*] mDNS探索中 ({timeout_seconds}秒間)...")
time.sleep(timeout_seconds)
zeroconf.close()
return listener.found_devices
3. SSDP(UPnP)によるスマート家電・ルーター探索
mDNSに応答しない機器(スマートTV、ネットワークカメラ、ルーター等)は、SSDP(239.255.255.250:1900) に反応します。
M-SEARCH というHTTPライクなUDPパケットを投げると、機器の詳細情報URL(XML)を返してくれます。
まとめ:ノイズを出さずに「機器の正体」を暴く
従来の「全IPアドレスの全ポートを叩きまくるスキャン」は、ネットワーク機器に過度な負荷をかけ、ファイアウォールにブロックされる時代遅れの手法になりつつあります。
- パケットを投げずに、端末自身の「自己紹介パケット(mDNS/SSDP)」を聴く
- ホスト名だけでなく、メーカー名、モデル名、AirPlay/印刷対応状況まで一瞬で特定できる
- わずか数秒でネットワーク帯域を一切消費せずに完結する
LAN内の「正体不明なIPアドレス」の特定に悩んでいるインフラエンジニアの方は、ぜひこのゼロコンフィグ探索をツールに組み込んでみてください!
📚 さらに詳しいアーキテクチャ設計・パラメータ表・トラブルシューティング
最後までお読みいただきありがとうございます!
本記事が少しでも「役に立った」「あとで試したい」と感じていただけましたら、ぜひQiitaの 「いいね(♡)」 と 「ストック」、および アカウントのフォロー をいただけると今後の検証・執筆の大きな励みになります!
また、本記事のさらに踏み込んだ 「深層アーキテクチャ解説」「主要パラメータの技術的根拠」「現場アンチパターン・トラブルシューティング対応表」 は、以下のGitHub技術リファレンスにて公開しています。
👉 【第18弾 詳細技術リファレンス (QIITA_ARTICLE_DETAIL_18.md)】
⭐ 全14層・200パターンの自立型インフラ&オンプレAIリファレンス集(おじさんの武器庫)を順次公開中です。ぜひGitHubリポジトリへの Star (★) と X (@OjisanTechnical) のフォローもお願いいたします!
👉 GitHub リポジトリ: ojisantech/ojisan-arsenal
💡 【検証環境・個人研究(PoC)に関する注記】
本記事は、筆者個人の自宅検証環境(ホームラボ/仮想環境)において、公開情報およびOSS(オープンソースソフトウェア)を用いて独自に構築・検証した個人研究(PoC)の記録です。特定の企業・団体の実環境や業務上の非公開情報とは一切関係ありません。