当前位置: 首页 > 知识库问答 >
问题:

有办法在你的网络上发现Android设备吗?

邢灿
2023-03-14

我希望能够在我的网络上发现Android设备,并可能检索一些关于它们的设备信息。这对于苹果设备来说非常容易,因为它们运行Bonjour服务。然而,我似乎找不到任何类似的服务运行在Android上。

这必须在不修改Android设备,安装某些服务或打开某些端口的情况下工作。它旨在与vanilla Android设备配合使用,就像Bonjour帮助您找到vanilla Apple设备一样。即使能够验证设备是否运行Android也足够了。

选择的答案:虽然它不是最高评级的答案(还没有),请看看路易斯的回应。正如他提到的,你可以使用DNS查询(使用你的本地DNS服务器)来发现Android设备。我发现这有100%的成功率,因为Android强制设备使用android-____的主机名。这显然很难在手机上改变,即使是根深蒂固的。所以我认为这是一个非常准确的方法。谢谢,路易斯!

Example:
$ nslookup 192.168.1.104 192.168.1.1
Server:     192.168.1.1
Address:    192.168.1.1#53

104.1.168.192.in-addr.arpa  name = android-711c129e251f14cf.\001.

示例代码:如果您想在Java中实现它(例如,在Android上运行),您不能轻松使用getHostName(),因为它使用外部DNS服务器。例如,您想在路由器上使用本地DNS服务器。Luis在下面提到,您可以修改Wifi连接的DNS服务器,但这可能会破坏其他东西。相反,我发现dnsjava库对发送目标DNS请求非常有用。以下是一些使用该库的示例代码:

        String ipAddress = "104.1.168.192";
        String dnsblDomain = "in-addr.arpa";
        Record[] records;
        Lookup lookup = new Lookup(ipAddress + "." + dnsblDomain, Type.PTR);
        SimpleResolver resolver = new SimpleResolver();
        resolver.setAddress(InetAddress.getByName("192.168.1.1"));
        lookup.setResolver(resolver);
        records = lookup.run();

        if(lookup.getResult() == Lookup.SUCCESSFUL) {
              for (int i = 0; i < records.length; i++) {
                if(records[i] instanceof PTRRecord) {
                  PTRRecord ptr = (PTRRecord) records[i];
                  System.out.println("DNS Record: " + records[0].rdataToString());
                }
              }
        } else {
            System.out.println("Failed lookup");
        }

    } catch(Exception e) { 
        System.out.println("Exception: " + e);
    }

这给了我输出:

DNS Record: android-711c129e251f14cf.\001.

答对 了

共有3个答案

全宪
2023-03-14

AFAIK,Android系统在其内置的系统应用程序/服务堆栈上不提供任何zeroconf应用程序/服务器。要在连接到本地网络的实际设备上启用自动发现,您需要安装一些第三方zeroconf应用程序,或者开发自己的应用程序/服务并将其安装在实际设备上,一些API选项包括:

  • JmDNS(用于 Apple 的 bonjour 协议)
  • Cling(用于微软的UPnP协议
  • Android NSD API(自 Android 4.1 起推出)

我不太清楚您的要求,如果您想要在普通Android设备上实现类似的功能(即自动发现和连接),您可能可以使用Wi-Fi direct,该功能现在在运行Android 4.0的一些更高版本的设备上可用,但是,它要求两个设备都支持Wi-Fi Direct,并且只能在Wi-Fi关闭的情况下创建点对点P2P连接,很像范围更长的蓝牙连接:

有关Wi-Fi Direct API支持,请查看官方指南-无线连接设备。

袁赞
2023-03-14

Android不会像iOS那么简单。没有与之相当的“你好”。

Android 4.0,Ice Cream Sandwich,引入了Wi-Fi Direct Peer to Peer Networking。起初,我希望它能够以您的想法进行扫描,但它可以帮助Android设备在没有接入点的情况下进行通信,因此它们实际上并不“在您的网络上”。此外,ICS只能在一小部分Android设备上运行。

与主动的netscan方法不同,您只能使用被动的监视方法。如果您的网络是安全的,嗅探加密数据包是可能的,但不方便。你必须

  • 将您的网络接口置于监控模式
  • 捕捉4向握手
  • 使用网络的预共享密钥解密它
  • 这将为您提供解密流量所需的密钥

如果你想看到它的实际效果,Wireshark支持WPA解密。

一旦您能够查看Wi-Fi流量,您会注意到Android设备倾向于与某些Google服务器进行通信,并且它们的HTTP连接具有可以识别的用户代理字符串。这是可行的被动解决方案的基础。

Table Network Security提供的产品似乎采用了这种类型的方法。

@Michelle Cannon提到了Libelium的Meshlium Xtreme,它的方法不会让你一路到达目的地(除非有最新的MAC地址范围表)。但这可能是达成一个较小目标的一部分。您可以:

    < li >检测所有无线设备 < li >使用MAC的组织唯一标识符(OUI)消除Apple设备 < li >通过监控信号强度来判断移动设备(移动设备往往会出现和消失) < li >您也许可以使用MAC OUI作为它是Android的提示 < li >您可以使用MAC OUI作为提示,它不是Android(而是笔记本电脑或无线网卡等)。).

如果您愿意检测可能是Android的设备,这可能是可行的。

@Michelle Cannon建议使用DHCP指纹识别。起初我不确定,但我必须感谢他提出了简单被动扫描的最佳选择。作为一个警告,我想解释一下为什么我迟到了。

在很多方面,Android使用Linux内核是好的。但是如果你想在网络上发现Android设备,那就不好了。Android的TCP/IP堆栈是Linux的,因此Android设备看起来像Linux设备,我一开始是这么想的。但是后来我意识到Linux有很多构建配置参数,所以在网络上看到Android可能会有一些与众不同的地方,但是什么呢?

DHCP指纹识别使用设备请求的确切DHCP选项加上时间。要做到这一点,您通常需要一个最新的指纹数据库来匹配。起初看起来指纹银行被大量采购这些数据,但后来我注意到他们的文件已经快一年没有更新了。对于所有不同的Android设备类型,我认为为一个项目保留更新的指纹是不实际的。

但后来我查看了Android的实际DHCP签名,我注意到了这一点:

Android 1.0:     dhcpvendorcode=dhcpcd 4.0.0-beta9
Android 1.5-2.1: dhcpvendorcode=dhcpcd 4.0.1
Android 2.2:     dhcpvendorcode=dhcpcd 4.0.15
Android 3.0:     dhcpvendorcode=dhcpcd-5.2.10 

Linux通常使用dhclient作为其DHCP客户端,但Android使用dhcpcd。Android强烈倾向于尽可能使用BSD风格许可的软件,dhcpcd使用BSD许可。dhcpvendorcode似乎可以作为移动设备运行Android的有力指标。

客户端在加入网络时使用DHCP获取IP地址,因此它开始时没有IP地址。它通过在初始交换中使用UDP广播来解决这个问题。在Wi-Fi上,即使使用WPA,广播流量也不会加密。因此,您只需在UDP端口67上侦听客户端到服务器的流量,而在端口68上侦听相反的流量。您甚至不需要将网络接口设置为混杂模式。您可以使用Wireshark之类的协议分析器轻松监控此流量。

我更喜欢编写代码来监控流量,并决定使用Python。我选择pydhcplib来处理DHCP的细节。我在这个图书馆的经历并不顺利。我需要手动下载并放置IN.py和TYPES.py支持文件。他们的数据包到字符串的转换将dhcpvendorcode留空。它确实正确地解析了DHCP数据包,所以我只编写了自己的打印代码。

下面是监控从客户端到服务器的DHCP流量的代码:

#!/usr/bin/python
from pydhcplib.dhcp_packet import *
from pydhcplib.dhcp_network import *
from pydhcplib.dhcp_constants import *


netopt = {
    'client_listen_port':"68",
    'server_listen_port':"67",
    'listen_address':"0.0.0.0"
}

class Server(DhcpServer):
    def __init__(self, options):
        DhcpServer.__init__(
            self,options["listen_address"],
            options["client_listen_port"],
            options["server_listen_port"])

    def PrintOptions(self, packet, options=['vendor_class', 'host_name', 'chaddr']):

        # uncomment next line to print full details
        # print packet.str()

        for option in options:
            # chaddr is not really and option, it's in the fixed header
            if option == 'chaddr':
                begin = DhcpFields[option][0]
                end = begin+6
                opdata = packet.packet_data[begin:end]
                hex = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
                print option+':', ':'.join([(hex[i/16]+hex[i%16]) for i in opdata])
            else:
                opdata = packet.options_data.get(option)
                if opdata:
                    print option+':', ''.join([chr(i) for i in opdata if i != 0])
        print

    def HandleDhcpDiscover(self, packet):
        print "DHCP DISCOVER"
        self.PrintOptions(packet)
    def HandleDhcpRequest(self, packet):
        print "DHCP REQUEST"
        self.PrintOptions(packet)

    ##  def HandleDhcpDecline(self, packet):
    ##      self.PrintOptions(packet)
    ##  def HandleDhcpRelease(self, packet):
    ##      self.PrintOptions(packet)
    ##  def HandleDhcpInform(self, packet):
    ##      self.PrintOptions(packet)


server = Server(netopt)

while True :
    server.GetNextDhcpPacket()

这段代码基于pydhcplib的服务器示例,因为它像服务器一样监听客户端请求。

当我的Nexus 7 Android 4.2平板电脑连接时,会捕获(编辑)此有趣的信息:

DHCP REQUEST
vendor_class: dhcpcd-5.5.6
host_name: android-5c1b97cdffffffff
chaddr: 10:bf:48:ff:ff:ff

DHCP DISCOVER
vendor_class: dhcpcd-5.5.6
host_name: android-5c1b97cdffffffff
chaddr: 10:bf:48:ff:ff:ff

主机名似乎有固定的格式,很容易解析。如果您需要IP地址,您可以监控服务器到客户端的流量。注意:当一个没有IP地址的新客户机第一次出现时,只有初始交换会被广播。未来租赁延期等。,都没有播出。

@Luis发布了一个很棒的解决方案,展示了简单越好。即使看到Android的DHCP客户端将host_name设置为android-5c1b97cdffffff,我也没有想到使用反向DNS查找向路由器询问其名称列表。路由器将host_name添加到其DNS服务器,因此如果其IP地址发生变化,您仍然可以访问设备。

在DHCP租约期间,host_name预计将保留在DNS中。您可以通过ping来检查设备是否仍然存在。

依赖于host_name的一个缺点是,有多种方法可以改变这一点。设备制造商或运营商很容易更改host_name(尽管在搜索之后,我无法找到他们曾经拥有的任何证据)。有一些应用程序可以更改主机名,但它们需要root,所以这最多是一种边缘情况。

最后,还有一个开放的 Android 问题 6111:允许指定当前具有 629 颗星的主机名。在未来的某个时候,也许很快就会在Android设置中看到可配置的host_name,这并不奇怪。因此,如果您开始依靠host_name来识别Android设备,请意识到它可以从您身下被拉出。

如果您正在进行实时跟踪,反向DNS查找的另一个潜在问题是您必须决定扫描的频率。(当然,如果您只是拍摄一次性快照,这不是一个问题。)频繁扫描会消耗网络资源,而不频繁扫描会导致数据过时。以下是添加DHCP监控的帮助方式:

  • 启动时使用反向 DNS 查找查找设备
  • Ping 设备以查看它们是否仍处于活动状态
  • 监控 DHCP 流量以立即检测新设备
  • 偶尔重新运行 DNS 查找以查找您可能错过的设备
  • 如果您需要注意到设备离开,请以所需的时序分辨率ping设备

虽然这并不容易(也不是100%准确),但有几种技术可以在您的网络上发现Android设备。

夏飞跃
2023-03-14

有一种非常简单的方法,在一些不同的设备上给我带来了积极的结果。

当设备连接到您的路由器时,它接收IP(即DHCP)并在DNS中注册名称。注册的名称似乎总是采用<code>android_ nnnnnnnn</code>的形式。

当然,你可以用同样的方法命名任何一台计算机,欺骗检查,导致误报...

此外,我无法确保所有设备供应商都遵循相同的方法,但我发现它在我测试过的不同品牌(包括不同SDK级别)的一些设备中都能正常工作。

--编辑--

怎么做

这取决于您将在哪里运行代码来发现Android设备。假设您将在Android设备上运行代码:

>

  • 首先发现您网络中响应ping的设备。您可以使用我对这篇文章的回答中的代码:execComd()来运行ping命令。

    使用以下html" target="_blank">代码获取响应设备的名称:

    InetAddress:inetAddresse=inetAddresss.getByName(string_with_ip_addr);

    字符串名称=inetAddress.getCanonicalHostName();

    --编辑 2--

    概念证明

    下面的方法只是我上面写的概念的证明。

    我正在使用isReachable()方法来生成ICMP请求,据说在许多帖子中,它仅适用于root设备,用于测试它的设备就是这种情况。但是,我没有为运行此代码的应用程序授予root权限,因此我认为它无法设置SIUD位,这就是某些人声称此方法失败的原因。我想从在无根设备上测试它的人的角度来做。

    要呼叫使用:

    ArrayList<String> hosts = scanSubNet("192.168.1.");
    

    它在<code>主机

    private ArrayList<String> scanSubNet(String subnet){
        ArrayList<String> hosts = new ArrayList<String>();
        
        InetAddress inetAddress = null;
        for(int i=1; i<10; i++){
            Log.d(TAG, "Trying: " + subnet + String.valueOf(i));
            try {
                inetAddress = InetAddress.getByName(subnet + String.valueOf(i));
                if(inetAddress.isReachable(1000)){
                    hosts.add(inetAddress.getHostName());
                    Log.d(TAG, inetAddress.getHostName());
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        return hosts;
    }
    

    当做

  •  类似资料:
    • 最近,我们在Android应用程序中增加了对Chromecast的支持,但在对各种移动设备(手机和平板电脑)的扩展测试中,发现在许多移动设备上,Flipps应用程序都没有发现Chromecast。在相同的设备上,我们使用了最新版本的官方Chromecast SDK演示应用程序进行测试,该应用程序从https://github.com/googlecast/castvideo-Android下载(主

    • 所以我在玩Expo+React Native+yoga graphql server+Apollo Client,通过查询获取数据在浏览器中工作,当我从Expo点击“在浏览器中运行”时,但如果我试图在android模拟器/QR code上从真实的手机上运行该应用程序,它会引发网络错误。附言。我在github上阅读了类似的帖子和问题,所以我设法使graphqlendpoint可以通过nat和No-I

    • 尝试使用pybonjour,但不确定它是否是我需要的。https://code.google.com/p/pybonjour/ 我希望能够自动发现出现在我的网络上的iOS设备,稍后将基于此运行一个脚本,但首先我想在它出现/消失在我的wifi网络上时立即发现iOS设备。 所以问题是,我该怎么做?在安装了python27和pybonjour包的windows机器上运行,这两个示例在pybonjour页

    • 我希望能够发现附近的任何类型的设备(10 m),并可能检索到除了MAC地址之外的一些设备信息。这应该通过WIFI发现。 这些设备不需要在同一个网络中(因为大多数问题要求类似的行为),它们可以只是在这个“antena”旁边通过。 设备不断与附近的接入点通信,因此我认为应用程序也能够捕捉这些广播。 我试图使用Android Nsd(网络服务发现),直到我发现这仅适用于同一网络中的设备。我刚刚开始研究

    • 那么有没有办法将flutter应用从windows机器运行到真正的ios设备呢? 我找了找,但找不到答案。我唯一发现的东西是2019年的,我认为这是一个很长的时间,也许开发了一个工具。

    • 我试图发现我的设备连接到的WiFi网络上的所有设备。这是普通的Java,不是Android。我需要搜索每个设备,看看它是否有一个特定的端口打开。我将通过连接到我发现的第一个符合此条件的设备,所以我需要它的IP地址。我基本上是在尝试编写以下代码: