- 所需库安装
- 需要安装
scapy
库用于抓包操作,如果未安装,可以使用pip install scapy
命令安装。另外,还需要re
库(Python 标准库,无需额外安装)用于正则表达式匹配。
- 需要安装
- 代码实现思路
- 利用
scapy
在指定的 5000 端口进行抓包操作。 - 从抓到的包中提取源 IP 地址。
- 使用提供的
is_internal_ip
函数根据常见内网网段判断 IP 是否为内网地址,同时将 IP 地址存入字典,根据其在字典中的唯一性再次判断是否为内网地址。
- 利用
- 完整代码示例
python
import re
from scapy.all import srp, Ether, ARP
def is_internal_ip(ip):
internal_ip_ranges = [
re.compile('^10\.'),
re.compile('^172\.(1[6 - 9]|2[0 - 9]|3[0 - 1])\.'),
re.compile('^192\.168\.')
]
for range in internal_ip_ranges:
if range.match(ip):
return True
return False
def check_internal_network():
ip_dict = {}
packets = srp(Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(pdst='0.0.0.0/0', sport = 5000, dport=5000), timeout = 3, verbose = 0)[0]
for packet in packets:
ip = packet[1].psrc
if ip not in ip_dict:
ip_dict[ip] = 1
else:
ip_dict[ip]+=1
if is_internal_ip(ip):
print(f"{ip} 是内网地址(通过常见网段判断)")
elif ip_dict[ip] == 1:
print(f"{ip} 是内网地址(通过IP唯一性判断)")
else:
print(f"{ip} 不是内网地址")
if __name__ == '__main__':
check_internal_network()
- 代码解释
- 在
is_internal_ip
函数中:- 定义了一个包含正则表达式对象的列表
internal_ip_ranges
,这些正则表达式分别用于匹配常见的内网网段。 - 遍历这个列表,对于每个正则表达式,如果能匹配传入的 IP 地址
ip
,则返回True
,表示该 IP 是内网地址;如果遍历完列表都没有匹配成功,则返回False
。
- 定义了一个包含正则表达式对象的列表
- 在
check_internal_network
函数中:- 创建了一个空字典
ip_dict
,用于记录每个 IP 地址出现的次数。 - 使用
scapy
的srp
函数进行抓包操作,构造了一个以太网帧(目的 MAC 地址为广播地址)和 ARP 请求(目标 IP 为0.0.0.0/0
,源端口和目的端口为 5000),设置超时时间为 3 秒且不显示详细信息,然后获取抓到的包。 - 对于每个抓到的包,获取其源 IP 地址
ip
。如果ip
不在ip_dict
中,将其添加到字典中并设置计数为 1;如果已经在字典中,则将计数加 1。 - 接着调用
is_internal_ip
函数判断ip
是否为内网地址,如果是则按照相应的判断方式打印结果;如果不是通过常见网段判断为内网地址,但在字典中的计数为 1(即唯一性判断),也认为是内网地址并打印结果;否则,认为不是内网地址并打印结果。
- 创建了一个空字典
- 在
if __name__ == '__main__'
部分调用check_internal_network
函数开始整个检查过程。
- 在