任何方式来发现您的networking上的Android设备?

我想能够发现我的networking上的Android设备,并可能检索有关它们的一些设备信息。 自从他们运行Bonjour服务以来,Apple设备非常简单。 但是,我似乎无法find任何类似的服务在Android上运行。

这必须在不修改Android设备,安装某些服务或打开某个端口的情况下工作。 它意味着以Bonjour帮助您find香草苹果设备的方式与香草Android设备一起工作。 即使能够validation设备运行Android也足够了。


已选答案 :虽然还不是最高评分的答案,但请看看Luis的回复。 正如他所提到的,您可以使用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服务器。 路易斯在下面提到,你可以修改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. 

答对了。

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

当设备连接到路由器时,它会收到一个IP(即DHCP)并在DNS中注册一个名称。 注册的名称似乎总是以android_nnnnnnnn的forms。

你可以使用相同的方法命名任何计算机并欺骗检查,从而导致误报…

另外,我不能确保所有的设备供应商都遵循相同的方法,但我发现它可以在我testing过的来自不同品牌(包括不同SDK级别)的less数设备上正常工作。

–EDITED–

怎么做

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

  1. 首先发现设备响应您的networking中的Ping 。 你可以在我的回复中使用下面的代码: execComd()运行一个ping命令。
  2. 使用代码获取响应设备的名称:

    InetAddress inetAddress = InetAddress.getByName(string_with_ip_addr);

    String name = inetAddress.getCanonicalHostName();

– EDIT 2–

概念validation

下面的方法只是我上面写的概念的一个教授。

我正在使用isReachable()方法来生成ICMP请求,这在很多只能用于根设备的post中说过,这是用于testing的设备的情况。 但是,我没有给运行这个代码的应用程序的root权限,所以我相信它不能设置SIUD位,这就是为什么一些clain这个方法失败了。 我想在这里从一个非rooted设备上testing它的人。

致电使用:

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

它在hosts返回响应ping请求的设备的名称列表。

 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不会像iOS那么简单。 没有Bonjour等价物。

Android 4.0,Ice Cream Sandwich,推出了Wi-Fi直连点对点networking。 起初我希望能够按照您的想法进行扫描,但是它可以帮助Android设备在没有接入点的情况下进行通信,因此它们并不真正“在您的networking上”。 此外,ICS仅在Android设备的一小部分上运行。

而不是一个积极的networking扫描方法,你留下了一个被动的监测方法。 如果您的networking安全,嗅探encryption的数据包是可能的,但不方便。 你必须

  • 将您的networking接口置于监视模式
  • 捕获4路握手
  • 使用networking的预共享密钥对其进行解密
  • 这将为您提供解密stream量所需的密钥

如果你想看到这个动作, Wireshark支持WPA解密 。

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

Tenable Network Security提供的产品似乎采取了这种方式。

另一个想法

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

  • 检测所有无线设备
  • 使用MAC的组织唯一标识符(OUI)消除Apple设备
  • 通过监测信号强度来判断移动设备是否正在移动(而移动设备将倾向于出现并消失)
  • 您可以使用MAC OUI作为Android的提示
  • 您可能能够使用MAC OUI作为不是Android的提示(但是是笔记本电脑或无线网卡等)。

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

DHCP指纹识别

@Michelle Cannonbuild议DHCP指纹识别。 起初我并不确定,但是我要感谢他提出了简单被动扫描的最佳select。 作为一条警戒线,我想解释为什么我迟到了晚会。

有些事情我们知道,认为我们不知道,我们认为我们知道但是错误的事情。

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

DHCP指纹使用设备请求的确切的DHCP选项加上时间。 为了这个工作你通常需要一个最新的指纹数据库来匹配。 起初,看起来像是fingerbank被大量采购这些数据,但后来我注意到他们的文件已经有近一年没有更新。 对于所有不同的Android设备types,我不认为为单个项目保留更新的指纹是可行的。

但后来我看了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监控

客户端在joinnetworking时使用DHCP来获取IP地址,因此它在没有IP地址的情况下启动。 它通过使用UDP广播进行初始交换来解决这个问题。 在Wi-Fi上,即使使用WPA,广播stream量也不会被encryption。 所以你可以只监听UDP端口67的客户端到服务器的stream量,反之则是68。 你甚至不需要把你的networking接口变成混杂模式。 您可以使用像Wireshark这样的协议分析器轻松地监控这个stream量。

我更喜欢编写代码来监视stream量,并决定使用Python。 我select了pydhcplib来处理DHCP的细节。 我对这个图书馆的经历并不顺利。 我需要手动下载并放置IN.py和TYPES.py支持文件。 他们的数据包到string转换是离开dhcpvendorcode空白。 它parsing了正确的DHCP数据包,所以我只写了自己的打印代码。

这是监视从客户端到服务器的DHCPstream量的代码:

 #!/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 

主机名似乎有一个固定的格式,很容易parsing。 如果您需要IP地址,您可以监视服务器到客户端的stream量。 注意:只有最初的交换,当一个新的客户首先出现没有IP地址,被广播。 未来的租约延期等不会被广播。

反向DNS查找

@Luis发布了一个很好的解决scheme,演示了如何更简单。 即使在看到Android的DHCP客户端将host_name设置为android-5c1b97cdffffffff之后,我也没有想到使用反向DNS查询来向路由器询问它的名称列表。 路由器将host_name添加到它的DNS服务器,所以如果IP地址更改,仍然可以访问该设备。

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

取决于host_name的一个缺点是有一些方法可以改变。 设备制造商或运营商很容易改变host_name(虽然search后,我一直无法find他们有任何证据)。 有些应用程序可以更改主机名 ,但是它们需要root,所以最多只能是一个边缘情况。

最后还有一个开放的Android Issue 6111:允许指定一个主机名 ,当前有629个星星。 在Android设置中看到可configuration的host_name在未来的某个时刻(也许很快)就不足为奇了。 所以,如果你开始根据host_name识别Android设备,意识到它可以从你的下拉出。

如果您正在进行实时跟踪,反向DNS查找的另一个潜在问题是您必须决定扫描的频率。 (当然,如果你只是做一次性的快照,这不是问题。)频繁的扫描会占用networking资源,经常会导致数据丢失。 以下是如何添加DHCP监控可以帮助:

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

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

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

  • JmDNS (适用于苹果的Bonjour协议)
  • Cling (用于微软的UPnP协议)
  • Android NSD API (自Android 4.1推出以来)

我不太清楚你的要求,如果你想在类似的东西(即自动发现和连接)在香草的Android设备上,你可能可以使用Wi-Fi的直接 ,现在可以在一些运行Android 4.0的后续设备,但是,它需要这两款设备都支持Wi-Fi Direct,并且只能在closuresWi-Fi的情况下创build点对点P2P连接,就像更长距离的蓝牙连接一样:

在这里输入图像说明

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

我正在看这个想法

http://www.libelium.com/smartphones_iphone_android_detection

特别注意这一点

用户是否需要安装特定的应用程序或以某种方式进行交互以进行检测?

不,扫描是静静地执行的,Meshlium只是检测由智能手机中集成的Wifi和蓝牙无线电发起的“信标帧”。 用户只需要打开两个无线接口中的至less一个。

很久以前,我用我的苹果机上的一个叫stumbler的应用程序来查找wifinetworking,我觉得这很类似

其他的想法

那么如果我需要确定本地networking上的Android手机,我会怎么做。 没有运行DNS服务,我只有几个可能性

SSID,如果它被广播 – 不能告诉我什么IP地址 – android可以让你有很多控制主机命名,所以我想你可以定义一个特定的IP范围到您的Android设备。 – 没有用。

或者让我说我看到networking上的一个未知的设备,如果蓝牙打开,然后我广播蓝牙设备签名SDPP,我可以用来推断我的设备types。

如果我正在运行一个支持android的服务,我想在我的networking上发现特定的android设备,那么我可以注册这些设备的mac地址,并在networking上观察它们。

除此之外,您需要在设备上运行bonjour(dns-sd)或upnpp dameon。

更新的响应

对不起,我没有正确理解原来的问题。 只有你的评论让我很清楚,你不想在目标设备上安装任何东西 ,但你只是想在你的networking中发现随机手机。

我不确定这是否真的有可能在你想要的方式。 没有任何networking发现服务在Android上运行,您将无法find设备在第一位。 当然,你可以使用一些低级别的networking协议,但是这只会给你一个指示,说明有什么东西,但不是它是什么(作为一个Android设备,PC,其他任何东西)。

最有前途的方法是检查预装的具有某种networkingfunction的应用程序。 例如,三星设备有Kies Air(如果用户启用的话),如果我没有记错的话,摩托罗拉正在使用UPnP作为他们的媒体服务器,HTC也有自己的东西。 但是,所有供应商和运营商的所有Android设备上都没有安装应用程序。 所以你不能单单依靠其中的一个,而是需要使用他们特定的协议和行为来检查各种不同的服务,以获得有关设备的附加信息。 而且,当然,用户必须启用该function才能使用它。

旧的回应

约克的另一个select是Qualcomm的AllJoyn 。 这是一个我以前用过的开源跨平台发现和点对点通信框架。

虽然Qualcomm是AllJoyn的大赞助商,但这并不意味着您需要在定义中使用Qualcomm芯片组。 事实上,AllJoyn可以在包括Intel和nVidia在内的任何芯片组上工作。 它不需要固定电话或对Android框架进行任何其他修改,只需使用Wi-Fi和/或蓝牙作为配对方法即可“开箱即用”。

我从这个话题中学到了很多东西。

还有一些叫做dhcp指纹的东西,显然不同的设备对于我们一直在讨论的那种networking扫描有不同的作用,比如那些使用NMAP的linux扫描器。 来自这些探测器的行为地图可以在互联网上find。

http://www.enterasys.com/company/literature/device-profiling-sab.pdf

https://media.defcon.org/dc-19/presentations/Bilodeau/DEFCON-19-Bilodeau-FingerBank.pdf

http://community.arubanetworks.com/t5/ArubaOS-and-Mobility-Controllers/COTD-DHCP-Fingerprinting-how-to-ArubaOS-6-0-1-0-and-above/td-p/11164

http://myweb.cableone.net/xnih/

这里有一个命令,用于ping你的networking上的所有机器(假设你的networking是192.168.1.x ),并对它们的名字进行反向查询:

 for i in {1..255}; do echo ping -t 4 192.168.1.${i} ; done | parallel -j 0 --no-notice 2> /dev/null | awk '/ttl/ { print $4 }' | sort | uniq | sed 's/://' | xargs -n 1 host 

需要GNU并行工作。 您可以使用“brew install parallel”在OSX上进行安装

从这里你可以看看名为android-c40a2b8027d663dd.home.的设备android-c40a2b8027d663dd.home. pipe他呢。

然后你可以试着在设备上运行nmap -O来看看还有什么可以弄清楚的:

 sudo nmap -O android-297e7f9fccaa5b5f.home. 

但这并不是那么有成效。