最初の部分では、範囲を制限できる限り nmap を使用できます。コメントによると、これにより、必要なホストが既に提供されているはずです。
sudo nmap -PR -sn 192.168.0-255.0-255 -e <interface-to-test>
これにより、ARP に基づいて検出が行われ、成功した場合は、その後、生存のために追加の ICMP ping が送信されます。これには、アクティブなローカル ホストがない範囲で約 1 秒、4 つのアクティブなホストで 5 秒かかりました。そのため、少し広い範囲に拡張することもできますが、1 日か 2 日ある場合を除き、完全な IPv4 アドレス空間には拡張できません。その場合は、wireshark または tcpdump を接続して、Gratuitous ARP を待ちます。
edit : これを機能させるには、テストするサブネットの IP を使用して「ソース マシン」を構成する必要があります。サブネットの外に出るとき、または IP が構成されていないときに、ARP の DAD モードを使用すると想定しましたが、何もしません。以下のアルゴリズム用に作成したスクリプトに、より一般的なバージョンを追加しましたが、単純に nmap を使用してこの結果を取得するよりも少し遅くなります。
構成されたネットマスクを検出するのは少しトリッキーです。しかし、この手順はうまくいくと思います。主なアイデアは、ホストがサブネット内のホストに対して ARP 要求を送信し、サブネット内にないホストに対して default-gw に対して何も送信しないか、ARP 要求を送信しないということです。
- 2 番目に小さいサブネットから始めます
N=29
。
X
ホストの IP とサブネット マスクによって形成されるこのサブネットからIPを選択しますN
。選択した IP がホストの IP ではなく、ネットワーク/ブロードキャストでもないことを確認してください。また、この IP が、ホストの IP とマスクによって形成されるサブネットの一部でないことを確認してN+1
ください。
- ソースを使用して他のホストにping
X
を実行します(応答するかどうかは気にせず、リクエストを送信するだけです)
- の ARP 要求が表示された場合は、 1 つ
X
減らしN
ます。2に戻る
- の ARP 要求が表示されない場合は
X
、N+1
サブネットが検索されています。
1 つの欠点は、過度に野心的なネットワーク スタックの実装が着信 ICMP 要求から MAC を学習する可能性があることですが、個人的には、このように機能するエンド デバイス スタックを知りません。
これを行うツールがあるかどうかはわかりませんが、ping、tcpdump、およびサブネット計算機を使用して手動で簡単に実行できるはずです;)。または、ハッキングをする気があれば、これをscapyで実装するのはおそらくそれほど手間ではありません
私はそれに沿って、動作するはずの完全な python scapy スクリプトを自分で作成し、linksys homegw、別の Linux マシン、および Android デバイスのホーム ネットワークでテストしました。
from __future__ import print_function, absolute_import, unicode_literals
from scapy.base_classes import Net
from scapy.config import conf
from scapy.layers.inet import Ether, ARP, ICMP, IP
from scapy.sendrecv import srp, debug
import scapy.route
iface = b'eth0'
subnet_to_test = b'192.168.1.0/24'
#or:
subnet_to_test = b'192.168.1.*'
#IP/MAC discovery
pkt = Ether(dst=b'ff:ff:ff:ff:ff:ff') / ARP(psrc=b'0.0.0.0', pdst=subnet_to_test, hwdst=b'ff:ff:ff:ff:ff:ff')
responses = srp(pkt, timeout=1, retry=0, verbose=0, iface=iface)
for r in responses[0]:
found = r[1].getfieldval('psrc')
foundmac = r[1].getfieldval('hwsrc')
n = 29
conf.debug_match = 1
while n > -1:
net = Net("{}/{}".format(found, n))
my_src = net.choice()
while my_src in Net("{}/{}".format(found, n + 1)):
my_src = net.choice()
pkt = Ether(dst=foundmac) / IP(dst=found, src=my_src) / ICMP(type=8)
resp = srp(pkt, timeout=1, retry=0, verbose=0, iface=iface, filter=b'ether dst FF:FF:FF:FF:FF:FF and arp')
received = [x for x in debug.recv if x.haslayer(ARP) and x.getfieldval('pdst') == my_src]
received.extend(x[1] for x in resp[0] if x[1].haslayer(ARP) and x[1].getfieldval('pdst') == my_src)
if len(received) == 0:
print("Found host: {}/{} on mac {}".format(found, n + 1, foundmac))
break
n -= 1