是否可以使用静态IP检测已配置连接设备的网络和网络掩码

时间:2012-12-31 15:49:11

标签: linux networking tcp ping ifconfig

我正在运行带有线网络接口的Linux设备。此接口的另一端插入另一个网络感知设备,该设备配置为使用某些静态IP地址和一些网络掩码。因此,我们有一个非常简单的网络,包括两个设备和一个电缆,甚至没有它们之间的切换,没有。

任务是开始与另一台设备交谈,我们需要

  1. 使用ifconfig等建立网络。
  2. 获取IP地址并启动使用此IP地址的程序 设备
  3. 我知道我可以进行广播ping,并在电缆的另一端获取设备的IP地址。这适合我。但是要激活网络并进行广播ping,我需要知道网络地址和网络掩码。我当前的bash脚本看起来像

    ifconfig 192.168.100.1 netmask 255.255.255.0 up
    ping -b 192.168.100.255
    

    设备响应。不幸的是,其中一些设备可能配置错误,网络和网络掩码不可预测。任何人都可以提出如何自动检索网络设置(netbase,netmask)的想法吗?即使是部分解决方案,也要感恩。如果有帮助,可以编译和安装自定义C工具。

2 个答案:

答案 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请求。

  1. 从第二个到最小的子网N=29开始。
  2. 从主机IP和子网掩码X形成的子网中选择一个IP N。确保选择的IP不是主机的IP而不是网络/广播。还要确保此IP不是主机IP和掩码N+1形成的子网的一部分。
  3. 使用来源X ping其他主机(您不关心它是否应答,只是发出请求)
  4. 如果您看到X的ARP请求,请将N减少一个。回到2
  5. 如果您没有看到X的ARP请求,则N+1是搜索到的子网。
  6. 一个缺陷可能是一个过于雄心勃勃的网络堆栈实现可能会从传入的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

链接本地地址只能用于与同一物理或逻辑链路上的设备通信,因此,如果您确实希望此设备位于同一子网上,则必须手动配置该接口。