尝试使用python脚本在我的网络上发现iOS设备



尝试使用pybonjour,但不确定它是否是我需要的。https://code.google.com/p/pybonjour/

我希望能够自动发现出现在我的网络上的iOS设备,将在此基础上运行一个脚本,但首先我想发现一个iOS设备,只要它出现/消失在我的wifi网络上。

问题是,我该怎么做?在安装了python27和pybonjour包的windows机器上运行,这两个示例从pybonjour页面工作,但是我应该运行什么命令来使用网络中包含的脚本发现iOS设备?或者这只会发现服务运行在我的PC上,我运行这个脚本!

如果我走错了方向,请告诉我,我似乎找不到这个包上的文档!

python browse_and_resolve.py xxxxxx

谢谢马特。

更新……

这篇文章和浏览器是有帮助的,http://marknelson.us/2011/10/25/dns-service-discovery-on-windows/在找到我需要搜索的服务。

例子;(这个发现是我的苹果电视,不是家里的自动取款机,所以无法查看iPhone的名字!)我猜是iphone!

python browse_and_resolve.py _appletv._tcp

如果你有windows实用程序dns-sd.exe,它将搜索网络上所有可用的服务。我用它来找到我要找的东西。

dns-sd -B _services._dns-sd._udp

更新……

"Bonjour以两种方式使用:-发布服务-检测(浏览)可用的服务"。

对于我想做的,我不认为它会工作,因为ipad/iPhone不会宣传一个服务,除非我运行一个应用程序来宣传一个(或越狱我的iPhone/ipad,然后ssh将打开)。还有别的主意吗?

你想做的事情(a)可能无法完成,(b)即使可以,也可能没有多大用处。

Bonjour的目的是发现服务,而不是设备。当然,每项服务都是由某些设备提供的,所以你可以间接地发现使用它的设备,但只能通过发现它们正在宣传的服务。

据我所知,(除了苹果电视)不宣传任何服务,除非你运行一个应用程序,使用Bonjour在其他机器上找到相同的应用程序。(越狱设备除外,通常会宣传SSH, AFP等)

有几种方法可以间接地获得网络上任何人正在宣传的所有服务的列表。最简单的可能是在Windows上使用Bonjour浏览器。(我从未真正使用过它,但我使用过的原始Mac工具和Java端口都建议Windows用户使用这个Windows端口。)启动它,你会得到一个服务列表,你可以点击每一个来获取详细信息。

所以,你可以验证你的iPhone和iPad没有广告任何服务,这将表明没有办法通过Bonjour检测到它们。

与此同时,即使你确实找到了一个设备,你打算做什么?假设你想以某种方式与设备通信,对吧?无论你想使用什么服务,只要浏览一下就可以了——然后,如果合适的话,过滤到iOS设备上。这肯定比在iOS设备上浏览,然后过滤到那些有你想要的服务的设备更容易。

至于是否有任何方法来检测iOS设备…嗯,至少有两种可能性。我不知道他们是否会工作,但是…

首先,即使iOS设备没有为你做任何广告,我假设它在浏览你可以做广告的服务。除此之外,它是如何发现有一台苹果电视可以播放AirTunes,有一台局域网上的iTunes可以同步,等等?

所以,使用Bonjour浏览器来获得你的itunes运行的桌面,Apple TV等的所有服务的广告列表。然后关闭桌面上的所有服务,使用PyBonjour发布任何看起来似乎相关的服务(如果需要,还可以使用netcat在发布的端口上放置简单的侦听器)。然后打开你的iPhone,看看它是否连接到其中任何一个。你可能想让它运行一段时间,或者把WiFi关掉再打开。(我猜,尽管有苹果的建议,但它不会连续浏览大多数服务,只是偶尔检查一下,或者每次网络状态发生变化时检查一下。毕竟,苹果推荐的是前台交互应用,而不是后台服务。

不幸的是,即使你能找到一个所有iOS设备都能连接的服务,你也可能无法通过连接来区分iOS设备和其他设备。例如,我很确定任何运行iTunes的Mac或Windows盒子都会打开你的假AirTunes服务,任何Mac都会打开你的AirPrint服务,以此类推。那么,你如何区分它和iPhone的撞击呢?您可能需要实际提供足够的协议来从中获取信息。这对苹果的无文件协议来说尤其困难。

但希望你会幸运,会有一些东西,所有的iOS设备,而不是其他的,想要交谈。iTunes同步似乎是显而易见的可能性。

或者,他们要广播的一些东西,否则它们就无法工作。如果没有广播,你就无法使用WiFi网络。而且大多数家庭WiFi网络使用DHCP,这意味着它们也必须广播DHCP发现(和请求)。您可以在这些消息中检测到某种启发式签名。如果没有别的,启用DDNS应该会导致设备发送它的主机名,你可以根据它来猜测(例如,除非你改变默认值,hostname.lower().endswith('iphone'))。

最简单的方法可能是将桌面设置为家庭网络的主要接入点。我相信这就像在控制面板的某个地方打开互联网连接共享一样简单。(设置为DHCP中继代理比设置为完整路由器的开销要少得多,但我不知道你如何在Windows上开始这样做。)然后,您可以捕获传入的DHCP广播(如果无法捕获,则捕获802.11广播)。Wireshark将为您轻松捕获和解析消息,因此您可以观察并看看是否值得进一步研究。(参见RFC 2131了解有关格式的详细信息,从Wireshark的神秘的一行描述中不明显。)

你可以更进一步,观察每台主机连接到互联网后的互联网连接。任何定期检查App Store, iOS升级服务器等的设备....好吧,除非有一个越狱开发团队的家伙住在你家里,那可能是iPhone,对吧?缺点是其中一些检查可能非常定期,并且在iPhone连接网络6小时后检测到它并不是很令人兴奋。

使用python-nmap而不是Bonjour。或者你可以使用pyzeroconf (Bonjour是zeroconf的一个实现),但它有点过时了(但应该仍然可以工作)。

python-nmap可能是最简单的,让我们假设你想找到所有在主机名中有'iPhone'或'iPad'的连接设备(只是一个简单的概念):

import nmap
...
def notify_me(ip, hostname):
print("I found an iOS device! IP Address: %s, Hostname: %s" % (ip, hostname))
iOS_device_list = ['iPhone', 'iPad']
iOS_devices_on_net = {}
nm = nmap.PortScanner()
# scan ip range
for i in range(2, 50, 1):
ip = "192.168.1." + str(i)
# specify ports to scan
nm.scan(ip, '62078') # Matt mentioned that it picks up iphone-sync on this port
hostname = nm[ip].hostname()
for device in iOS_device_list:
if device.lower() in hostname.lower():
iOS_devices_on_net.update({ip:hostname})
notify_me(ip, hostname)
# show all iOS devices in ip range
print iOS_devices_on_net

这种方法的限制是它依赖于个人没有更改他们的主机名,主机名最初包括他们的名称和设备名称。它还假设iOS设备上有一个端口侦听,该端口将返回主机名(事实可能并非如此)。您可以通过使用python-nmap库将osscan作为命令运行来使用它,这是首选。这显然是一个更好的方法。我上面的概念只是一个如何使用它的简单例子。

从命令行使用nmap(我相信python-nmap有nm.commandline()方法)是最简单的:

nmap -O -v ip

还可以尝试添加--osscan-guess; --fuzzy以获得最佳效果。例子:

nmap -O -v --osscan-guess ip

然后在输出中搜索iOS设备关键字(参见本例)。这是人类可读的。请注意,您需要以管理员身份运行所有这些操作才能正常工作(Windows:runas, other:sudo)。

我研究这个问题已经有一年了。我很快就在我的mac上运行了它,但在我的PC上运行却遇到了很多麻烦。我试过很多很多不同的方法。我有一个家庭自动化系统,当我或我的伴侣在家时(也就是说,我们的iphone可以在家庭WiFi上检测到),它会打开暖气和热水(通过arduino和射频模块)。最后,我使用'nslookup'来查找iPhone的IP地址(以防IP地址发生变化,因为它们是动态的(但它们实际上从未在我的路由器上做过))和'nmap'来检测iPhone是否在网络上。如果iPhone处于深度睡眠状态,"nmap"并不总能找到手机,所以我让它检查了10次才显示手机在家。下面是我用python编写的部分家庭自动化代码。我用过穿线。对以下代码有任何问题,请告诉我。

# Dictionary to store variables to reuse on program restart
v = {
'boilerControlCH' : 'HIH', # 'scheduled' or 'HIH' (Honey I'm Home)
'boilerControlHW' : 'scheduled',
'thermostatSetPoint' : 20.8,
'thermostatVariance' : 0.1,
'morningTime' : datetime(1970,1,1,6,0,0),
'nightTime' : datetime(1970,1,1,23,0,0),
'someOneHome' : False,
'guest' : False,
'minimumTemperatureOO' : False,
'minimumTemperature' : 4.0,
'iPhoneMark' : {'iPhoneHostname' : 'marks-iphone', 'home' : False},
'iPhoneJessica' : {'iPhoneHostname' :'jessicaesiphone', 'home' : False}
}

# Check if anyone at home
def occupancyStatus(person, Bol = False):
with lockOccupancyStatus:
someOneHome = False
if 'iPhone' in person:
v[person]['home'] = Bol
elif 'retest' in person:
pass
else:
v[person] = Bol
if v['guest'] == True:
someOneHome = True
for key in v:
if 'iPhone' in key:
if v[key]['home'] == True:
someOneHome = True
v['someOneHome'] = someOneHome
variablesToFile()
return

和主代码

# iPhone home status threading code
class nmapClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global exitCounter
nmapThread()
msg.log('Exited nmapThread')    
waitEvent.set()
waitEventAdjustable.set()
serialDataWaiting.set()
exitCounter += 1

def nmapThread():
iPhone = {}
maxCounts = 10
for phone in v:
if 'iPhone' in phone:
iPhone[phone] = {}
iPhone[phone]['hostname'] = v[phone]['iPhoneHostname']
iPhone[phone]['count'] = maxCounts
#msg.log(iPhone)
while exitFlag[0] == 0:
for phone in iPhone:
if iPhone[phone]['count'] > 0:
phoneFound = False
IPAddress = '0.0.0.0'
# Find iPhones IP address using its hostname
commandNsloolup = 'nslookup %s' %iPhone[phone]['hostname']
childNslookup = pexpect.popen_spawn.PopenSpawn(commandNsloolup, timeout = None)
output = childNslookup.readline()
while 'rn' in output:
#msg.log(output)
if 'Name:' in output:
output = childNslookup.readline()
if 'Address:' in output:
tempStr = output
startPoint = tempStr.find('192')
tempStr = tempStr[startPoint:]
IPAddress = tempStr.replace('rn', '')
#msg.log(IPAddress)
output = childNslookup.readline()

if IPAddress == '0.0.0.0':
pass
#msg.error('Error finding IP address for %s' %iPhone[phone]['hostname'], GFI(CF()).lineno)
else:
#commandNmap = 'nmap -PR -sn %s' %IPAddress
#commandNmap = 'nmap -p 62078 -Pn %s' %IPAddress # -p specifies ports to try and access, -Pn removes pinging
commandNmap = 'nmap -p 62078 --max-rate 100 %s' %IPAddress
childNmap = pexpect.popen_spawn.PopenSpawn(commandNmap, timeout = None)
output = childNmap.readline()
while 'rn' in output:
if 'Host is up' in output:
phoneFound = True
break
output = childNmap.readline()
#if phoneFound:
#   break

if phoneFound:              
iPhone[phone]['count'] = 0
if v[phone]['home'] == False:
msg.log('%s's iPhone has returned home' %phone)
occupancyStatus(phone, True)
waitEventAdjustable.set()
#else:
#msg.log('%s's iPhone still at home' %phone)
else:
iPhone[phone]['count'] -= 1
if v[phone]['home'] == True and iPhone[phone]['count'] == 0:
msg.log('%s's iPhone has left home' %phone)
occupancyStatus(phone, False)
waitEventAdjustable.set()
#else:
#msg.log('%s's iPhone still away from home' %phone)
elif iPhone[phone]['count'] < 0:
msg.error('Error with count variable in iPhone dictionary', GFI(CF()).lineno)

longWait = True
for phone in iPhone:
if iPhone[phone]['count'] > 0:
longWait = False
#msg.log('%s: %s' %(phone, iPhone[phone]['count']))
if longWait:
#msg.log('wait long')               
# 600 = run every 10 minutes
waitEvent.wait(timeout=600)
for phone in iPhone:
iPhone[phone]['count'] = maxCounts
else:
#msg.log('wait short')
waitEvent.wait(timeout=60)  
return

如果你把它直接复制到你自己的脚本中,代码可能无法工作,因为有一些部分我没有复制,试图保持事情简单易读,但希望上面的代码给每个人一种我是如何做事情的感觉。

最新更新