LinuxでAvahi DaemonをmDNSリフレクターとして設定する:VLAN間でのAirPlay、Chromecast、プリンターの検出

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

日曜日の午前2時15分。ネットワークチームがオフィスのLANセグメンテーション作業を完了し、45台のIoTデバイス、12台のネットワークプリンター、8台の会議室用テレビを分離されたサブネットへ移行した直後のことです。10分後、アラートキューがパンク状態に陥ります。役員がChromecastディスプレイにスライドをキャストできず、スタッフはHPプリンターを検出できなくなり、すべてのMacBookでApple AirPlayの画面ミラーリング機能が見失われてしまいました。

その原因は何でしょうか?正解はMulticast DNS (mDNS) です。mDNSはUDPポート5353を使用し、リンクローカルマルチキャストアドレス 224.0.0.251 (IPv4) または ff02::fb (IPv6) を介して、Time-to-Live (TTL) 値 1 で動作します。仕様上、L3ルーターはサブネットの境界でこれらのパケットを破棄します。そのため、フラットなネットワークをVLANに分割すると、ゼロ構成(Zero-configuration)による機器検出が即座に動作しなくなってしまうのです。

セキュリティ境界を取り払って元のフラットな構成に戻す代わりに、マルチホーム構成のLinuxルーターやゲートウェイ、または軽量なProxmox LXCコンテナ上でAvahi daemonをmDNSリフレクター(Reflector)として実行する方法があります。

クイックスタート (5分)

現在まさに障害対応中である場合は、トランク接続されたVLANインターフェースを持つDebianおよびUbuntuホスト向けの緊急デプロイ手順を以下に示します。

1. AvahiとmDNSユーティリティのインストール

sudo apt update && sudo apt install -y avahi-daemon avahi-utils

2. リフレクター機能の有効化

メイン設定ファイルを開きます:

sudo nano /etc/avahi/avahi-daemon.conf

[reflector] ブロック配下で enable-reflector=yes を設定し、ホストのリソース制限を設定します:

[server]
host-name=mdns-gateway
use-ipv4=yes
use-ipv6=yes
check-response-ttl=no

[reflector]
enable-reflector=yes

[rlimits]
rlimit-core=0
rlimit-data=4194304
rlimit-fsize=0
rlimit-nofile=768
rlimit-stack=4194304
rlimit-nproc=3

3. デーモンの再起動と動作確認

sudo systemctl restart avahi-daemon
sudo systemctl status avahi-daemon

すべてのインターフェースでアクティブなサービスアドバタイズを照会します:

# ネットワーク上で検出されたすべてのサービスを参照
avahi-browse -a -t -r

# またはGoogle CastおよびAirPlayを個別にフィルタリング
avahi-browse -t _googlecast._tcp
avahi-browse -t _airplay._tcp

これで、異なるVLANインターフェース上のデバイスが3〜5秒以内にサービス一覧に表示されるようになります。

詳細解説

Avahiがマルチキャストドメインをどのようにブリッジしているかを理解することで、ブロードキャストストーム、高いCPU負荷、非対称ルーティングの障害を防ぐことができます。

サブネット境界を越えたmDNSの仕組み

Apple Bonjour、Google Cast、そして最新のネットワークプリンターは、DNS Service Discovery (DNS-SD) を介してサービスレコードをブロードキャストします。mDNSパケットは TTL=1 を保持しているため、標準的なルーターはそれらを通知なく破棄(ドロップ)します。

リフレクションがアクティブな場合、Avahiはアプリケーション層のプロキシとして機能します:

  1. Avahiは設定されたすべてのネットワークインターフェースにわたりマルチキャストグループ 224.0.0.251:5353 に参加します。
  2. VLAN 10 (192.168.10.45) 上のノートPCが _googlecast._tcp.local に対するmDNSクエリをブロードキャストします。
  3. Avahiはインターフェース eth0.10 でこのパケットをキャプチャします。
  4. デーモンはリンクローカルヘッダーを書き換え、eth0.20 (IoT VLAN) および eth0.30 (プリンターVLAN) からクエリを再送信します。
  5. VLAN 20 (192.168.20.110) 上のChromecast Ultraがリフレクトされたクエリを受信し、自身のIPとポートを含むmDNSレスポンスを送信します。
  6. Avahiは eth0.20 でレスポンスをキャプチャして eth0.10 に送り返し、サービス検出が完了します。

ホストファイアウォールルール (iptablesおよびnftables)

Linuxゲートウェイでローカルファイアウォールが動作している場合、受信したUDP 5353トラフィックはAvahiが処理する前に破棄されてしまいます。

# IPv4およびIPv6のマルチキャストDNS用iptablesルール
sudo iptables -A INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 5353 -s 192.168.0.0/16 -j ACCEPT
sudo ip6tables -A INPUT -p udp --dport 5353 -d ff02::fb -j ACCEPT

UFWで管理されているシステムの場合:

sudo ufw allow in proto udp to 224.0.0.251 port 5353
sudo ufw allow in proto udp to any port 5353 comment 'mDNS unicast replies'

高度な設定

デフォルトのリフレクター設定では、すべてのブロードキャストがすべてのインターフェースに向けて中継されます。企業環境では、これがセキュリティリスクを生み出したり、帯域幅の狭いWi-Fiチャネルを圧迫したりする原因になります。

1. インターフェースの制限

Avahiはデフォルトで、パブリックWANインターフェースやWireGuardトンネルを含むすべてのアクティブなNICにバインドします。/etc/avahi/avahi-daemon.conf 内でリフレクションの対象を内部VLANのみに制限します:

[server]
# ワークステーション (10)、IoT (20)、プリンター (30) のみにバインド
allow-interfaces=eth0.10,eth0.20,eth0.30
deny-interfaces=eth0,wg0,tun0

2. ユニキャストルーティング(検出後に潜む落とし穴)

検出は単なるハンドシェイクにすぎません。iPhoneがスマートテレビを検出すると、メディアをストリーミングするために直接ユニキャストTCP/UDPソケットを開きます。ルーターがVLAN間のパケット転送をブロックしている場合、画面上では検出に成功しても、ストリーミングを開始した瞬間にタイムアウトしてしまいます。

VLAN間ファイアウォールで実際のペイロードストリームが許可されていることを確認してください:

  • AirPlay / Apple TV: TCP 7000 (制御/ミラーリング)、TCP 7100、TCP 5000 (音声)、および UDP 6000–6009 (RTPストリーム)。
  • Google Cast: TCP 8008 (HTTP制御)、TCP 8009 (HTTPS制御)、TCP 8443、および UDP 1900 (SSDPフォールバック)。
  • IPP & Raw印刷: TCP 631 (IPP/IPPS) および TCP 9100 (RAW JetDirect)。
# ワークステーションVLAN (192.168.10.0/24) からIoTデバイス (192.168.20.0/24) へのストリーミングを許可
sudo iptables -A FORWARD -s 192.168.10.0/24 -d 192.168.20.0/24 -p tcp -m multiport --dports 5000,7000,7100,8008,8009,8443 -j ACCEPT
sudo iptables -A FORWARD -s 192.168.10.0/24 -d 192.168.20.0/24 -p udp --dport 6000:6009 -j ACCEPT
sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

実践的なトラブルシューティング

tcpdumpを使用したパケット欠落の診断

デバイスが表示されない場合は、マルチキャストパケットがゲートウェイに到達しているかを確認します:

# すべてのインターフェースでリアルタイムのmDNSクエリを監視
sudo tcpdump -n -i any port 5353 -vv

eth0.10 にクエリパケットが到着し、数ミリ秒以内に対象の送信パケットが eth0.20 に現れることを確認してください。

ブロードキャストストームとリフレクションループの回避

  • 同一のVLANペア上で2つのリフレクターを絶対に実行しないこと: 2台のゲートウェイが同じサブネットを enable-reflector=yes でブリッジしている場合、クエリが無限ループで跳ね返り続けます。これによりCPU使用率が100%に張り付き、マネージドスイッチがクラッシュします。
  • スイッチのIGMPスヌーピングを確認: マネージドL2スイッチは、VLAN上でアクティブなIGMPクエリアが存在しない場合、マルチキャストフレームをドロップします。コアスイッチで各VLANに対してアクティブなIGMPクエリアが有効になっていることを確認してください。
  • ローカルサービスの公開を無効化: ゲートウェイホスト自体がプリンターやファイル共有を提供していない場合は、[publish] 配下に disable-publishing=yes を追加してメモリを節約し、バックグラウンドトラフィックを削減します。
Share: