如何使用Python通过端口获取服务版本信息
如何通过端口获取服务版本信息
我已经掌握端口扫描和服务识别方法,但不知道怎么获取服务版本。比如nmap能得到这样的结果:
PORT STATE SERVICE VERSION
80/tcp open http Google httpd 2.0 (GFE)
我的Python代码目前只能识别服务名,输出如下:
Port 80 is open http
Port 443 is open https
代码片段:
for port in range(1,65535): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) socket.setdefaulttimeout(1) # returns an error indicator result = s.connect_ex((target,port)) if result ==0: #print ("Port: %s => service name: %s" %(port, socket.getservbyport(port, protocolname))) service = socket.getservbyport(port, protocolname) if(service): print("Port {} is open {} ".format(port,service)) else: print("Port {} is open ".format(port)) s.close()
请指导如何获取服务版本信息。
解决方案
方法1:手动抓取服务Banner
很多服务在建立TCP连接后会返回包含版本信息的Banner,你可以在连接成功后尝试读取这些数据,但不同服务的交互规则不同:
import socket target = "目标IP" protocolname = "tcp" for port in range(1, 65535): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) socket.setdefaulttimeout(1) result = s.connect_ex((target, port)) if result == 0: service = socket.getservbyport(port, protocolname) version = "Unknown" # 尝试读取Banner,不同服务处理逻辑不同 try: if service == "http": # HTTP服务需要发送请求才会返回版本头 s.send(b"HEAD / HTTP/1.1\r\nHost: " + target.encode() + b"\r\n\r\n") banner = s.recv(1024).decode() for line in banner.split("\r\n"): if line.lower().startswith("server:"): version = line.split(": ")[1] break elif service in ["ftp", "ssh"]: # FTP、SSH这类服务直接返回Banner banner = s.recv(1024).decode().strip() if banner: version = banner except Exception: pass print(f"Port {port} is open {service} | Version: {version}") s.close()
局限:这种方法兼容性差,部分服务会隐藏Banner,或者需要特定请求格式才能触发版本返回。
方法2:使用python-nmap调用Nmap版本扫描
这是最可靠的方案,直接复用Nmap成熟的服务版本识别能力:
- 先安装依赖:
pip install python-nmap
- 示例代码:
import nmap target = "目标IP" scanner = nmap.PortScanner() # -sV启用版本扫描,-p指定端口范围,-T4平衡扫描速度和准确性 scanner.scan(hosts=target, arguments='-p 1-65535 -sV -T4') for host in scanner.all_hosts(): print(f"Host: {host}") for proto in scanner[host].all_protocols(): print(f"Protocol: {proto}") ports = scanner[host][proto].keys() for port in ports: service_info = scanner[host][proto][port] print(f"Port: {port} | Service: {service_info['name']} | Version: {service_info['version']}")
优势:支持绝大多数常见服务的版本识别,结果和Nmap原生输出一致,无需自己处理不同服务的交互逻辑。
内容的提问来源于stack exchange,提问作者PythonUser
相关产品推荐
相关产品推荐

