如何准确探测服务器类型 | 网站服务器类型识别技术解析

服务器类型探测工具

下面是一个完整的服务器类型探测工具,能够通过分析TCP/IP栈特征和HTTP响应头来识别服务器操作系统和Web服务器类型。

服务器类型探测

import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
import socket
import requests
import re
from urllib.parse import urlparse
class ServerDetector:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("服务器类型探测工具")
        self.window.geometry("800x600")
        self.window.resizable(True, True)
        # 设置主题
        self.window.tk.call("source", "azure.tcl")
        self.window.tk.call("set_theme", "dark")
        self.create_widgets()
    def create_widgets(self):
        # 创建主框架
        main_frame = ttk.Frame(self.window)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        # 创建输入区域
        input_frame = ttk.LabelFrame(main_frame, text="目标服务器")
        input_frame.pack(fill=tk.X, pady=10)
        ttk.Label(input_frame, text="URL或IP地址:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
        self.target_entry = ttk.Entry(input_frame, width=50)
        self.target_entry.grid(row=0, column=1, padx=5, pady=5, sticky="we")
        self.target_entry.insert(0, "https://example.com")
        # 端口选择
        ttk.Label(input_frame, text="端口:").grid(row=0, column=2, padx=5, pady=5, sticky="w")
        self.port_var = tk.StringVar(value="自动检测")
        port_options = ["自动检测", "80 (HTTP)", "443 (HTTPS)", "其他"]
        self.port_combobox = ttk.Combobox(input_frame, textvariable=self.port_var, values=port_options, width=12)
        self.port_combobox.grid(row=0, column=3, padx=5, pady=5)
        # 自定义端口输入
        self.custom_port_frame = ttk.Frame(input_frame)
        self.custom_port_label = ttk.Label(self.custom_port_frame, text="自定义端口:")
        self.custom_port_entry = ttk.Entry(self.custom_port_frame, width=8)
        self.custom_port_label.pack(side=tk.LEFT, padx=(0, 5))
        self.custom_port_entry.pack(side=tk.LEFT)
        # 绑定端口选择事件
        self.port_combobox.bind("<<ComboboxSelected>>", self.on_port_select)
        # 检测按钮
        detect_button = ttk.Button(input_frame, text="开始探测", command=self.detect_server)
        detect_button.grid(row=0, column=4, padx=10, pady=5)
        # 创建结果显示区域
        results_frame = ttk.LabelFrame(main_frame, text="探测结果")
        results_frame.pack(fill=tk.BOTH, expand=True, pady=10)
        # 结果标签
        results_grid = ttk.Frame(results_frame)
        results_grid.pack(fill=tk.X, padx=10, pady=10)
        ttk.Label(results_grid, text="操作系统:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
        self.os_label = ttk.Label(results_grid, text="待探测...", foreground="gray")
        self.os_label.grid(row=0, column=1, padx=5, pady=5, sticky="w")
        ttk.Label(results_grid, text="Web服务器:").grid(row=1, column=0, padx=5, pady=5, sticky="w")
        self.webserver_label = ttk.Label(results_grid, text="待探测...", foreground="gray")
        self.webserver_label.grid(row=1, column=1, padx=5, pady=5, sticky="w")
        ttk.Label(results_grid, text="后端技术:").grid(row=2, column=0, padx=5, pady=5, sticky="w")
        self.tech_label = ttk.Label(results_grid, text="待探测...", foreground="gray")
        self.tech_label.grid(row=2, column=1, padx=5, pady=5, sticky="w")
        ttk.Label(results_grid, text="开放端口:").grid(row=3, column=0, padx=5, pady=5, sticky="w")
        self.ports_label = ttk.Label(results_grid, text="待探测...", foreground="gray")
        self.ports_label.grid(row=3, column=1, padx=5, pady=5, sticky="w")
        # 详细信息区域
        details_frame = ttk.LabelFrame(results_frame, text="详细信息")
        details_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        self.details_text = scrolledtext.ScrolledText(details_frame, wrap=tk.WORD, height=10)
        self.details_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        self.details_text.config(state=tk.DISABLED)
        # 状态栏
        self.status_var = tk.StringVar(value="就绪")
        status_bar = ttk.Label(self.window, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)
    def on_port_select(self, event):
        if self.port_var.get() == "其他":
            self.custom_port_frame.grid(row=0, column=4, padx=5, pady=5)
        else:
            self.custom_port_frame.grid_forget()
    def update_status(self, message):
        self.status_var.set(message)
        self.window.update()
    def detect_server(self):
        target = self.target_entry.get().strip()
        if not target:
            messagebox.showerror("错误", "请输入目标URL或IP地址")
            return
        # 确定端口
        port_option = self.port_var.get()
        if port_option == "自动检测":
            port = None
        elif port_option == "80 (HTTP)":
            port = 80
        elif port_option == "443 (HTTPS)":
            port = 443
        elif port_option == "其他":
            try:
                port = int(self.custom_port_entry.get().strip())
            except ValueError:
                messagebox.showerror("错误", "请输入有效的端口号")
                return
        else:
            port = 80
        # 重置UI
        self.os_label.config(text="探测中...", foreground="orange")
        self.webserver_label.config(text="探测中...", foreground="orange")
        self.tech_label.config(text="探测中...", foreground="orange")
        self.ports_label.config(text="探测中...", foreground="orange")
        self.details_text.config(state=tk.NORMAL)
        self.details_text.delete(1.0, tk.END)
        self.details_text.insert(tk.END, "开始服务器探测...n")
        self.details_text.config(state=tk.DISABLED)
        self.update_status(f"正在探测服务器: {target}")
        # 解析目标
        try:
            parsed_url = urlparse(target)
            if not parsed_url.scheme:
                # 如果URL没有协议,添加http://
                target = "http://" + target
                parsed_url = urlparse(target)
            host = parsed_url.hostname
            if not host:
                raise ValueError("无效的URL")
            # 获取IP地址
            self.update_status(f"解析域名: {host}")
            ip_address = socket.gethostbyname(host)
            self.details_text.config(state=tk.NORMAL)
            self.details_text.insert(tk.END, f"解析域名: {host} -> {ip_address}n")
            self.details_text.config(state=tk.DISABLED)
            # 探测操作系统
            self.update_status("分析操作系统...")
            os_info = self.detect_os(ip_address, port)
            self.os_label.config(text=os_info, foreground="#4CAF50")
            self.details_text.config(state=tk.NORMAL)
            self.details_text.insert(tk.END, f"操作系统: {os_info}n")
            self.details_text.config(state=tk.DISABLED)
            # 探测Web服务器信息
            self.update_status("分析Web服务器...")
            web_info, tech_info = self.detect_web_server(target)
            self.webserver_label.config(text=web_info, foreground="#4CAF50")
            self.tech_label.config(text=tech_info, foreground="#4CAF50")
            self.details_text.config(state=tk.NORMAL)
            self.details_text.insert(tk.END, f"Web服务器: {web_info}n")
            self.details_text.insert(tk.END, f"后端技术: {tech_info}n")
            self.details_text.config(state=tk.DISABLED)
            # 探测常见端口
            self.update_status("扫描常见端口...")
            open_ports = self.scan_common_ports(ip_address)
            self.ports_label.config(text=", ".join(map(str, open_ports)) if open_ports else "未检测到开放端口", 
                                    foreground="#4CAF50")
            self.details_text.config(state=tk.NORMAL)
            self.details_text.insert(tk.END, f"开放端口: {open_ports}n")
            self.details_text.config(state=tk.DISABLED)
            self.update_status("探测完成")
        except Exception as e:
            messagebox.showerror("错误", f"探测过程中发生错误: {str(e)}")
            self.update_status("发生错误")
            self.os_label.config(text="错误", foreground="red")
            self.webserver_label.config(text="错误", foreground="red")
            self.tech_label.config(text="错误", foreground="red")
            self.ports_label.config(text="错误", foreground="red")
    def detect_os(self, ip, port):
        """通过TCP/IP栈特征探测操作系统"""
        try:
            # 创建TCP套接字
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(3)
            # 尝试连接
            if port is None:
                # 尝试80和443
                for p in [80, 443]:
                    try:
                        s.connect((ip, p))
                        port = p
                        break
                    except:
                        continue
                if port is None:
                    raise ConnectionError("无法连接到80或443端口")
            else:
                s.connect((ip, port))
            # 获取TTL值
            ttl = s.getsockopt(socket.IPPROTO_IP, socket.IP_TTL)
            # 分析TTL值
            if ttl <= 64:
                return "Linux/Unix系统"
            elif ttl <= 128:
                return "Windows系统"
            else:
                return f"未知操作系统 (TTL: {ttl})"
        except socket.timeout:
            return "连接超时 - 无法确定操作系统"
        except ConnectionRefusedError:
            return "连接被拒绝 - 无法确定操作系统"
        except Exception as e:
            return f"错误: {str(e)}"
    def detect_web_server(self, url):
        """通过HTTP头探测Web服务器和后台技术"""
        try:
            # 发送HEAD请求
            self.details_text.config(state=tk.NORMAL)
            self.details_text.insert(tk.END, f"发送请求到: {url}n")
            self.details_text.config(state=tk.DISABLED)
            response = requests.head(url, timeout=5, allow_redirects=True)
            # 分析响应头
            server_header = response.headers.get('Server', '未识别')
            powered_by = response.headers.get('X-Powered-By', '未识别')
            # 识别常见Web服务器
            if 'Apache' in server_header:
                server_type = "Apache"
            elif 'nginx' in server_header:
                server_type = "Nginx"
            elif 'Microsoft-IIS' in server_header:
                server_type = "Microsoft IIS"
            elif 'LiteSpeed' in server_header:
                server_type = "LiteSpeed"
            else:
                server_type = server_header
            # 识别后台技术
            if 'PHP' in powered_by:
                backend = "PHP"
            elif 'ASP.NET' in powered_by or 'X-AspNet-Version' in response.headers:
                backend = "ASP.NET"
            elif 'Node.js' in powered_by:
                backend = "Node.js"
            elif 'Python' in powered_by:
                backend = "Python"
            elif 'Java' in powered_by:
                backend = "Java"
            else:
                backend = powered_by
            # 记录详细信息
            self.details_text.config(state=tk.NORMAL)
            self.details_text.insert(tk.END, f"HTTP响应头:n")
            for header, value in response.headers.items():
                self.details_text.insert(tk.END, f"  {header}: {value}n")
            self.details_text.config(state=tk.DISABLED)
            return server_type, backend
        except requests.exceptions.SSLError:
            # 尝试使用HTTP
            if url.startswith('https://'):
                http_url = url.replace('https://', 'http://', 1)
                self.details_text.config(state=tk.NORMAL)
                self.details_text.insert(tk.END, f"SSL错误, 尝试使用HTTP: {http_url}n")
                self.details_text.config(state=tk.DISABLED)
                return self.detect_web_server(http_url)
            return "SSL错误", "无法确定"
        except requests.exceptions.RequestException as e:
            return f"HTTP错误: {str(e)}", "无法确定"
    def scan_common_ports(self, ip):
        """扫描常见端口"""
        common_ports = [21, 22, 23, 25, 53, 80, 110, 143, 443, 587, 993, 995, 3306, 3389]
        open_ports = []
        for port in common_ports:
            try:
                self.update_status(f"扫描端口: {port}")
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(0.5)
                result = sock.connect_ex((ip, port))
                if result == 0:
                    open_ports.append(port)
                    self.details_text.config(state=tk.NORMAL)
                    self.details_text.insert(tk.END, f"端口 {port} 开放n")
                    self.details_text.config(state=tk.DISABLED)
                sock.close()
            except:
                pass
        return open_ports
    def run(self):
        self.window.mainloop()
if __name__ == "__main__":
    app = ServerDetector()
    app.run()

功能说明

这个服务器类型探测工具具有以下功能:

  1. 操作系统探测

    • 通过分析TCP/IP栈特征(如TTL值)识别目标服务器的操作系统类型
    • 支持Linux/Unix和Windows系统的识别
  2. Web服务器识别

    服务器类型探测

    • 通过分析HTTP响应头中的”Server”字段识别Web服务器类型
    • 支持识别Apache、Nginx、IIS等常见Web服务器
  3. 后端技术识别

    • 通过分析”X-Powered-By”等HTTP头识别后端技术
    • 支持识别PHP、ASP.NET、Node.js等后台技术
  4. 常见端口扫描

    • 扫描21个常见端口(如HTTP、HTTPS、SSH、FTP等)
    • 显示开放的端口列表
  5. 详细探测信息

    服务器类型探测

    • 显示完整的HTTP响应头
    • 显示域名解析结果
    • 显示探测过程中的详细日志

使用方法

  1. 在”目标服务器”输入框中输入URL或IP地址
  2. 选择端口(默认自动检测80和443端口)
  3. 点击”开始探测”按钮
  4. 查看探测结果和详细信息

注意事项

  • 端口扫描功能仅扫描常见端口,不会进行全端口扫描
  • 某些服务器可能隐藏或修改HTTP头信息,导致探测结果不准确
  • 操作系统探测基于TTL值分析,结果仅供参考
  • 请确保您有权限探测目标服务器,未经授权的探测可能违反法律或服务条款

这个工具提供了一个直观的图形界面,使用深色主题,并在探测过程中显示详细的状态信息,使用户能够清晰地了解探测进度和结果。

图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/288651.html

(0)
上一篇 2026年2月9日 02:11
下一篇 2026年2月9日 02:15

相关推荐

  • 监控管理服务器在企业管理中扮演何种关键角色?其具体作用有哪些?

    监控管理服务器的作用随着信息技术的飞速发展,企业对数据安全和系统稳定性的要求越来越高,监控管理服务器作为企业信息化建设的重要组成部分,承担着保障企业信息系统安全、稳定运行的重要职责,本文将详细介绍监控管理服务器的作用,帮助读者更好地理解其在企业信息化建设中的重要性,监控管理服务器的作用实时监控监控管理服务器能够……

    2025年10月31日
    01040
  • 监控摄像头智能升级,智能监控摄像头如何实现高效应用?

    随着科技的不断发展,监控摄像头已经从传统的被动监控工具转变为智能监控摄像头,它们在安防、交通、家庭等领域发挥着越来越重要的作用,本文将为您详细介绍智能监控摄像头的特点、应用场景以及选购技巧,智能监控摄像头的特点高清画质智能监控摄像头采用高清摄像头,画面清晰,细节丰富,便于用户观察监控场景,智能识别智能监控摄像头……

    2025年11月1日
    0640
  • 如何配置云计算服务层次?选择合适层次时需注意哪些关键要点?

    配置云计算服务层次云计算服务层次是构建云架构的核心框架,分为基础架构即服务(IaaS)、平台即服务(PaaS)、软件即服务(SaaS)三层,不同层次提供不同粒度的资源和服务,配置时需结合业务需求、技术栈和成本预算,遵循分层规划、安全优先、动态优化的原则,以下是具体配置要点及最佳实践,IaaS(基础架构即服务)配……

    2026年1月7日
    0720
    • 服务器间歇性无响应是什么原因?如何排查解决?

      根源分析、排查逻辑与解决方案服务器间歇性无响应是IT运维中常见的复杂问题,指服务器在特定场景下(如高并发时段、特定操作触发时)出现短暂无响应、延迟或服务中断,而非持续性的宕机,这类问题对业务连续性、用户体验和系统稳定性构成直接威胁,需结合多维度因素深入排查与解决,常见原因分析:从硬件到软件的多维溯源服务器间歇性……

      2026年1月10日
      020
  • 服务器系统升级更换是否可行?企业级服务器更换流程详解及常见问题

    服务器系统能换吗?专业解析与实操指南服务器系统是支撑企业业务、个人应用的核心基础设施,其稳定性与性能直接影响业务连续性,服务器系统能否更换?本文将从专业角度深入解析服务器系统更换的可行性、流程、注意事项及实践案例,结合酷番云云产品的实际应用,为您全面解答,服务器系统的类型与更换可行性概述服务器系统分为物理服务器……

    2026年1月20日
    0460

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注