You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中使用Scapy能否获取局域网内主机名?如何实现?

解答

首先明确结论:仅靠你当前使用的ARP扫描逻辑无法通过scapy获取主机名,ARP协议的作用只是完成IP地址和MAC地址的映射,报文本身不携带任何主机名相关字段。要实现类似Nmap的主机名获取能力,你可以结合以下两种可通过scapy实现的方案补充逻辑:

可选实现方案

方案1:反向DNS(PTR记录)查询

对扫描到的IP发送DNS反向查询请求,目标域名格式为[反向IP段].in-addr.arpa,如果目标设备配置了PTR记录就能返回对应的主机名,该方案通用性较强,对支持DNS的设备都适用。

方案2:NetBIOS名称查询

对扫描到的IP的137端口发送NetBIOS名称查询请求,几乎所有Windows系统主机默认开启该服务,大量IoT、Linux设备也会开启相关支持,是局域网下获取主机名成功率很高的方案,适合没有搭建内部DNS的局域网场景。

修改后带主机名获取的完整代码示例

import scapy.all as scapy

request = scapy.ARP()
broadcast = scapy.Ether()
broadcast.dst = 'ff:ff:ff:ff:ff:ff'
available_networks = []

def get_hostname_by_ptr(ip):
    # 构造反向DNS查询包
    reversed_ip = '.'.join(reversed(ip.split('.')))
    dns_req = scapy.IP(dst="223.5.5.5")/scapy.UDP(dport=53)/scapy.DNS(rd=1, qd=scapy.DNSQR(qname=f"{reversed_ip}.in-addr.arpa", qtype="PTR"))
    try:
        resp = scapy.sr1(dns_req, timeout=1, verbose=0)
        if resp and resp.haslayer(scapy.DNS) and resp[scapy.DNS].ancount > 0:
            return resp[scapy.DNS].an.rdata.decode().strip('.')
    except:
        pass
    return None

def get_hostname_by_netbios(ip):
    # 构造NetBIOS查询包
    nbns_req = scapy.IP(dst=ip)/scapy.UDP(sport=137, dport=137)/scapy.NBNSQueryRequest(NAME_TRN_ID=12345, QUESTION_NAME="*")
    try:
        resp = scapy.sr1(nbns_req, timeout=1, verbose=0)
        if resp and resp.haslayer(scapy.NBNSQueryResponse):
            return resp[scapy.NBNSQueryResponse].NAME.decode().strip()
    except:
        pass
    return None

def IP_Scan(net_area, net_mask):
    available_networks.clear()
    request.pdst = f'{net_area}/{net_mask}'
    request_broadcast = broadcast / request
    clients = scapy.srp(request_broadcast, timeout=5, verbose=0)[0]
    for sent_ip, received_ip in clients:
        ip = received_ip.psrc
        # 优先取NetBIOS结果,再取PTR结果,都拿不到返回未知
        hostname = get_hostname_by_netbios(ip) or get_hostname_by_ptr(ip) or "未知"
        available_networks.append({'IP': ip, 'MAC': received_ip.hwsrc, '主机名': hostname})
    return available_networks

注意事项

  • 上述代码中反向DNS查询默认使用公共DNS,你可以替换为你当前局域网的网关DNS地址,提升PTR查询的成功率
  • 部分开启了防火墙的设备会拦截NetBIOS或DNS查询请求,这种场景下无法获取到主机名,和Nmap的扫描表现一致

内容的提问来源于stack exchange,提问作者Saizzou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 22:24:08