AndroidはiOSほど簡単ではありません。Bonjourに相当するものはありません。
Android 4.0、Ice Cream Sandwichは、Wi-Fi Direct PeertoPeerネットワーキングを導入しました。最初は、あなたの考えどおりにスキャンできることを望んでいましたが、Androidデバイスがアクセスポイントなしで通信するのに役立つため、実際には「ネットワーク上」にはありません。さらに、ICSはAndroidデバイスのごく一部でのみ実行されます。
アクティブなネットスキャンアプローチではなく、パッシブモニタリングアプローチが残されています。ネットワークが安全であれば、暗号化されたパケットをスニッフィングすることは可能ですが、不便です。あなたがしなければならないでしょう
これが実際に動作していることを確認したい場合は、WiresharkがWPA復号化をサポートしています。
Wi-Fiトラフィックを表示できるようになると、Androidデバイスは特定のGoogleサーバーと通信する傾向があり、そのHTTP接続には識別可能なユーザーエージェント文字列が含まれていることがわかります。これは、実行可能なパッシブソリューションの基礎です。
Tenable Network Securityは、このタイプのアプローチを採用しているように見える製品を提供しています。
別のアイデア
@Michelle Cannonは、LibeliumのMeshlium Xtremeについて言及しました。そのアプローチでは、そこまで到達することはできません(最新のMACアドレス範囲テーブルがないわけではありません)。しかし、それはより小さな目標を達成することの一部である可能性があります。あなたはできる:
- すべてのワイヤレスデバイスを検出する
- MACのOrganizationallyUniqueIdentifier(OUI)を使用してAppleデバイスを排除する
- 信号強度を監視して移動していることを確認することで、モバイルデバイスであることを伝えます(モバイルデバイスは表示されて消える傾向があります)
- あなたはそれがAndroidであるというヒントとしてMACOUIを使うことができるかもしれません
- MAC OUIは、Androidではない(ラップトップやワイヤレスカードなど)ヒントとして使用できる場合があります。
これは、おそらくAndroidであるデバイスを検出する意思がある場合に機能する可能性があります。
DHCPフィンガープリント
@Michelle Cannonは、DHCPフィンガープリントを提案しました。最初はわかりませんでしたが、単純なパッシブスキャンの最善策のように見えるものを提案してくれた彼に感謝しなければなりません。注意点として、なぜパーティーに遅れたのかを説明したいと思います。
私たちが知っていること、知らないと思うこと、知っていると思うが間違っていることがあります。
多くの点で、AndroidがLinuxカーネルを使用するのは良いことです。ただし、ネットワーク上でAndroidデバイスを検出する場合は適切ではありません。AndroidのTCP/IPスタックはLinuxであるため、AndroidデバイスはLinuxデバイスのように見えるので、最初は考えました。しかし、Linuxには多くのビルド構成パラメーターがあるので、ネットワーク上で見たときにAndroidに特有の何かがある可能性があることに気付きましたが、どうでしょうか。
DHCPフィンガープリントは、デバイスとタイミングによって要求された正確なDHCPオプションを使用します。これが機能するためには、通常、照合するための最新の指紋データベースが必要です。最初は、 fingerbankがこのデータを調達するために混雑しているように見えましたが、その後、ファイルがほぼ1年間更新されていないことに気付きました。すべての異なる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は通常DHCPクライアントとしてdhclientを使用しますが、Androidはdhcpcdを使用しています。Androidは、可能な場合はBSDスタイルでライセンスされたソフトウェアを使用することを強く好み、dhcpcdはBSDライセンスを使用します。dhcpvendorcodeは、モバイルデバイスがAndroidを実行していることを示す強力な指標として使用できるように思われます。
DHCP監視
クライアントは、ネットワークに参加するときにDHCPを使用してIPアドレスを取得するため、IPアドレスなしで開始します。最初の交換にUDPブロードキャストを使用することで、この問題を回避します。Wi-Fiでは、WPAを使用しても、ブロードキャストトラフィックは暗号化されません。したがって、UDPポート67でクライアントからサーバーへのトラフィックをリッスンし、68でその逆をリッスンできます。ネットワークインターフェイスを無差別モードにする必要はありません。Wiresharkなどのプロトコルアナライザを使用して、このトラフィックを簡単に監視できます。
私はトラフィックを監視するコードを書くことを好み、Pythonを使用することにしました。DHCPの詳細を処理するためにpydhcplibを選択しました。このライブラリでの私の経験はスムーズではありませんでした。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-5c1b97cdffffffffに設定しているのを見た後でも、DNS逆引き参照を使用してルーターに名前のリストを要求することは考えていませんでした。ルーターはhost_nameをDNSサーバーに追加するため、IPアドレスが変更されてもデバイスにアクセスできます。
host_nameは、DHCPリースの期間中、DNSにリストされたままになると予想されます。pingを実行することで、デバイスがまだ存在するかどうかを確認できます。
host_nameに依存することの1つの欠点は、これを変更できる方法があることです。デバイスの製造元または通信事業者がhost_nameを変更するのは簡単です(ただし、検索した後、彼らが持っている証拠を見つけることができませんでした)。ホスト名を変更するアプリはありますが、rootが必要なので、せいぜいエッジケースです。
最後に、未解決のAndroid Issue6111があります。現在629個の星が付いているホスト名を指定できるようにします。将来のある時点で、おそらくすぐに、Android設定で構成可能なhost_nameが表示されるのは当然のことです。したがって、Androidデバイスを識別するためにhost_nameに依存し始める場合は、それがあなたの下からヤンクアウトされる可能性があることに注意してください。
ライブトラッキングを実行している場合、逆引きDNSルックアップのもう1つの潜在的な問題は、スキャンの頻度を決定する必要があることです。(もちろん、これは1回限りのスナップショットを作成する場合は問題になりません。)頻繁にスキャンするとネットワークリソースが消費され、まれに古いデータが残ります。DHCP監視を追加すると次のようになります。
- 起動時に逆引きDNSルックアップを使用してデバイスを検索します
- デバイスにpingを実行して、デバイスがまだアクティブかどうかを確認します
- DHCPトラフィックを監視して、新しいデバイスを即座に検出します
- ときどきDNSルックアップを再実行して、見逃した可能性のあるデバイスを見つけます
- デバイスが離れていることに気付く必要がある場合は、希望のタイミング解像度でデバイスにpingを実行します
簡単ではありませんが(100%正確でもありません)、ネットワーク上のAndroidデバイスを検出できるようにするいくつかの手法があります。