我正在运行带有线网络接口的Linux设备。此接口的另一端插入另一个网络感知设备,该设备配置为使用某些静态IP地址和一些网络掩码。因此,我们有一个非常简单的网络,包括两个设备和一个电缆,甚至没有它们之间的切换,没有。
任务是开始与另一台设备交谈,我们需要
我知道我可以进行广播ping,并在电缆的另一端获取设备的IP地址。这适合我。但是要激活网络并进行广播ping,我需要知道网络地址和网络掩码。我当前的bash脚本看起来像
ifconfig 192.168.100.1 netmask 255.255.255.0 up
ping -b 192.168.100.255
设备响应。不幸的是,其中一些设备可能配置错误,网络和网络掩码不可预测。任何人都可以提出如何自动检索网络设置(netbase,netmask)的想法吗?即使是部分解决方案,也要感恩。如果有帮助,可以编译和安装自定义C工具。
答案 0 :(得分:3)
对于第一部分,您可以使用nmap,只要您可以以某种方式限制范围,根据您的评论,这已经应该为您提供所需的主机:
sudo nmap -PR -sn 192.168.0-255.0-255 -e <interface-to-test>
这可以基于ARP进行发现,如果成功,则会在之后成功获得额外的ICMP ping活动。这个让我在没有活动本地主机的范围和5个有4个活动主机的范围内花了大约一秒钟。所以你甚至可以将它扩展到更大的范围,但不是完整的IPv4地址空间,除非你有一两天。在那种情况下,我只是挂起wireshark或tcpdump并等待无偿的ARP。
编辑:为此,您必须使用要测试的子网中的IP配置“源计算机”。我假设它在离开子网时或者没有配置ip时会使用ARP的DAD模式,但它不会做任何事情。我在下面为算法编写的脚本中添加了一个更通用的版本,但它比使用nmap获得此结果要慢一些。
检测配置的网络掩码有点棘手。但我认为这个程序会起作用,主要的想法是主机会发送一个针对其子网中主机的ARP请求,而不是针对不在其子网中的主机的默认gw的ARP请求。
N=29
开始。X
形成的子网中选择一个IP N
。确保选择的IP不是主机的IP而不是网络/广播。还要确保此IP不是主机IP和掩码N+1
形成的子网的一部分。X
ping其他主机(您不关心它是否应答,只是发出请求)X
的ARP请求,请将N
减少一个。回到2 X
的ARP请求,则N+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
答案 1 :(得分:-1)
你所要求的是不可能的。
最初,您有一个没有IP地址的接口。因此,您发送的任何数据包都不知道在何处发送回复(因此ICMP或ARP请求将不起作用)。
由于发件人不知道如何访问此接口,您可以在接口上侦听任何广播ARP请求(使用tcpdump,wireshark等)。这将显示网络中正在解析的IP地址,但它没有给你网络掩码(因此也没有网络地址)。此外,它不仅为您提供直接连接的邻居的IP地址,它将为您提供所有在此广播域内发出的ARP请求(因此您可能会看到许多IP地址。)
现在,至于确定设备正在使用的网络掩码,在采用CIDR时是不可能的(前缀可以是/ 16和/ 32之间的任何地方,并且无法准确知道邻居是哪一个设备正在使用。)
话虽如此,您可能希望查看链接本地IPv4地址。在Linux上,有一个名为AVAHI的程序,在Windows上称为APIPA。两者都实现RFC 3927:http://tools.ietf.org/html/rfc3927
链接本地地址只能用于与同一物理或逻辑链路上的设备通信,因此,如果您确实希望此设备位于同一子网上,则必须手动配置该接口。