找回密碼
 立即註冊
惟家LINE群QRCODE
    查看: 0|回覆: 0

    mDNS 跨 VLAN 怎麼過?Avahi reflector 的完整設定與取捨

    [複製鏈接]

    !lvup!   100%

    363

    主題

    27

    回帖

    2200萬

    積分

    管理員

    積分
    22005752
    發表於 3 天前 | 顯示全部樓層 |閱讀模式
    上一篇講 VLAN,這篇專門講最容易卡住的那一關:mDNS。



    先搞懂 mDNS 在幹嘛

    mDNS(Multicast DNS) 是一種「不用 DNS 伺服器也能找到彼此」的機制。

    運作方式:


    • 裝置把自己的名字註冊成 xxx.local
    • 要找某個服務的時候,往多播位址 224.0.0.251:5353 喊一聲
    • 符合的裝置直接回應


    關鍵:它用的是多播(multicast),而多播預設不會跨越路由器。

    所以 VLAN 一分開,兩邊就聽不到彼此了。

    哪些東西依賴 mDNS


    • HomeKit —— 整個配對和通訊都靠它
    • Chromecast / Google Home
    • AirPlay / AirPrint
    • ESPHome 裝置的自動發現
    • Shelly、Tasmota、WLED 等的自動發現
    • 大部分的網路印表機
    • Spotify Connect
    • HA 的很多整合的「自動發現」功能


    症狀:VLAN 設好之後,HA 的「自動發現」什麼都找不到,
    Chromecast 在手機上消失,印表機不見了。

    解法一:Avahi reflector(最常見)

    Avahi 是 Linux 上的 mDNS 實作,它的 reflector 功能會
    把一個介面收到的 mDNS 封包轉發到其他介面

    OpenWrt 設定
    1. opkg update
    2. opkg install avahi-daemon
    複製代碼

    編輯 /etc/avahi/avahi-daemon.conf
    1. [server]
    2. use-ipv4=yes
    3. use-ipv6=no
    4. # 只列出要互通的介面,不要留空(留空=所有介面)
    5. allow-interfaces=br-lan,br-iot
    6. ratelimit-interval-usec=1000000
    7. ratelimit-burst=1000
    8. [wide-area]
    9. enable-wide-area=no
    10. [publish]
    11. publish-addresses=yes
    12. publish-hinfo=no
    13. publish-workstation=no
    14. disable-publishing=no
    15. [reflector]
    16. enable-reflector=yes
    17. reflect-ipv=no
    18. # 新版 Avahi 支援只反射特定服務(見下方)
    19. # reflect-filters=_googlecast._tcp.local,_hap._tcp.local
    複製代碼

    啟用:
    1. /etc/init.d/avahi-daemon enable
    2. /etc/init.d/avahi-daemon restart
    複製代碼

    還要開防火牆

    Avahi 能轉發,但防火牆要放行 5353:
    1. # /etc/config/firewall
    2. config rule
    3.     option name 'Allow-mDNS'
    4.     option src '*'
    5.     option dest_port '5353'
    6.     option proto 'udp'
    7.     option target 'ACCEPT'
    8.     option family 'ipv4'
    複製代碼
    1. /etc/init.d/firewall restart
    複製代碼



    解法二:各平台的內建功能

    UniFi

    設定 → 網路 → 選那個網路 → 進階 → 開啟 Multicast DNS

    UniFi 的實作是每個網路各自開關,兩邊都要開才會互通。

    pfSense / OPNsense

    安裝 Avahi 套件(系統 → 套件管理員),
    然後在設定裡勾選要橋接的介面。

    MikroTik RouterOS

    原生沒有 mDNS reflector。選項:


    • 用 RouterOS 7 的 container 功能跑一個 avahi 容器
    • 或者另外放一台小機器(樹莓派)當 reflector
    • 或者放棄自動發現,全部手動指定 IP


    OpenWrt 的替代方案:mdns-repeater

    比 Avahi 輕量很多,只做一件事:
    1. opkg install mdns-repeater
    2. # 或從 GitHub 編譯
    複製代碼
    1. mdns-repeater br-lan br-iot
    複製代碼

    優點:極輕量、單一用途、不會有 Avahi 那些額外的服務發布。
    缺點:功能少,不能過濾服務類型。

    安全上的取捨(一定要理解)

    開了 reflector 之後:


    • IoT 網段看得到主網段所有廣播服務的名稱
    • 主網段也看得到 IoT 的
    • 等於洩漏了一份裝置清單


    這削弱了 VLAN 隔離的一部分效果。

    但要看清楚:reflector 只轉發「服務廣播」,不會讓實際的連線通過。
    實際連線還是被防火牆規則管著。

    所以風險是「資訊洩漏」而不是「存取權限」。
    對家用環境來說通常可以接受

    降低風險的三個做法

    1. 只反射需要的介面

    不要在 allow-interfaces 裡列出訪客網路。
    訪客不需要看到你的 Chromecast。

    2. 用服務過濾(如果你的 Avahi 版本支援)

    新版 Avahi 有 reflect-filters,只轉發特定的服務類型:
    1. [reflector]
    2. enable-reflector=yes
    3. reflect-filters=_googlecast._tcp.local,_hap._tcp.local,_esphomelib._tcp.local
    複製代碼

    常見的服務類型:


    • _googlecast._tcp — Chromecast / Google Home
    • _hap._tcp — HomeKit
    • _airplay._tcp_raop._tcp — AirPlay
    • _ipp._tcp_printer._tcp — 印表機
    • _esphomelib._tcp — ESPHome
    • _http._tcp — 很多小裝置的網頁介面


    3. 完全不開,改用手動設定

    這是最安全的做法。

    多數 HA 整合都支援手動輸入 IP,只是不會自動跳出來。
    1. 設定 → 裝置與服務 → 新增整合 → 選那個整合
    2. → 有些會問「要自動發現還是手動輸入」
    複製代碼

    配合 DHCP 保留把 IP 固定住,設定一次就不用再管。

    缺點


    • HomeKit 幾乎不能用(它的配對流程依賴 mDNS)
    • Chromecast 投放不能用
    • 新增裝置比較麻煩




    怎麼決定

    我的建議:


    • 家裡有 HomeKit / Chromecast / AirPlay → 開 reflector,用服務過濾
    • 只有 Zigbee + 少量 Wi-Fi 裝置 → 不用開,手動設定就好
    • 完全不在意那點資訊洩漏 → 直接開,最省事


    Zigbee 的隱藏優勢又出現了
    Zigbee 裝置根本不上 IP 網路,完全沒有 mDNS 的問題。
    只有網關需要連網,而網關可以手動指定。

    除錯:怎麼確認 mDNS 有沒有通

    在 HA 主機上(或任何 Linux 機器)
    1. # 掃描所有 mDNS 服務
    2. avahi-browse -a -t
    3. # 只看某一類
    4. avahi-browse -t _esphomelib._tcp
    5. # 看某個名字解析到哪個 IP
    6. avahi-resolve -n myesp.local
    複製代碼

    用 Python(HA 裡就有)
    1. python3 -c "
    2. from zeroconf import Zeroconf, ServiceBrowser
    3. import time
    4. class L:
    5.     def add_service(self,zc,t,n): print('找到:', n)
    6.     def remove_service(self,zc,t,n): pass
    7.     def update_service(self,zc,t,n): pass
    8. zc = Zeroconf()
    9. ServiceBrowser(zc, '_esphomelib._tcp.local.', L())
    10. time.sleep(5)
    11. zc.close()
    12. "
    複製代碼

    直接抓封包
    1. tcpdump -i any -n port 5353
    複製代碼

    在路由器上跑這個,你會看到 mDNS 的查詢和回應。
    有轉發成功的話,會看到同樣的封包出現在兩個介面上。

    常見的失敗原因


    • 防火牆擋 5353 —— 最常見,Avahi 設定對了但封包過不去
    • allow-interfaces 寫錯介面名 —— 用 ip link 確認實際名稱
    • IGMP snooping —— 交換器上的這個功能可能擋掉多播,試著關掉
    • AP 的 client isolation 開著 —— 同一個 SSID 內的裝置也看不到彼此
    • IPv6 —— 有些裝置用 IPv6 的 mDNS,記得設 use-ipv6 或直接關掉裝置的 IPv6


    ---

    我自己的設定是開 reflector 但用服務過濾
    只放行 Chromecast、ESPHome、印表機三類。

    其他的全部手動指定 IP,反正設定一次而已。
    您需要登入後纔可以回帖 登入 | 立即註冊

    本版積分規則

    Archiver|手機版|惟家的智能論壇

    GMT+8, 2026-9-24 11:20 , Processed in 0.079350 second(s), 25 queries .

    快速回覆 返回頂部 返回列表