gny*_*his 55 android service-discovery discovery
我希望能够在我的网络上发现Android设备,并可能检索有关它们的一些设备信息.Apple设备使用Bonjour服务非常容易.但是,我似乎无法在Android上运行任何类似的服务.
这必须在不修改Android设备,安装某些服务或打开某个端口的情况下工作.这意味着以Bonjour帮助您找到香草Apple设备的方式使用vanilla Android设备.即使能够只是验证设备运行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.
Run Code Online (Sandbox Code Playgroud)
示例代码:如果您想在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);
}
Run Code Online (Sandbox Code Playgroud)
这给了我输出:
DNS Record: android-711c129e251f14cf.\001.
Run Code Online (Sandbox Code Playgroud)
答对了.
Lui*_*uis 31
有一种非常简单的方法可以在少数不同的设备上给我带来积极的结果.
当设备连接到您的路由器时,它会收到一个IP(即DHCP)并在DNS中注册一个名称.注册的名称似乎始终在表单中android_nnnnnnnn
.
对于cource,您可以使用相同的方法命名任何计算机并欺骗检查,从而导致误报......
此外,我无法确保所有设备供应商都采用相同的方法,但我发现它可以在我测试的不同品牌(包括不同的SDK级别)的少数设备中正常工作.
--EDITED--
怎么做
这取决于您将运行代码来发现Android设备的位置.假设您将在Android设备中运行代码:
Ping
在您的网络中响应的设备.您可以在我对这篇文章的回答中使用代码:execComd()来运行ping命令.使用代码获取响应设备的名称:
InetAddress inetAddress = InetAddress.getByName(string_with_ip_addr);
String name = inetAddress.getCanonicalHostName();
--EDIT 2--
概念证明
下面的方法只是我上面写的内容的概念.
我正在使用isReachable()
方法来生成ICMP请求,这在许多帖子中都说过,这些帖子只适用于有根设备,这是用于测试它的设备的情况.但是,我没有为运行此代码的应用程序授予root权限,因此我认为它无法设置SIUD位,这就是为什么某些绑定此方法失败的原因.我想在这里有人在非root设备上测试它.
要求使用:
ArrayList<String> hosts = scanSubNet("192.168.1.");
Run Code Online (Sandbox Code Playgroud)
它返回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;
}
Run Code Online (Sandbox Code Playgroud)
问候.
jim*_*ark 21
Android不会像iOS那么容易.没有Bonjour等价物.
Android 4.0,Ice Cream Sandwich,推出了Wi-Fi Direct Peer to Peer网络.起初我希望它能够以您的思维方式进行扫描,但它可以帮助Android设备在没有接入点的情况下进行通信,因此它们并非真正"在您的网络上".此外,ICS仅运行一小部分Android设备.
而不是主动的网络扫描方法,你留下了被动监控方法.如果您的网络是安全的,可以嗅探加密数据包,但不方便.你必须这样做
一旦您能够查看Wi-Fi流量,您就会注意到Android设备倾向于与某些Google服务器通信,并且其HTTP连接具有可识别的用户代理字符串.这是可行的被动解决方案的基础.
Tenable Network Security提供的产品似乎采用这种方法.
@Michelle Cannon提到了Libelium的Meshlium Xtreme,它的方法不会让你一直到那里(不是没有最新的MAC地址范围表).但它可能是实现较小目标的一部分.您可以:
如果您愿意检测可能是 Android的设备,这可能是可行的.
@Michelle Cannon建议使用DHCP指纹识别.起初我不确定,但我要感谢他建议看起来像是简单被动扫描的最佳选择.作为警示尾巴,我想解释一下为什么我迟到了.
从很多方面来说,Android使用Linux内核是件好事.但是,如果您想在网络上发现Android设备,那就不好了.Android的TCP/IP堆栈就是Linux,因此Android设备看起来就像Linux设备一样.但后来我意识到Linux有很多构建配置参数,所以当在网络上看到Android时可能会有一些与众不同的东西,但是什么呢?
DHCP指纹识别使用设备请求的确切DHCP选项加上时序.为此,您通常需要一个最新的指纹数据库来匹配.起初看起来看起来像fingerbank一样采购这些数据,但后来我注意到他们的文件近一年没有更新.对于所有不同的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
Run Code Online (Sandbox Code Playgroud)
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()
Run Code Online (Sandbox Code Playgroud)
此代码基于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
Run Code Online (Sandbox Code Playgroud)
主机名似乎具有固定格式并且易于解析.如果需要IP地址,可以监控服务器到客户端的流量.注意:仅当新客户端首次显示没有IP地址时才进行初始交换.未来的租约延期等不会被广播.
@Luis发布了一个很好的解决方案,演示了更简单的更好.即使在看到Android的DHCP客户端将host_name设置为android-5c1b97cdffffffff后,我也没想到要使用反向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监控可以提供帮助的方法:
虽然这并不容易(也不是100%准确),但有几种技术可以发现网络上的Android设备.
AFAIK,Android系统在其内置的系统应用/服务堆栈上不提供任何zeroconf应用/服务.要在连接到本地网络的实际设备上启用自动发现,您需要安装一些第三方zeroconf应用程序或开发自己的应用程序/服务并将其安装在实际设备上,一些API选项是:
我不太清楚你的要求,如果你想在类似香草的Android设备上有类似的东西(即自动发现和连接),你可以使用Wi-Fi direct,现在可以在以后运行Android 4.0的设备上使用,但是,它需要这两款设备都支持Wi-Fi Direct,只能在关闭Wi-Fi的情况下创建ad-hoc P2P连接,就像具有更长距离的蓝牙连接一样:
有关Wi-Fi Direct API支持,请查看官方指南 - 无线连接设备.
归档时间: |
|
查看次数: |
54711 次 |
最近记录: |