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

如何使用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成熟的服务版本识别能力:

  1. 先安装依赖:
pip install python-nmap
  1. 示例代码:
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 08:24:55