Python扫描网络IP地址和mac
问题描述:
ip a outputscreenshot我想创建一个脚本,扫描局域网,并获得所有使用Python的机器的IP地址和MAC地址。下面的脚本执行此操作,但是它会将列表打印两次?这怎么可能实现,或者如何改变下面的脚本来打印一次列表(作为一个字典,其中ip地址是键,mac是值)?Python扫描网络IP地址和mac
from __future__ import absolute_import, division, print_function
import logging
import scapy.config
import scapy.layers.l2
import scapy.route
import socket
import math
import errno
logging.basicConfig(format='%(asctime)s %(levelname)-5s %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=logging.DEBUG)
logger = logging.getLogger(__name__)
def long2net(arg):
if (arg <= 0 or arg >= 0xFFFFFFFF):
raise ValueError("illegal netmask value", hex(arg))
return 32 - int(round(math.log(0xFFFFFFFF - arg, 2)))
def to_CIDR_notation(bytes_network, bytes_netmask):
network = scapy.utils.ltoa(bytes_network)
netmask = long2net(bytes_netmask)
net = "%s/%s" % (network, netmask)
if netmask < 16:
logger.warn("%s is too big. skipping" % net)
return None
return net
def scan_and_print_neighbors(net, interface, timeout=1):
logger.info("arping %s on %s" % (net, interface))
try:
ans, unans = scapy.layers.l2.arping(net, iface=interface, timeout=timeout, verbose=True)
for s, r in ans.res:
line = r.sprintf("%Ether.src% %ARP.psrc%")
try:
hostname = socket.gethostbyaddr(r.psrc)
line += " " + hostname[0]
except socket.herror:
# failed to resolve
pass
logger.info(line)
except socket.error as e:
if e.errno == errno.EPERM: # Operation not permitted
logger.error("%s. Did you run as root?", e.strerror)
else:
raise
if __name__ == "__main__":
for network, netmask, _, interface, address in scapy.config.conf.route.routes:
# skip loopback network and default gw
if network == 0 or interface == 'lo' or address == '127.0.0.1' or address == '0.0.0.0':
continue
if netmask <= 0 or netmask == 0xFFFFFFFF:
continue
net = to_CIDR_notation(network, netmask)
if interface != scapy.config.conf.iface:
# see http://trac.secdev.org/scapy/ticket/537
logger.warn("skipping %s because scapy currently doesn't support arping on non-primary network interfaces", net)
continue
if net:
scan_and_print_neighbors(net, interface)
答
您是否试过将verbose
设置为False
?
ans, unans = scapy.layers.l2.arping(net, iface=interface, timeout=timeout, verbose=False)
除了你scapy.layers.l2.arping(
设置verbose=False
, 导入conf
模块:
from scapy.all import conf
仅低于你的if __name__ == "__main__":
行添加conf.verb=0
:
if __name__ == "__main__":
conf.verb=0
for network, netmask, _, interface, address in scapy.config.conf.route.routes:
# skip loopback network and default gw
if network == 0 or interface == 'lo' or address == '127.0.0.1' or address == '0.0.0.0':
continue
编辑:我认为你的脚本正在循环对于您的/proc/net/route
中定义的每个“路线”,尚未明确过滤(即, )我的猜测是,如果你在哪里执行route -n
,你可能会发现有2条路径在那里有某种方式具有相同的网络和接口值,但其他的东西与网络掩码或网关不同。
不管怎么说,通过这种方法得到通过的方法是在您致电scan_and_print_neighbors(net, interface)
后添加break
以退出for-loop。
例如:
if __name__ == "__main__":
for network, netmask, _, interface, address in scapy.config.conf.route.routes:
# skip loopback network and default gw
if network == 0 or interface == 'lo' or address == '127.0.0.1' or address == '0.0.0.0':
continue
if netmask <= 0 or netmask == 0xFFFFFFFF:
continue
net = to_CIDR_notation(network, netmask)
if interface != scapy.config.conf.iface:
# see http://trac.secdev.org/scapy/ticket/537
logger.warn("skipping %s because scapy currently doesn't support arping on non-primary network interfaces", net)
continue
if net:
scan_and_print_neighbors(net, interface)
break
有,我有,它仍然打印列表两次? – bshah
更新了我的答案并在我的系统上进行了测试。现在它只打印你使用记录器声明的信息,而不是来自scapy模块本身的详细信息。 –
它仍然打印出两个列表。通过在scapy.layers.l2.arping中导入conf模块是什么意思? – bshah