linux - 我可以使用静态 IP 检测已配置连接设备的网络和网络掩码吗

标签 linux networking tcp ping ifconfig

我正在运行具有有线网络接口(interface)的 Linux 设备。该接口(interface)的另一端插入另一个配置为使用某些静态 IP 地址和网络掩码的网络感知设备。因此,我们有一个非常简单的网络,仅由两个设备和一根电缆组成,甚至没有它们之间的交换机,什么都没有。

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

  1. 使用 ifconfig 等设置网络。
  2. 获取 IP 地址并启动我的程序,该程序使用该 IP 地址与 设备。

我知道我可以进行广播 ping 并获取电缆另一端设备的 IP 地址。这对我有用。但要激活网络并进行广播 ping,我需要知道网络地址和网络掩码。我当前的 bash 脚本看起来像

ifconfig 192.168.100.1 netmask 255.255.255.0 up
ping -b 192.168.100.255

设备响应。不幸的是,其中一些设备可能会因不可预测的网络和网络掩码而配置错误。有人能提出如何自动检索网络设置(网络库、网络掩码)的想法吗?即使是部分解决方案也会感激不尽。如果有帮助的话,我可以编译并安装一个自定义 C 工具。

最佳答案

对于第一部分,只要您能以某种方式限制范围,您就可以使用 nmap,根据您的评论,这已经应该为您提供您想要的主机:

sudo nmap -PR -sn 192.168.0-255.0-255 -e <interface-to-test>

这会基于 ARP 进行发现,如果成功,则会在之后进行额外的 ICMP ping 以确定 liveness 。在没有事件本地主机的范围内,我花了大约一秒钟的时间,在有 4 个事件主机的范围上花了 5 秒。因此,您甚至可以将其扩展到更大的范围,但不能扩展到完整的 IPv4 地址空间,除非您有一两天的时间。在这种情况下,我只需连接wireshark或tcpdump并等待免费的ARP。

编辑:为此,您必须使用要测试的子网中的 IP 配置“源计算机”。我以为它会在走出子网或未配置 ip 时使用 ARP 的 DAD 模式,但它只是不执行任何操作。我在为下面的算法编写的脚本中添加了一个更通用的版本,但它比简单地使用 nmap 获得此结果要慢一些。

检测配置的网络掩码有点棘手。但我认为这个过程是可行的,主要思想是主机将向其子网中的主机发送 ARP 请求,而对于不在其子网中的主机则不发送任何内容或对其 default-gw 发出 ARP 请求。

  1. 从倒数第二个子网开始 N=29
  2. 从由主机 IP 和子网掩码 N 构成的子网中选择一个 IP X。确保选择的 IP 不是主机的 IP,也不是网络/广播的 IP。另请确保此 IP 不属于由主机 IP 和掩码 N+1 形成的子网的一部分。
  3. 使用源 X 对其他主机执行 Ping 操作(您不关心它是否应答,只需发出请求即可)
  4. 如果您看到 X 的 ARP 请求,请将 N 减一。返回2
  5. 如果您没有看到 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 

关于linux - 我可以使用静态 IP 检测已配置连接设备的网络和网络掩码吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14103535/

相关文章:

c++ - Tcp Client 发送的数据接收速度非常慢

linux - 使用python脚本查找和删除文件

linux - 如何为 Linux 机器添加网络适配器?

linux - 群 - 脚本已完成但仍被锁定

networking - Docker守护程序无法初始化网络 Controller

C - 如何通过包含多个 0 字节的 UDP 发送字节字符数组?

c# - IBM MQSeries 从 .NET 访问问题

docker - Docker TCP与主机端口

linux - 解释来自/proc/[id]/mountstats 或/proc/self/mountstats 的数据

c - 使用指针在 c 中打印当前工作目录