簡體   English   中英

如何檢測本地網絡中的特定設備?

[英]How to detect specific devices in a local network?

我正在構建一個 IoT 解決方案,我將多個設備連接到我的本地網絡,我想將這些設備連接到控制我的解決方案的集線器。

連接新設備后,我想將其與集線器連接並為其命名以進行識別。 我想以自動方式實現檢測(因此我不必手動輸入 IP 地址)。 例如,當網絡中存在 Chromecast 時,我可以在手機的流媒體應用程序中看到它。 所以我想做一些類似的事情來將集線器與設備連接起來。

到目前為止,我的想法是有兩種方法可以做到這一點:

  1. 集線器掃描網絡以查找新設備(定期或當我說有新設備存在時)。
  2. 一旦連接,設備就會掃描網絡以找到集線器。

這些方法中的任何一種是否比另一種更受歡迎,在這種情況下為什么?

進行掃描時,無論選擇哪個方向,最有效的掃描方式是什么? 我正在使用 Java 進行實現,到目前為止我所擁有的是:

int timeout = 100;
for (int i = 1; i < 255; i++)
{
    String host = subnet + "." + i;

    if (InetAddress.getByName(host).isReachable(timeout))
    {
        String hostname = InetAddress.getByName(host).getHostName();
        String canonicalHostName = InetAddress.getByName(host).getCanonicalHostName();
        System.out.println(host + " is reachable. Hostname: " + hostname + ", CanonicalHostName: " + canonicalHostName);
    }
}

我在這里看到的是,對於我網絡中的大多數內容,返回的主機名只是 IP 地址,而不是我在路由器中看到的主機名。 我想我可以使用主機名作為識別器來檢測特定設備並了解它們的位置 - 但是這個小 poc 似乎不起作用。 那么如何才能很好地識別設備呢?

是否有任何適用於 Java(或 Javascript)和 ESP8266 的庫/解決方案可以做到這一點? (如果實施“智能家居”設備,感覺就像一個常見問題)。

我們沒有單一的方法來發現局域網上的設備。

設備通常不是掃描網絡,而是使用多播或廣播協議來宣布它們的存在,或者它們會聚在(通常是外部)預先配置的服務器上。

一些設備使用mDNS - 松散地基於 DNS 協議,它們多播數據包以宣傳它們在網絡上的存在。 Apple 在其產品中使用 mDNS。 它在 Android 上的支持很差,並且在 Windows 上需要額外的軟件。 mDNS 名稱通常位於.local域中。

一些設備使用UPNPSSDP - Belkin 的 Wemo 系列產品就是這樣做的。 UPNP 和 SSDP 是基於 XML 和SOAP 的過於復雜的協議,對於 RAM 和處理能力有限的設備(如 ESP8266 和 ESP32)來說,它們是糟糕的選擇。

有些設備只是推出自己的協議。 Haiku 的“Big Ass Fan”系列就是這樣做的——他們使用一種自產協議廣播 UDP 數據包,該協議至少在最初容易受到各種問題的影響。 我不建議走這條路,除非你真的知道你在做什么。 其他已建立的協議已經有機會消除錯誤。 除非你在協議設計方面有經驗,否則你更有可能重新發明其他協議所存在的問題,而不是一個美妙的閃亮的新可發現性協議。

這些類型的設備將定期廣播或多播一個數據包來宣布自己,或者你稱之為“集線器”的東西會廣播或多播一個請求,設備會響應該請求。

並非所有設備都提供直接控制它們所連接的 LAN 的接口。 有些只是與遠程服務器會合。 在這種情況下,您可以通過要求服務器枚舉它們來發現它們,並通過該服務器控制它們。 Google 的 Nest 產品就是這樣工作的——初始配置是通過藍牙完成的; 之后,應用程序通過遠程服務器與設備進行通信。

以這種方式集合的設備通常預先配置有集合服務器的名稱,但它們也可能在網絡配置期間使用服務器名稱進行配置(通常應用與它們通信以共享 wifi 憑據;它也可能共享有關會合服務器也是如此)。

我們通常不會掃描 IP 地址塊中的名稱或主動探測新設備,除非我們正在調試網絡或進行某種安全掃描。

您描述的掃描 IP 地址塊的過程存在問題且不可靠。 它工作的唯一原因是某些路由器從設備的 DHCP 請求中獲取設備的名稱(或者路由器可能被配置為知道設備的名稱)。 路由器還為網絡上的設備處理 DNS,通常是將它們轉發到 ISP 的 DNS 服務器或網絡所有者配置為使用的 DNS 服務器。 它攔截其知道名稱的設備的 DNS 請求並自行回復,而不是將它們轉發到外部 DNS 服務器。

您還必須了解網絡配置才能正確執行此操作。 網絡只有/24嗎? 如果是 /22 呢? 或/16? 如果網絡配置為 /8,您准備好掃描 2^24 個 IP 地址了嗎?

盡管路由器可能會攔截對名稱和返回地址的請求,但它不一定會攔截地址和返回名稱的名稱。

掃描還會產生不必要的網絡流量。 雖然您的一個“中心”掃描可能看起來不多,但如果您有來自不同制造商的多台掃描儀在運行,它就不能很好地擴展。

如果您的“集線器”繞過路由器進行 DNS 請求,那么它也將無法解析路由器提供的名稱。

也並非所有路由器都這樣做。 它不是 Internet 架構的一部分,而是某些路由器提供的便利功能。 你不能依賴它工作。

您還可以嘗試主動掃描網絡,嘗試與其上的每個 IP 地址進行通信。 我們這樣做是為了網絡調試,但不斷運行它來檢測新設備將是一種與網絡交互的敵對方式。

網絡基礎設施設備——交換機和路由器——當然維護網絡上所有活動設備的列表。 您可以使用SNMP (簡單網絡管理協議)訪問這些列表,但很少有消費者交換機和路由器支持 SNMP。 允許隨機軟件訪問您的網絡基礎設施是網絡安全的噩夢。

最好的選擇是像 mDNS 這樣的簡單多播/廣播協議。 不要掃描、宣布或請求。 它反應靈敏,不會給網絡帶來負擔,不依賴路由器的特性,不會讓網絡管理員討厭你。

很久以前,我實施了一個類似的解決方案來發現連接到網絡的客戶端。 我的策略包括利用 DHCP 配置。

如果您的設備必須向您控制的 Linux/Unix DHCP 服務器詢問 IP 地址,您可以將其配置為讓您知道設備何時連接或斷開網絡。

我們使用的是 Linux DHCP 服務器,在dhcpd.conf 中有一個關於事件的部分。 基本上它說,當 DHCP 為客戶端提交特定的 IP 地址租約時,它會引發一個事件,當發生這種情況時,它可以運行您可以為該事件定義的偵聽器。 在偵聽器中,我們可以要求 DHCP 執行命令,例如將客戶端信息(例如 MAC 地址)及其 IP 地址租用寫入命名管道,並且您的 Java 應用程序可能只是從這個隊列中讀取。 (另請參閱dhcp-eval了解更多詳情)。 當客戶端釋放 IP 租用或租用到期時,可以運行類似的事件。

這是一個例子

subnet 192.168.1.0 netmask 255.255.255.0 {
    option routers  192.168.1.2;

    on commit {
        set clip = binary-to-ascii(10, 8, ".", leased-address);
        set clhw = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6));
        execute("/usr/local/sbin/dhcpevent", "commit", clip, clhw, host-decl-name);
    }
    ...

如果你可以控制你的 DHCP 配置,那么你可以從中提取很多東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM