mDNS(Multicast DNS、マルチキャストDNS)は、DNSサーバーを置かずに「プリンター名.local」のような名前をLAN内で解決する仕組みです。仕様はRFC 6762で、問い合わせを同じネットワーク上の全機器へマルチキャストで送り、名前の持ち主だけが答えます。AppleのBonjourやLinuxのAvahiは、このmDNSとサービス発見のDNS-SDをまとめて実装したソフトウェアにあたります。
本記事では、宛先アドレスとポート、名前の確保手順、TTLの既定値といった仕組みをRFCの記述で押さえ、通常のDNSとの違いとデメリットを比べます。そのうえで、Pythonとサービスファイルでサービスを広告・探索するコード、ファイアウォールのログに出る「mdns.mcast.net」、タスクマネージャーに出る「mdns-discovery.exe」、ESETの「受信マルチキャストDNS要求」の正体、VLANやクラウドを越えられない理由と止め方まで順に扱います。
まとめ:mDNSの要点と、機器探索をmDNSに任せてよい範囲
- mDNSは「.local」で終わる名前を、IPv4なら224.0.0.251、IPv6ならFF02::FBのUDP 5353番へ問い合わせて解決します(RFC 6762)。
- 通常のDNSとの違いは、問い合わせ先のサーバーがなく、届く範囲が同じリンク(同じセグメント)に限られる点です。
- サービスの発見(「近くのプリンター一覧」など)は、mDNSの上で動くDNS-SD(RFC 6763)が担います。PTRでサービス一覧を取得し、SRV・TXTで接続先と属性を確認します。
- 224.0.0.251はルーターが転送しない範囲のアドレスです。VLANやサブネットを越えてサービスを発見するには、mDNSゲートウェイや、DNS-SDの情報を通常のDNSで参照できる構成などが必要です。クラウドの仮想ネットワークへはそのまま持ち込めません。
- 「mdns.mcast.net」は224.0.0.251の逆引き名で、ログに出ても不審な外部通信ではありません。「mdns-discovery.exe」はArduino IDEのボード探索ツールです。
- 社内でActive Directoryのドメイン名に「.local」を使うと、mDNSと衝突します。RFC 6762もMicrosoftも使用を推奨していません。
- デメリットは、認証がなく同じLANの誰でも応答できること、機器名や提供サービスがLAN全体に見えること、ルーターを越えないことの3点です。インターネット側からUDP 5353へ届く状態は、情報漏えいとDoS攻撃の踏み台につながるため、境界で必ず遮断します。
判断を先に書くと、mDNSは「同じLAN内で、利用者が機器のIPアドレスを知らなくてもつながる」ことに価値がある技術です。家庭や会議室、工場の1セグメント内での機器探索には向き、セグメントやクラウドをまたぐ名前解決には向きません。後者は通常のDNSか、機器側から接続を張る方式で設計します。
mDNSの仕組み:宛先アドレス・名前の確保手順・TTLの既定値
通常のDNSは、クライアントが決められたDNSサーバーへ問い合わせます。mDNSには問い合わせ先のサーバーがありません。代わりに、同じリンク上の全機器が受け取るマルチキャストアドレスへ質問を投げ、その名前を持つ機器が自分で応答します。RFC 6762は、完全修飾名が「.local.」で終わる名前をリンクローカルと定め、その解決にmDNSを使うとしています。
宛先アドレス・MACアドレス・UDPポート番号とパケットの照合値
RFC 6762 5.1節は、問い合わせ先を「224.0.0.251:5353(IPv6では[FF02::FB]:5353)」と定めています。パケットキャプチャやファイアウォールの設定で照合するときは、次の値を見ます。
| 項目 | 値 | 根拠 |
|---|---|---|
| IPv4マルチキャストアドレス | 224.0.0.251 | RFC 6762・IANA登録 |
| IPv6マルチキャストアドレス | FF02::FB | RFC 6762 |
| トランスポート/ポート | UDP 5353 | RFC 6762 |
| 宛先MACアドレス(IPv4) | 01:00:5e:00:00:fb | IANAのマッピング規則 |
| 対象の名前 | 「.local.」で終わる名前 | RFC 6762 3節 |
MACアドレスは、IPv4マルチキャストアドレスの下位23ビットを01:00:5e:00:00:00に重ねるIANAの規則から導かれます。224.0.0.251の下位は0x0000fbなので、対応するMACアドレスは01:00:5e:00:00:fbです。アドレスの登録状況はIANAのIPv4マルチキャストアドレス一覧で確認できます。
名前の確保手順:プローブ3回とアナウンスで重複を避ける仕組み
mDNSでは、各機器が自分で名前を名乗ります。重複を避けるため、使う前に確認の手順を踏みます(RFC 6762 8節)。
- 0〜250ミリ秒のランダムな待ち時間のあと、「この名前を使っている機器はいるか」というプローブを250ミリ秒間隔で3回送る。
- 3回目から250ミリ秒たっても競合する応答がなければ、その名前を自分のものとして使い始める。
- アナウンスとして、問い合わせを待たずに自分のレコードをまず1秒間隔で2回送る。追加送信する場合は、送信間隔を毎回少なくとも2倍に広げ、合計8回までとする。
競合が見つかった側は、その名前をあきらめて別名を選びます。RFCは例として末尾に「2」を付ける方法を挙げています。家庭のLANで同じ型番のプリンターが「Printer-2.local」のような名前になるのは、この手順の結果です。
レコードTTLの推奨値:ホスト名は120秒、サービス情報は75分
RFC 6762 10節は、レコードの種類ごとにTTLの推奨値を分けています。
- ホスト名を含むレコード(A・AAAA・HINFO、ホスト名を指すSRV、逆引きPTR)は120秒。
- それ以外のレコード(DNS-SDのPTR・TXTなど)は75分(4,500秒)。
継続して必要なレコードは、TTLの80〜82%が経過した時点で再問い合わせの対象になり、応答がなければ85〜87%、90〜92%、95〜97%でも再試行されます(5.2節)。正常に停止する機器は、TTLを0にした「goodbye」パケットを送り、周囲のキャッシュから自分を消します。機器を撤去しても一覧から消えないなら、goodbyeを送らずに電源を切られた機器のサービス情報が、キャッシュに残っていないかを確認してください。python-zeroconf 0.151.5で広告したsensor-01.localをmacOS 26.6のdns-sd -G v4で引いたところ、TTL欄は120でした。python-zeroconfは、ホスト名のレコードのTTLの既定値を120秒、それ以外を4,500秒としています。
パケットの見分け方:QU/QMビット・キャッシュフラッシュビット・既知応答の抑制
mDNSのパケットは通常のDNSと同じ形式ですが、クラス欄(16ビット)の最上位ビットを独自の意味で使います。キャプチャを読むときに「クラスが0x8001になっている」「問い合わせに回答欄が入っている」と戸惑うのは、この3つの仕組みのためです。
- QU/QMビット(問い合わせ側):RFC 6762 5.4節は、問い合わせのクラス欄の最上位ビットを「ユニキャストでの応答も受け付ける」印と定めています。このビットが立った問い合わせを「QU」、通常のマルチキャスト応答を求める問い合わせを「QM」と呼びます。スリープ復帰やケーブル接続の直後は、最初の一斉問い合わせにQUを使い、再送からはQMに戻すのが推奨です。
- キャッシュフラッシュビット(応答側):応答のクラス欄の最上位ビットが立っていると、「この名前と種類のレコードはこれで全部」という意味になります(10.2節)。受け取った機器は、1秒より古い同じレコードを1秒後に破棄します。クラスが0x8001と表示されるのは「クラス1(IN)+このビット」で、0x8001というクラスが存在するわけではありません。
- 既知応答の抑制(Known-Answer Suppression):問い合わせ側は、すでに知っている答えを問い合わせの回答欄に入れて送ります(7.1節)。応答側は、既知応答の残りTTLが、自分の持つ正しいTTLの半分以上なら応答を抑制します。プリンター一覧の再読み込みで応答が少ないのは、この仕組みが効いているためです。
通常のDNS・LLMNRとの違い:問い合わせ先・ポート・届く範囲
ローカルの名前解決には、mDNSのほかにMicrosoftが使ってきたLLMNR(RFC 4795)があります。3つの違いは次のとおりです。
| 項目 | DNS | mDNS | LLMNR |
|---|---|---|---|
| 問い合わせ先 | DNSサーバー(ユニキャスト) | 224.0.0.251/FF02::FB | 224.0.0.252/FF02::1:3 |
| ポート | 53 | UDP 5353 | 5355 |
| 名前の範囲 | インターネット全体 | .local | 単一ラベルの名前など |
| 届く範囲 | ルーターを越える | 同じリンクのみ | 同じリンクのみ |
| 管理者 | ゾーンの管理者 | 各機器が自分で名乗る | 各機器が自分で名乗る |
| 仕様 | RFC 1034/1035 | RFC 6762 | RFC 4795 |
通常のDNSでは、名前とIPアドレスの対応をゾーンの管理者が登録し、権威サーバーが答えます。mDNSは登録作業そのものをなくし、機器が電源を入れた時点で名前を名乗る方式です。手間がない代わりに、誰が名乗っても止める仕組みがなく、届く範囲も同じリンクに限られます。DNSの応答に署名を付けてなりすましを防ぐDNSSECのような仕組みもmDNSにはありません。署名による検証の考え方はDNSSECとは?DNSの安全性を守る仕組みと役割・導入手順をわかりやすく解説で整理しています。
Windowsは、Windows 10 バージョン1703でmDNSにネイティブ対応しました。MicrosoftのWindows Core Networking Teamは2022年4月22日、マルチキャストによる名前解決の標準はmDNSだと位置付けています。そのうえで、NetBIOS名前解決とLLMNRは「現在ほとんど使われていない」として、段階的に縮小していく方針を示しました。新しく構築する環境で、LLMNRに頼る設計を選ぶ理由はありません。
通常のDNSで名前とIPアドレスを結び付けるAレコードの書き方は、Aレコードとは?IPv4アドレスへの対応付けとAAAA/CNAMEとの違い・書き方・digでの確認を実装者向けに解説で扱っています。LAN内の機器に固定の名前を配りたいなら、mDNSに頼らずLAN用のDNSサーバーを置く方法もあり、構築例はPi-holeの使い方|v6のインストール・DNS設定・ブロックリスト管理が参考になります。
DNS-SDによるサービス探索:PTR・SRV・TXTの役割
「mDNS」と「DNS-SD」は混同されがちですが、役割が違います。mDNSは名前をIPアドレスへ変える手段で、DNS-SD(DNS-Based Service Discovery、RFC 6763)は「この種類のサービスを提供している機器はどれか」を探す手順です。DNS-SDは通常のDNSでも動きますが、LANではmDNSと組み合わせて使われます。AppleのBonjourやAvahiは、この2つをまとめて実装しています。
ネットワークプリンター(IPP)を探す場合、DNS-SDでは次のレコードを使います。以下は情報をたどる論理的な流れで、問い合わせの固定順序ではありません。PTR応答の追加レコードでSRV・TXT・A/AAAAも得られる場合があります。
- PTR:「
_ipp._tcp.local.」を問い合わせ、サービスのインスタンス名の一覧を得る。 - SRV:インスタンス名から、接続先のホスト名とポート番号を得る。
- TXT:同じ名前から、機種名や対応機能などの付加情報をkey=value形式で得る。
- A/AAAA:SRVが示したホスト名を、mDNSでIPアドレスに解決する。
「_services._dns-sd._udp.local.」にPTR問い合わせを送ると、LANで広告されているサービスの種類を一覧できます。macOSでLAN内に広告されているサービスの種類を列挙するには、次のコマンドが使用可能です。AirPlayなら_airplay._tcp、Chromecastなら_googlecast._tcpのように表示され、内容は接続しているLANと各機器の広告状況によって変わります。
dns-sd -B _services._dns-sd._udp local.
ルーターを越えて広域でDNS-SDを使いたい場合は、リンク上のmDNSレコードを通常のDNS名前空間へ公開する「Discovery Proxy」がRFC 8766で標準化されています。
Bonjour・Avahi・Windowsの実装とOSごとのmDNS担当プロセス
OSごとに、mDNSを処理するプログラムが違います。名前を見て「何のプロセスか」を判断する材料にしてください。
| 環境 | 実装・プロセス | 確認コマンドの例 |
|---|---|---|
| macOS・iOS | mDNSResponder(Bonjour) | dns-sd |
| Windows 10以降 | OS標準のmDNS | Wireshark(udp.port==5353) |
| Windows(追加導入) | Bonjourサービス | dns-sd |
| Linux | avahi-daemon+nss-mdns | avahi-browse |
| Android | NSD(サービス探索API) | アプリから API |
mDNSResponderとBonjourの役割・Windowsでの導入条件
mDNSResponderはAppleのmDNS/DNS-SD実装で、macOSではシステムのリゾルバーとBonjourのサービス広告・発見を担います。公開されているソースはapple-oss-distributions/mDNSResponderです。Windowsでは、iTunesなどのApple製品や「Bonjour Print Services for Windows」(Apple Supportで配布中の版は2.0.2)を入れると、「Bonjourサービス」としてmDNSResponder.exeが常駐します。Windows 10以降はOS自体がmDNSに対応しているため、Bonjour APIに依存するアプリを使わず、Windows標準のmDNS機能で用途を満たせるなら、Bonjourを追加する必要はありません。
Bonjourを入れたWindowsでdns-sdを実行し、「failed -65563 (Service Not Running)」で終わる場合は、Bonjourサービスが停止しています。-65563はAppleのdns_sd.hでkDNSServiceErr_ServiceNotRunningと定義された値で、デーモン(Windowsではシステムサービス)が動いていないことを示します。サービス管理画面で「Bonjourサービス」を開始すれば解消します。
Avahiとnss-mdns:Linuxで.localを名前解決させる構成
Linuxでは、avahi-daemonがmDNS/DNS-SDの応答と広告を担当します。2026年10月14日時点で、GitHubのavahi/avahiで「Latest」になっている安定版は2020年2月の0.8です。0.9系はリリース候補の段階で、最新のタグは2026年6月25日の0.9-rc5です。
avahi-daemonだけでは、ping raspberrypi.localのような一般のプログラムからの名前解決はできません。glibcの名前解決に組み込むプラグインがnss-mdnsで、/etc/nsswitch.confのhosts:行にmdns4_minimalなどを加えて有効にします。DebianやUbuntuではlibnss-mdnsパッケージとして入ります。nss-mdnsのREADMEがDebianの例として示す行は次のとおりです。
# /etc/nsswitch.conf の hosts 行
hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4
# アプリと同じ経路(NSS)で引けるかを確かめる
getent hosts raspberrypi.local
mdns4_minimalは「.local」で終わる名前と169.254.x.xのアドレスだけを扱い、[NOTFOUND=return]で見つからなければ通常のDNSへ問い合わせずに終えます。READMEは、確認にhostやnslookupを使わないよう注意しています。この2つはNSSを通らずDNSへ直接問い合わせるため、nss-mdnsが正しく動いていても「見つからない」と表示されます。既定の設定(/etc/mdns.allowなし)では、foo.bar.localのように3ラベル以上の名前は扱いません。社内DNSが最上位の「local」についてSOAレコードを返す環境でも、nss-mdnsは問い合わせを断ります。Raspberry Pi OSは初期状態でAvahiが動いており、「ホスト名.local」でSSH接続できるのはこの構成のおかげです。ラズパイを家庭内の機器制御に使う構成はラズパイでスマートホームを自作する方法|できること・Home Assistant構成・赤外線家電の操作で紹介しています。
GNOMEの「パスワードと鍵」(Seahorse)が「DNS-SD initialization failed: Daemon not running」と記録するのも、Avahiに関係するメッセージです。Seahorseのソースは、LAN内で共有されたPGP鍵を探すためにAvahiのクライアントを作り、失敗するとこの文をAvahiのエラー文付きで出します。「Daemon not running」はAVAHI_ERR_NO_DAEMONの文言で、avahi-daemonが動いていないという意味です。LANでの鍵共有を使わないなら動作に影響はなく、気になる場合はsystemctl status avahi-daemonで状態を確かめて起動します。
Android・ESP32の探索APIとMatterのDNS-SDサービス種別
AndroidアプリはNetwork Service Discovery(NSD)のAPIからDNS-SDを使えます。ESP32などのマイコンでも、ESP-IDFやArduinoのライブラリでmDNSの応答を実装できます。スマートホームの共通規格Matterも、機器の探索に使うDNS-SDのサービス種別を定めています。Matter 1.2のコア仕様は初期設定(コミッショニング)を待つ機器の探索に_matterc._udpを、Matter 1.4のコア仕様は運用中のノードの探索に_matter._tcpを使うと定めています。Wi-FiやEthernetのMatter機器とコントローラーを別のセグメントに置く設計では、後述するVLANの制約と同じ観点で、探索が届くかを確認します。
ChromeとEdgeのWebRTC:ローカルIPをmDNS名で隠す仕組みと解除ポリシー
Chromeは、WebRTCで取得できる端末のプライベートIPアドレスを、「1f4712db-ea17-4bcf-a596-105139dfd8bf.local」のようなランダムなmDNS名に置き換えて隠します。Chromeの開発チームは、この機能をChrome 76(2019年8月)で全面展開すると告知していました。Webページのスクリプトに社内のIPアドレスを読み取らせないための対策です。
一方で、社内のP2P配信のようにローカルIPアドレスが見えないと困る用途もあります。Chromeのポリシー定義は、WebRtcLocalIpsAllowedUrlsに登録したURLに限ってローカルIPアドレスをそのまま見せ、それ以外はmDNS名で隠すと説明しています(Chrome 79以降が対象)。Microsoftの「mDNS を無効にする方法」は、Microsoft eCDNのピア配信のためにEdgeとChromeでこのポリシーをレジストリから設定する手順です。同ページは、mDNSそのものを無効にするわけではないと明記しています。Windowsの名前解決に使うmDNSを止めたい場合は、後述するセキュリティの章を見てください。WebRTCの接続確立の流れはWebRTCとは?P2Pの仕組み・ICE/STUN/TURNからSFU選定・実装・運用判断まで実装者向けに解説で解説しています。
PythonとAvahiでmDNSのサービスを広告・探索するコード例
ここからは、自分でmDNSを動かして確かめる手順です。Pythonではpython-zeroconfが、mDNSとDNS-SDを純粋なPythonで実装したライブラリとして広く使われています。2026年10月14日時点で、PyPIの最新は2026年9月28日公開の0.151.5で、対応するPythonは3.10以上です。MacのXcodeコマンドラインツールに含まれる/usr/bin/python3(3.9.6)では0.151.5を導入できないため、3.10以上のPythonで仮想環境を作ります。この章の2つのコードは、zeroconf 0.151.5・Python 3.12・macOS 26.6の組み合わせで動作を確認しています。版の更新が速いライブラリなので、導入時に最新版を確認してください。
# インストール(Python 3.10以上の仮想環境の中で実行する)
python -m pip install zeroconf==0.151.5
python-zeroconfによるHTTPサービスの探索と一覧表示
次のコードは、LAN内で「_http._tcp」を広告している機器を10秒間探し、見つけた順に名前・IPアドレス・ポート・TXTの中身を表示します。プリンターを探すなら_ipp._tcp.local.、AirPlayなら_airplay._tcp.local.に置き換えます。このコードの構成は、プロジェクトのREADMEにある例に沿ったものです。
import time
from zeroconf import ServiceBrowser, ServiceListener, Zeroconf
class Logger(ServiceListener):
def add_service(self, zc: Zeroconf, type_: str, name: str) -> None:
# SRV・TXT・A/AAAAを問い合わせて接続情報をまとめて取得する
info = zc.get_service_info(type_, name)
if info:
print("発見:", name, info.parsed_addresses(), info.port, info.properties)
def remove_service(self, zc: Zeroconf, type_: str, name: str) -> None:
print("消失:", name)
def update_service(self, zc: Zeroconf, type_: str, name: str) -> None:
print("更新:", name)
with Zeroconf() as zc:
ServiceBrowser(zc, "_http._tcp.local.", Logger())
time.sleep(10) # 10秒だけ探索して終了する
add_serviceが呼ばれるのは、PTRの応答でインスタンス名を知った時点です。get_service_infoはそこからSRV・TXT・アドレスを追加で問い合わせるため、DNS-SDの章で説明した流れがそのままコードに表れています。何も表示されない場合は、同じセグメントに_http._tcpを広告する機器がないか、後述の「ファイアウォールによるUDP 5353の遮断」の節を確認します。
python-zeroconfによる自作機器のサービス広告
逆に、自分のプログラムを「見つけてもらう側」にするコードです。IoT機器や社内ツールが自分の管理画面を広告すると、利用者はIPアドレスを知らなくても接続先を発見できます。ただし、このコードはHTTPサーバーを起動しません。広告したIPアドレスの8080番で別途HTTPサーバーを動かし、対応クライアントからhttp://sensor-01.local:8080/apiへ接続します。プロジェクトのexamples/registration.pyと同じServiceInfoとregister_serviceを使います。
import socket
import time
from zeroconf import ServiceInfo, Zeroconf
info = ServiceInfo(
"_http._tcp.local.",
"sensor-01._http._tcp.local.",
addresses=[socket.inet_aton("192.168.1.50")], # 自機のLAN側IPアドレスに置き換える
port=8080,
properties={"path": "/api", "model": "demo"}, # TXTレコードとして広告される
server="sensor-01.local.",
)
zc = Zeroconf()
zc.register_service(info) # プローブで名前の重複を確かめてからアナウンスする
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
finally:
zc.unregister_service(info) # 停止時に登録を取り消し、周囲の一覧から消す
zc.close()
このスクリプトを動かしたまま、別の端末で前節の探索コードかavahi-browse -rt _http._tcpを実行すると、sensor-01が一覧に現れます。前節の探索コードでは、次のように表示されました(IPアドレスは広告時に指定した値になります)。
発見: sensor-01._http._tcp.local. ['192.168.1.50'] 8080 {b'path': b'/api', b'model': b'demo'}
TXTレコードの値はバイト列(b'...')で返るため、文字列として使うときはデコードします。スクリプトを止めると一覧から消えるのは、登録の取り消し時に周囲へ通知が送られるためです。このコードでは、サービス名が重複するとNonUniqueNameExceptionが発生します。自動で改名させるにはregister_serviceにallow_name_change=Trueを渡します。このとき「sensor-01-2」のように変わるのはサービスのインスタンス名で、serverに指定したホスト名ではありません。
Avahiのサービスファイルによる常駐サービスの広告
Linuxで常駐しているWebサーバーなどを広告するだけなら、プログラムを書く必要はありません。avahi.service(5)によると、/etc/avahi/services/*.serviceに置いたXMLが静的なDNS-SDのサービス情報として扱われます。replace-wildcards="yes"を指定すると、名前の中の%hがホスト名に置き換わります。
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">Sensor API on %h</name>
<service>
<type>_http._tcp</type>
<port>8080</port>
<txt-record>path=/api</txt-record>
</service>
</service-group>
# 配置して反映し、広告されているかを確かめる
sudo cp sensor-api.service /etc/avahi/services/
sudo systemctl reload avahi-daemon
avahi-browse -rt _http._tcp
サービスファイル方式は、広告する内容が固定で、プロセスの起動・停止と連動させる必要がない場合に向きます。プロセスが止まっても広告は残るため、死活と連動させたいならアプリ側でpython-zeroconfなどを使って広告するほうが実態と一致します。
ログやタスクマネージャーに出るmDNS関連の名前と正体の見分け方
ログの宛先名・プロセス名・設定項目名は、それぞれ意味が異なります。
mdns.mcast.net:224.0.0.251を逆引きしたときの名前
ルーターやファイアウォールのログ、netstatの結果に「mdns.mcast.net」と出るのは、宛先の224.0.0.251をDNSで逆引きした名前です。RFC 6762 22節は、IANAが次のレコードを登録していると記しています。
251.0.0.224.IN-ADDR.ARPA. IN PTR MDNS.MCAST.NET.
実際にdig -x 224.0.0.251を実行するとmdns.mcast.net.が返り、逆にmdns.mcast.netを正引きすると224.0.0.251が返ります。つまり、ログの「mdns.mcast.net」はLAN内のmDNS通信そのもので、外部サーバーとの通信ではありません。
mdns-discovery.exe:Arduino IDEのボード探索ツール
Windowsのタスクマネージャーやファイアウォールの許可ダイアログに出る「mdns-discovery.exe」は、Arduinoが公開しているネットワーク上のボード探索ツールです。GitHubのarduino/mdns-discoveryで公開されており、Arduino IDE 2.x やarduino-cliが、Wi-Fi接続のボードへOTAで書き込む際に使います。
ソースを読むと、サービス名は_arduino._tcpで、30秒ごとにmDNS問い合わせを送り、1回の問い合わせは15秒で打ち切る作りです。IDEを開いている間に「常にネットワークへアクセスしようとする」ように見えるのはこのためです。ネットワーク経由で書き込まないなら、ファイアウォールで許可しなくても、USB接続での書き込みには影響しません。1.0.12で報告されたWindows 11の探索問題(Issue #87)は修正済みとして閉じられており、2026年10月14日時点で、GitHub Releasesの最新版は2026年7月3日公開の1.1.0です。arduino-cliの使い方はarduino-cliとは?インストールからコンパイル・書き込み・CI自動化まで実践ガイドを参照してください。
ESETの「受信マルチキャストDNS要求」は実はLLMNRの設定
ESET製品のファイアウォールの詳細設定には、「受信マルチキャストDNS要求」を扱う項目があります。ESET Internet Security 16.0の公式ヘルプでは、項目名は「信頼ゾーンでマルチキャストアドレスの解決を許可(LLMNR)」で、説明文は「ファイアウォール経由での信頼ゾーンからの受信マルチキャストDNS要求を許可します」です。名前は似ていますが、対象はmDNS(5353番)ではなくLLMNR(5355番)です。mDNSのプリンター検出やAirPlayがつながらない原因を探すときは、この項目ではなく5353番を扱うルールを確認します。
診断コマンドで.localの名前解決とmDNSの応答を確かめる手順
「.localの名前が引けない」ときは、mDNS対応の診断コマンドの結果と、一般アプリと同じ経路での名前解決の結果を比べると、どこで止まっているかを切り分けられます。dns-sdはmacOSのmDNSResponderを利用するため、OSの名前解決サービス自体を迂回するものではありません。
OS別診断コマンドによる名前解決とサービス応答の確認
# macOS:ホスト名をIPv4アドレスに解決
dns-sd -G v4 myhost.local
# Linux(Avahi):ホスト名の解決と、全サービスの一覧
avahi-resolve -n myhost.local
avahi-browse -art
# Linux:アプリと同じ経路(NSS)で引けるか
getent hosts myhost.local
# OS共通:digで224.0.0.251の5353番へ直接問い合わせ
dig -p 5353 @224.0.0.251 myhost.local
# パケットを見る(インターフェース名は環境に合わせる)
sudo tcpdump -i en0 -n udp port 5353
digやコマンドで引けるのにアプリから引けない場合は、OS側の設定(Linuxならnss-mdnsの未設定)を疑います。コマンドでも応答がない場合は、入力したホスト名、問い合わせ元のmDNSサービス、接続インターフェース、相手の広告設定、ファイアウォールやマルチキャストの到達性を順に確認します。avahi-browseの-aは全種類、-rは名前解決、-tは一覧を出し終えたら終了する指定です。tcpdumpで問い合わせだけが見える場合も、遮断とは断定できません。名前の誤り、応答側サービスの停止、既知応答による応答抑制、キャプチャ対象インターフェースも確認します。
digの結果でTTLが10秒になる理由と、digに答えない実装
digは5353番以外の送信元ポートから1回だけ問い合わせる、簡易な問い合わせ元です。RFC 6762 6.7節は、送信元ポートが5353でない問い合わせを「レガシーユニキャスト」として扱い、送信元へユニキャストで返すことを必須(MUST)とし、その応答のTTLは10秒を超えないよう推奨(SHOULD NOT)しています。キャッシュを更新する仕組みを持たない問い合わせ元に、古い情報を長く残させないためです。
2026年10月14日にmacOS 26.6.2で試した結果は次のとおりです。
- 自機のホスト名を
dig -p 5353 @224.0.0.251で引くと、mDNSResponderからTTL 10秒のAレコードと、追加情報のAAAAレコードが返った。digは同時に「WARNING: .local is reserved for Multicast DNS」と警告を表示した。 - python-zeroconf 0.151.5で広告した
sensor-01.localは、dns-sd -G v4ではTTL 120秒で解決できたが、digでは4秒待ってもタイムアウトした。
TTLが10秒と短いのは、6.7節の推奨に沿った値で、不具合ではありません。また、実装によってはdigのような簡易な問い合わせに答えないため、digで応答がないことだけを根拠に「機器がmDNSに応答していない」と判断するのは早計です。dns-sdやavahi-resolveの結果と合わせて判断してください。
つながらない原因:.localドメイン・VLAN・ファイアウォールの3点
Active Directoryの「.local」ドメインとmDNSの衝突
社内のADドメインを「example.local」のように作っている環境では、Macやスマートフォンが「.local」をmDNSで引きに行き、社内DNSの名前が解決できない、または遅くなる問題が起きます。RFC 6762 付録Gは、「.local」をユニキャストDNSのプライベートなトップレベルドメインに使うとmDNSと衝突し、余計な通信や解決の遅れを招くとして、使用を推奨していません。Microsoftも、ADを含むドメイン名には自社で登録したドメインのサブドメインを使い、「.local」のような特殊用途の名前を避けるよう案内しています。既存のADドメインは簡単には改名できないため、新規構築時に避けるのが現実的な対策です。
VLAN・サブネット間でmDNSの探索が届かない理由と中継の方法
224.0.0.251は、RFC 5771が「リンク外へ転送されない制御用トラフィック」と定める224.0.0.0/24の範囲にあります。そのため、来客用Wi-Fiと社内LANをVLANで分けると、別のVLANにあるプリンターやChromecastは見えなくなります。セグメントの分け方はVLANとは?仕組み・ポートVLAN/タグVLAN・IEEE 802.1QからVLAN間ルーティング設計まで実装者向けに解説を参照してください。
越えさせる方法は、ルーター上でmDNSを中継する「mDNSゲートウェイ(リフレクター)」です。Avahiでは/etc/avahi/avahi-daemon.confの[reflector]節でenable-reflector=yesとすると、受け取ったmDNSを接続中の全インターフェースへ中継します。reflect-filters=_airplay._tcp.local,_raop._tcp.localのような指定で、中継するサービスを絞る設定も可能です。CiscoのCatalyst 9800 ワイヤレスコントローラーの「mDNSゲートウェイ」のように、業務用ネットワーク機器にも同等の機能があります。全サービスを無条件に中継すると、分けたはずのセグメント間で機器情報が見えてしまうため、中継するサービスの種類は絞ってください。
ファイアウォールによるUDP 5353の遮断と先に確認する設定項目
応答側の機器で受信のUDP 5353が閉じていると、問い合わせは届いても答えが返りません。Windowsで確認する対象は、Windows Defender ファイアウォールの受信規則「mDNS (UDP-In)」です。なお、IGMPスヌーピングの指針であるRFC 4541は、224.0.0.Xの範囲への(IGMP以外の)パケットを全ポートへ転送すべきとしています。スヌーピングの設定だけで224.0.0.251が止まるとは限らないため、先にファイアウォールと無線APのマルチキャスト設定を確認します。
クラウドとIoT設計:mDNSを使う場面と使わない場面の判断基準
ここまでの仕組みから、mDNSを設計に組み込むかどうかは「探す側と探される側が同じリンクにいるか」でほぼ決まります。受託開発でIoT機器や現場端末の構成を決めるときに、判断が分かれやすい2つの場面を整理します。
AWSのVPCではLANのmDNS探索をそのまま持ち込めない理由
クラウドの仮想ネットワークは、オンプレミスのLANと同じようにはマルチキャストを扱いません。AWSのTransit Gatewayのマルチキャスト解説は、VPC内のサブネット間でマルチキャストを流すにはマルチキャストを有効にしたTransit Gatewayを新しく作る必要があり、Direct Connect・Site-to-Site VPN・ピアリング接続ではマルチキャストのルーティングに対応しないと明記しています。工場や店舗のLANにある機器を、VPN越しにクラウド側からmDNSで探す構成は取れないということです。
クラウドと現場機器をつなぐ場合は、次のように役割を分けると破綻しません。
- 現場のLAN内:機器の初期設定や保守端末からの接続にmDNSを使う。利用者はIPアドレスを知らなくても「機器名.local」でつながる。
- 現場からクラウドへ:機器またはゲートウェイ側から、MQTTやHTTPSで外向きに接続を張る。クラウド側の名前は通常のDNSで解決する。
- クラウド内のサービス同士:mDNSではなく、DNSやクラウドのサービスディスカバリ機能で接続先を管理する。
現場側でmDNSとクラウド接続の両方を受け持つ中継機は、IoTゲートウェイとして設計するのが定石です。役割とプロトコル変換の考え方はIoTゲートウェイとは?プロトコル変換の役割とクラウド直結との使い分けで解説しています。
IoT機器の初期設定と現場運用でmDNSを採用する条件と見送る条件
mDNSを採用してよいのは、次の条件がそろう場合です。
- 探す側(スマートフォンや保守PC)と機器が、同じセグメントに置かれる運用である。
- 機器のIPアドレスがDHCPで変わり、利用者に毎回IPアドレスを伝える手段がない。
- 想定台数で探索時間とマルチキャスト通信量を測定し、運用要件を満たしている。名前の競合時の挙動も、採用する実装で確認している。
一方、来客用Wi-Fiと業務機器が同じセグメントにある、機器が数百台規模でセグメントをまたいで管理される、なりすましが業務停止や情報漏えいに直結する、といった場合は、mDNSの採用を見送る判断です。代わりに、IPアドレスをDHCPの予約で固定して通常のDNSに登録するか、機器から管理サーバーへ接続させる構成にします。DHCPでの固定割り当ての設計はDHCPとは?IPアドレス自動割り当ての仕組みとDORA・リース・固定IP設計を実装者向けに解説で扱っています。
機器側のファームウェア、現場ゲートウェイ、クラウドの受け口を一体で設計する案件では、mDNSをどこまで使うかが保守の手間を左右します。センサーや現場端末からクラウドまでの構成を含めて相談したい場合は、一創のAI/IoTソリューションで、通信方式の選定から機器連携の開発まで支援しています。
セキュリティ:mDNSのデメリットと、止めるべき場面・Windowsでの止め方
LAN内のリスク:認証のない応答と機器情報の公開
mDNSには認証がありません。LANにいる誰でも応答を返せるため、なりすまされる余地があります。また、機器名・機種名・提供サービスをLAN全体へ公開するので、来客用ネットワークでは情報が漏れる経路になります。RFC 6762 11節は、リンク外から届いた応答を問い合わせ側が捨てるよう求めていますが、同じLANの中にいる攻撃者は防げません。
インターネット側へのUDP 5353開放:CERT/CC VU#550620
見落とされやすいのが、ルーターやサーバーがインターネット側から届いたmDNSの問い合わせに答えてしまう状態です。CERT/CCは2015年3月31日公開のVU#550620で、リンク外からのユニキャスト問い合わせに応答するmDNS実装があり、ネットワーク機器の情報漏えいや、問い合わせより大きな応答を利用したDoS攻撃の増幅に使われうると警告しました。RFC 6762 5.5節は、ユニキャストの問い合わせの送信元が同じサブネットかを確かめ、違えば黙って捨てるよう推奨しています。ただし、これは必須(MUST)ではなく推奨(SHOULD)の扱いです。CERT/CCは、LinuxのAvahiもユニキャストの問い合わせに応答することが知られていると記しています。
対策は、CERT/CCの推奨どおり、WAN側との境界でUDP 5353の送受信を遮断することです。インターネットに直接つながるサーバーでは、セキュリティグループやファイアウォールが5353番を外部へ開けていないかを確認し、mDNSが不要ならavahi-daemonなどのサービスごと止めます。
Windowsでの止め方:ファイアウォール規則「mDNS (UDP-In)」
一方で、LAN内のmDNSは止めると壊れるものが多いのも事実です。Microsoftの「mDNS in the enterprise」は、全面的に止めると会議室のワイヤレス画面共有やプリンターへのアクセスが動かなくなる可能性があると注意しています。そのうえで、次の使い分けを勧めています。
- 全プロファイルでの受信制限:他の許可規則も確認したうえで、Windows Defender ファイアウォールの受信規則「mDNS (UDP-In)」を、パブリック・プライベート・ドメインの全プロファイルで無効にする。自宅や客先でmDNSを使う持ち出し端末には勧められていない。
- ドメインプロファイルだけの受信制限:ドメインプロファイルの「mDNS (UDP-In)」だけを無効にする。ドメインプロファイルが適用される接続で受信を制限する。適用プロファイルと他の許可規則によって効果が変わるため、社内外それぞれで確認する。Microsoftはモバイルワーカーがいる組織の推奨策としている。
判断の基準は単純です。来客用Wi-Fiや不特定多数がつながるセグメントでは、mDNSの中継をしないか、中継するサービスを絞ります。プリンターや会議室機器を使う社内セグメントでは止めず、セグメント分割で届く範囲を限るほうが、止めて業務を壊すより被害が小さく済みます。
よくある質問
mDNSとは何ですか?通常のDNSとの違いは?
DNSサーバーなしで「.local」で終わる名前をIPアドレスに解決する仕組みです。問い合わせをUDP 5353番で224.0.0.251(IPv6はFF02::FB)へマルチキャストし、名前の持ち主が応答します。仕様はRFC 6762です。通常のDNSは管理者が登録した名前をサーバーが答え、ルーターを越えて届きますが、mDNSは機器が自分で名乗り、同じリンク内にしか届きません。
mDNSのデメリットは?
認証がないため同じLANの誰でも応答でき、なりすましの余地があること、機器名や提供サービスがLAN全体に見えること、ルーターを越えないためVLANやクラウドをまたいで使えないことです。インターネット側から5353番に届く状態では、情報漏えいやDoS攻撃の増幅に悪用されるおそれもあるため、境界で遮断します。
mdns.mcast.netとは何ですか?
mDNSの宛先アドレス224.0.0.251を逆引きしたときの名前で、IANAが登録しています。ログに出ても外部との通信ではなく、LAN内のmDNS通信です。
mdns-discovery.exeは削除してもよいですか?
Arduino IDEやarduino-cliが、Wi-Fi接続のボードを探すために使うツールです。ネットワーク経由で書き込まないなら、ファイアウォールで許可しなくてもUSBでの書き込みには影響しません。Arduino IDEの構成部品なので、ファイルを消すより通信の許可・拒否で管理します。
WindowsでmDNSを無効にするには?
Windows Defender ファイアウォールの受信規則「mDNS (UDP-In)」を無効にします。全プロファイルで無効にすると当該規則による受信許可を解除できますが、他の許可規則や送信通信は別途確認が必要です。持ち出し端末ではドメインプロファイルだけを無効にする方法をMicrosoftは推奨しています。