web-dev-qa-db-ja.com

ネットワーク上のデバイスを発見する方法Android?

ネットワーク上のAndroidデバイスを検出し、それらに関するデバイス情報を取得できるようにしたい。 AppleデバイスはBonjourサービスを実行するため、これは非常に簡単です。ただし、Androidで実行されている同様のサービスは見つかりません。

これは、Androidデバイスを変更したり、サービスをインストールしたり、ポートを開いたりすることなく機能する必要があります。 BonjourがVanilla Androidデバイスを見つけるのに役立つように、Vanilla Appleデバイスで動作することを意図しています。デバイスがAndroidを実行していることを確認するだけでも十分です。


選択した回答:(まだ)最高評価の回答ではありませんが、ルイスの回答をご覧ください。彼が言及したように、DNSルックアップ(ローカルDNSサーバーを使用)を使用してAndroidデバイスを検出できます。 AndroidがデバイスにAndroidホスト名の使用を強制するため、これが100%の成功率を持つことがわかりました-_ ____。これは、たとえルート化されていても、電話で変更することは明らかに困難です。ですから、これはかなり正確な方法だと思います。ありがとう、ルイス!

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で実行する場合など)、外部DNSサーバーを使用するためgetHostName()を簡単に使用できません。たとえば、ルーターでローカル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.

ビンゴ。

55
gnychis

いくつかの異なるデバイスで良い結果が得られた非常にシンプルなアプローチがあります。

デバイスがルーターに接続すると、IP(つまりDHCP)を受信し、DNSに名前を登録します。登録されている名前は、常に_Android_nnnnnnnn_という形式になっているようです。

もちろん、同じアプローチで任意のコンピューターに名前を付けてチェックをtrickすことで、誤検知を引き起こすことができます...

また、すべてのデバイスサプライヤが同じアプローチに従っていることを保証できませんが、テストしたさまざまなブランド(さまざまなSDKレベルを含む)のいくつかのデバイスで正しく動作することがわかりました。

-編集済み-

それを行う方法

Androidデバイスを検出するためにコードを実行する場所によって異なります。Androidデバイスでコードを実行すると仮定すると:

  1. まず、ネットワーク内のPingに応答するデバイスを検出します。この投稿に対する私の回答のコードを使用できます: execComd() pingコマンドを実行します。
  2. コードを使用して応答デバイスの名前を取得します。

    InetAddress inetAddress = InetAddress.getByName(string_with_ip_addr);

    文字列名= inetAddress.getCanonicalHostName();

-編集2--

概念実証

以下のメソッドは、私が上で書いたものの概念の教授です。

isReachable()メソッドを使用してICMPリクエストを生成しています。これは、ルート化されたデバイスでのみ機能する多くの投稿で言われていますが、これはテストに使用されるデバイスの場合です。ただし、このコードを実行するアプリケーションにルート権限を付与しなかったため、SIUDビットを設定できなかったと考えています。これが、このメソッドが失敗する理由です。私はここで、ルート化されていないデバイスでテストしている人からです。

電話をかけるには:

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

hostsaに、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;
}
_

よろしく。

31
Luis

AndroidはiOSほど簡単ではありません。 Bonjourに相当するものはありません。

Android 4.0、アイスクリームサンドイッチ、導入 Wi-Fi Direct ピアツーピアネットワーキング。最初は、あなたの思い通りにスキャンできることを望んでいましたが、Androidデバイスがアクセスポイントなしで通信できるので、実際には「ネットワーク上」ではありません。また、ICSはAndroidデバイスのごく一部でのみ実行されます。

アクティブネットスキャンアプローチではなく、パッシブモニタリングアプローチが残ります。ネットワークが安全な場合、暗号化されたパケットを盗聴することは可能ですが、不便です。する必要があります

  • ネットワークインターフェースを モニターモード に設定します
  • 4-way handshake をキャプチャします
  • ネットワークの事前共有キーを使用して復号化する
  • これにより、トラフィックを復号化するために必要なキーが得られます

これを実際に見たい場合、 WiresharkWPA復号化 をサポートします。

Wi-Fiトラフィックを表示できるようになると、Androidデバイスは特定のGoogleサーバーと通信する傾向があり、そのHTTP接続には 識別可能なユーザーエージェント文字列 があります。これは、実行可能なパッシブソリューションの基盤です。

Tenable Network Security このタイプのアプローチを採用していると思われる製品を提供します。

別のアイデア

@Michelle Cannon氏はLibeliumのMeshlium Xtremeについて言及しましたが、そのアプローチではそこまで行くことはできません(最新のMACアドレス範囲テーブルがないわけではありません)。しかし、それはより小さな目標を達成することの一部かもしれません。あなたはできる:

  • すべてのワイヤレスデバイスを検出する
  • MACのOrganizationally Unique Identifier(OUI)を使用してAppleデバイスを排除します
  • 信号強度を監視して移動していることを判断することで、モバイルデバイスであることを通知します(モバイルデバイスは表示されて消える傾向があります)
  • MAC OUIをAndroidのヒントとして使用できる場合があります
  • MAC OUIをAndroidではないヒントとして使用できる場合があります(ただし、ラップトップまたはワイヤレスカードなど)。

おそらく Androidのデバイスを検出したい場合、これは実行可能です。

DHCPフィンガープリンティング

@Michelle CannonはDHCPフィンガープリンティングを提案しました。最初は確信がありませんでしたが、単純なパッシブスキャンの最善策のように見えるものを提案してくれたことに感謝しなければなりません。念のため、パーティーに遅れた理由を説明したいと思います。

私たちが知っていること、私たちが知らないと思っていること、私たちが知っていると思うが間違っていることがあります。

多くの点で、AndroidがLinuxカーネルを使用するのは良いことです。ただし、ネットワーク上のAndroidデバイスを検出するのはよくありません。 AndroidのTCP/IPスタックはそのためLinuxのAndroidデバイスはLinuxデバイスのように見えます。しかし、Linuxにはa lotのビルド構成パラメーターがあるため、ネットワーク上で見たときにAndroidに特有の何かがある可能性がありますが、それは何ですか?

DHCPフィンガープリントでは、デバイスに要求された正確なDHCPオプションとタイミングが使用されます。これが機能するには、通常、最新の指紋データベースと照合する必要があります。最初は fingerbank がこのデータを調達しているように見えましたが、そのファイルがほぼ1年間更新されていないことに気付きました。さまざまなAndroidデバイスタイプがあるため、1つのプロジェクトの更新されたフィンガープリントを保持することは実用的ではないと思います。

しかし、その後、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アドレスなしで最初に表示される最初の交換のみがブロードキャストされます。将来のリース延長などは放送されません。

逆引きDNSルックアップ

@Luisは、どれほどシンプルで優れているかを示す優れたソリューションを投稿しました。 AndroidのDHCPクライアントがHost_nameをAndroid-5c1b97cdffffffffに設定しているのを見ても、逆DNSルックアップを使用して名前のリストをルーターに要求することは考えていませんでした。ルーターはDNSサーバーにHost_nameを追加するため、IPアドレスが変更された場合でもデバイスにアクセスできます。

Host_nameは、DHCPリース期間中、DNSにリストされたままになると予想されます。 pinging itにより、デバイスがまだ存在するかどうかを確認できます。

Host_nameに依存する1つの欠点は、これを変更できる方法があることです。デバイスの製造元または通信事業者がHost_nameを変更するのは簡単です(ただし、検索した後、彼らが持っている証拠を見つけることができませんでした)。 ホスト名を変更するアプリ がありますが、ルートが必要なため、多くてもEdgeのケースになります。

最後に、現在開いている Android Issue 6111:ホスト名の指定を許可 現在629の星があります。 Androidの設定で構成可能なHost_nameが将来のある時点で、おそらくすぐに表示されるのは驚くことではありません。したがって、Androidデバイスを識別するためにHost_nameに依存して開始する場合、それがあなたの下からヤンクされる可能性があることを理解してください。

ライブトラッキングを行う場合、逆DNSルックアップの別の潜在的な問題は、スキャンの頻度を決定する必要があることです。 (もちろん、1回限りのスナップショットを撮っている場合、これは問題になりません。)頻繁なスキャンはネットワークリソースを消費し、まれに古いデータが残ります。 DHCP監視の追加がどのように役立つかを次に示します。

  • 起動時に、逆DNSルックアップを使用してデバイスを検索します
  • デバイスをPingして、まだアクティブかどうかを確認します
  • DHCPトラフィックを監視して、新しいデバイスを即座に検出します
  • 時々、DNSルックアップを再実行して、見逃したデバイスを見つけます
  • デバイスの離脱を確認する必要がある場合は、目的のタイミング解像度でデバイスにpingを実行します

簡単ではありませんが(100%正確でもありません)、ネットワーク上のAndroidデバイスを検出するためにpossibleにするテクニックがいくつかあります。

21
jimhark

知る限り、Androidシステムは zeroconf 組み込みシステムapp/serviceスタックにapp/serviceを提供しません。実際のデバイスで自動検出を有効にするにはローカルネットワークに接続するには、サードパーティのzeroconfアプリをインストールするか、独自のアプリ/サービスを開発して実際のデバイスにインストールする必要があります。APIオプションは次のとおりです。

  • JmDNS (Appleのbonjourプロトコルの場合)
  • Cling (MicrosoftのUPnPプロトコルの場合)
  • Android NSD API (Android 4.1)以降導入)

Vanilla Androidデバイスでは、おそらく Wi-Fi direct を使用できます。 Android 4.0を実行している後のデバイスで利用可能になりましたが、両方のデバイスがWi-Fi Directをサポートし、Wi-FiをオフにしたアドホックP2P接続のみを作成する必要があります。より長い範囲のBluetooth接続:

enter image description here

Wi-Fi Direct APIサポートについては、公式ガイドをご覧ください- Connecting Devices Wirelessly

5
yorkw

私はこれを考えています

http://www.libelium.com/smartphones_iphone_Android_detection

これに特別な注意を払う

ユーザーは特定のアプリをインストールする必要がありますか、それとも何らかの方法で検出する必要がありますか?

いいえ、スキャンはサイレントに実行されます。Meshliumは、スマートフォンに統合されたWifiおよびBluetooth無線によって発生した「ビーコンフレーム」を検出するだけです。ユーザーは、2つのワイヤレスインターフェイスのうち少なくとも1つをオンにする必要があります。

昔、私は私のMacでstumblerというアプリを使ってWi-Fiネットワークを見つけていましたが、これは似ていると思います

他のアイデア

ローカルネットワーク上のAndroid電話を特定する必要がある場合、どうすればよいでしょうか。 DNSサービスが実行されていないため、いくつかの可能性しかありません

SSIDがブロードキャストされている場合-何も言えないIPアドレス-Androidを使用すると、ホストの名前付けを詳細に制御できるため、特定のIP範囲をAndroidデバイス。 -役に立たない。

または、ネットワーク上に不明なデバイスが表示されていると言えます。Bluetoothがオンになっている場合、BluetoothデバイスシグネチャSDPPをブロードキャストしており、これを使用してデバイスタイプを推測できます。

Androidをサポートするサービスを実行していて、ネットワーク上の特定のAndroidデバイスを検出したい場合、それらのデバイスのMACアドレスを登録して、通信網。

それ以外は、デバイスでbonjour(dns-sd)またはupnpp dameonを実行する必要があります。

2
Michelle Cannon

私はこのトピックから多くを学んでいます。

また、dhcpフィンガープリントと呼ばれるものもあります。明らかに、異なるデバイスは、LinuxスキャナーであるNMAPを使用するデバイスなど、これまで議論してきたネットワークスキャンの種類とは異なる動作をします。これらのプローブの動作のマップは、インターネットで入手できます。

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/

1
Michelle Cannon

更新された応答

申し訳ありませんが、元の質問を正しく理解していません。あなたのコメントだけが、ターゲットデバイスにanythingをインストールする必要はないが、ネットワーク内のランダムな電話を発見する方法が必要であることを本当に明確にした。

これがあなたが望むように本当に可能になるかどうかはわかりません。ネットワーク検出サービスを実行せずにAndroid最初にデバイスを見つけることはできません。もちろん、低レベルのネットワークプロトコルを使用することもできますが、それは何かがあることを示すインジケータのみを提供しますしかし、そうではありません(Androidデバイス、PC、その他何でも)。

最も有望なアプローチは、何らかのネットワーク機能を備えたプリインストールされたアプリをチェックすることです。例えば。 SamsungデバイスにはKies Air(ユーザーが有効にしている場合)があり、MotorolaはMedia ServerにUPnPを使用しており、HTCにも同様に記憶しています。ただし、すべてのベンダーおよびキャリアのすべてのAndroidデバイスにインストールされるアプリはありません。したがって、これらの1つだけに依存することはできませんが、特定のサービスを使用してさまざまなサービスを確認する必要がありますデバイスに関する追加情報を取得するためのプロトコルと動作、そしてもちろん、ユーザーはそれを使用するために機能を有効にする必要があります。

古い応答

Yorkwのリストの追加の代替手段は、クアルコムの AllJoyn です。これは、私が過去に自分ですでに使用したオープンソースのクロスプラットフォーム検出およびピアツーピア通信フレームワークです。

QualcommはAllJoynの大きなスポンサーですが、これは、定義にQualcommチップセットが必要であることを意味するものではありません。実際、AllJoynはIntelやnVidiaを含むあらゆるチップセットで動作します。根ざした携帯電話やAndroidフレームワークへのその他の変更を必要とせず、ペアリング方法としてWi-FiやBluetoothを使用するだけで機能します。

1
André

これは、ネットワーク上のすべてのマシンにpingを実行し(ネットワークが192.168.1.xであると想定)、名前の逆引きを行う1つのライナーです。

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 parallel for work。をインストールします。「brew install parallel」を使用してOSXにインストールできます。

これから、Android-c40a2b8027d663dd.home.またはその他の名前のデバイスを見ることができます。

その後、デバイスでnmap -Oを実行して、他に何がわかるかを確認できます。

Sudo nmap -O Android-297e7f9fccaa5b5f.home.

しかし、実際にはそれほど実りはありません。

0
Will Schenk