为何指定端口范围时Python-nmap的all_protocols()无返回结果?
Python-nmap无法列出协议问题排查与解决
问题现象
扫描本地回环地址127.0.0.1的25-200端口范围后,调用all_protocols()返回空列表:
import nmap nmap_path = [r"C:\Program Files (x86)\Nmap\nmap.exe"] nmScan = nmap.PortScanner(nmap_search_path=nmap_path) nmScan.scan('127.0.0.1', '25-200') # 扫描结果输出 # {'nmap': {'command_line': '"C:\\\\Program Files (x86)\\\\Nmap\\\\nmap.exe" -oX - -p 25-200 -sV 127.0.0.1', 'scaninfo': {'tcp': {'method': 'syn', 'services': '25-200'}}, 'scanstats': {'timestr': 'Mon Nov 6 11:46:34 2023', 'elapsed': '37.95', 'uphosts': '1', 'downhosts': '0', 'totalhosts': '1'}}, 'scan': {'127.0.0.1': {'hostnames': [{'name': 'localhost', 'type': 'PTR'}], 'addresses': {'ipv4': '127.0.0.1'}, 'vendor': {}, 'status': {'state': 'up', 'reason': 'localhost-response'}}}}
nmScan['127.0.0.1'].all_protocols() # 输出:[]
但仅扫描80端口时,all_protocols()正常返回['tcp']:
import nmap nmap_path = [r"C:\Program Files (x86)\Nmap\nmap.exe"] nmScan = nmap.PortScanner(nmap_search_path=nmap_path) nmScan.scan('127.0.0.1', '80-80') # 扫描结果输出 # {'nmap': {'command_line': '"C:\\\\Program Files (x86)\\\\Nmap\\\\nmap.exe" -oX - -p 80-80 -sV 127.0.0.1', 'scaninfo': {'tcp': {'method': 'syn', 'services': '80'}}, 'scanstats': {'timestr': 'Mon Nov 6 11:39:45 2023', 'elapsed': '2.78', 'uphosts': '1', 'downhosts': '0', 'totalhosts': '1'}}, 'scan': {'127.0.0.1': {'hostnames': [{'name': 'localhost', 'type': 'PTR'}], 'addresses': {'ipv4': '127.0.0.1'}, 'vendor': {}, 'status': {'state': 'up', 'reason': 'localhost-response'}, 'tcp': {80: {'state': 'filtered', 'reason': 'no-response', 'name': 'http', 'product': '', 'version': '', 'extrainfo': '', 'conf': '3', 'cpe': ''}}}}}
nmScan['127.0.0.1'].all_protocols() # 输出:['tcp']
原因分析
Python-nmap的all_protocols()方法仅返回扫描结果中包含端口状态信息的协议。当扫描25-200端口范围时,该范围内所有端口未被检测到开放、过滤等可记录的状态(nmap未返回这些端口的详细状态数据),导致主机条目里没有tcp键,因此all_protocols()返回空列表。而扫描80端口时,nmap返回了该端口的filtered状态,主机条目里存在tcp键,方法就能正确返回协议列表。
解决方案
1. 强制指定扫描协议并调整扫描参数
在scan()方法中通过arguments明确指定扫描协议,同时添加参数获取更详细的端口状态:
import nmap nmap_path = [r"C:\Program Files (x86)\Nmap\nmap.exe"] nmScan = nmap.PortScanner(nmap_search_path=nmap_path) # 指定TCP扫描模式,添加-v参数启用 verbose 输出 nmScan.scan('127.0.0.1', '25-200', arguments='-sT -v') print(nmScan['127.0.0.1'].all_protocols())
2. 从scaninfo中直接提取扫描协议
如果不需要依赖端口状态信息,可直接从scaninfo中获取已扫描的协议类型,该字段不受端口状态影响:
# 从scaninfo字典中提取协议列表 protocols = list(nmScan.scaninfo().keys()) print(protocols) # 输出: ['tcp']
内容的提问来源于stack exchange,提问作者engrtech
相关产品推荐
相关产品推荐

