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

如何使用Python实现UDP端口开放状态检测?

问题原因分析

你原来的代码存在两个核心问题:

  • 普通SOCK_DGRAM类型的UDP套接字无法接收关联的ICMP错误报文,所以你在Wireshark能抓到的端口不可达报文,不会传递给普通UDP套接字,导致除了端口开放且主动返回响应的情况外,其余请求都会触发TimeoutError,你的逻辑错误地把所有超时都判定为端口开放,同时永远触发不到兜底的except分支。
  • 你尝试新增原始ICMP套接字的思路是对的,但缺少了ICMP报文解析、端口匹配的逻辑,也没有处理原始套接字的权限要求,所以无法得到正确结果。

可行实现方案

前置要求

运行使用原始套接字的代码需要满足权限要求:

  • Linux系统需要以root身份运行
  • Windows系统需要以管理员身份启动运行终端

完整代码实现

import socket
import struct

def udp_connection(ip, port, timeout=2):
    # 先创建UDP套接字发探测包
    udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp_sock.settimeout(timeout)
    # 创建原始ICMP套接字收错误报文
    icmp_sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
    icmp_sock.settimeout(timeout)
    
    try:
        # 发送UDP探测包
        udp_sock.sendto(b'test', (ip, port))
        # 先尝试收UDP响应,收到说明端口明确开放
        data, addr = udp_sock.recvfrom(1024)
        return f"[+] UDP Port Open: {port} 收到响应: {data}\n"
    except TimeoutError:
        # UDP收不到响应,尝试收ICMP报文判断
        try:
            icmp_data, addr = icmp_sock.recvfrom(1024)
            # 解析ICMP包头:IP头前20字节,之后是ICMP头
            icmp_header = icmp_data[20:28]
            icmp_type, icmp_code, _, _, _ = struct.unpack('!BBHHH', icmp_header)
            # ICMP类型3是目标不可达,代码3是端口不可达
            if icmp_type == 3 and icmp_code == 3:
                # 解析ICMP载荷里的原始UDP头,确认是对应我们探测的端口的报错
                original_udp_header = icmp_data[48:56]
                original_dst_port = struct.unpack('!H', original_udp_header[2:4])[0]
                if original_dst_port == port:
                    return f"[-] UDP Port Closed: {port} 收到端口不可达ICMP报文\n"
            # 其他ICMP报文或者端口不匹配,视为无明确关闭信号,判定为开放|过滤
            return f"[+] UDP Port Open|Filtered: {port} 无明确关闭响应\n"
        except TimeoutError:
            # 既收不到UDP响应也收不到ICMP报错,判定为开放|过滤
            return f"[+] UDP Port Open|Filtered: {port} 超时无响应\n"
    finally:
        udp_sock.close()
        icmp_sock.close()

注意事项

  • 不要直接把超时等同于端口开放,UDP端口无响应的情况有可能是被防火墙过滤,所以标注为Open|Filtered更严谨
  • 批量扫描的时候建议控制发包速率,避免被目标网络的安全设备拦截
  • 不同操作系统对原始套接字的处理存在细微差异,如果Windows下收不到ICMP报文,可以尝试将ICMP套接字绑定到0.0.0.0的任意端口。

内容的提问来源于stack exchange,提问作者Lima Victor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:06:06