什么叫做门户网站大型门户网站的建设外包在本公司制作好还是
什么叫做门户网站,大型门户网站的建设外包在本公司制作好还是,学好网页设计与网站建设的意义,仿照一个国外的网站要多少钱目录
前言
ICMP 时间戳探测存活主机原理
基本工作原理
时间戳消息结构
探测逻辑
技术优势
代码设计思路
整体架构设计
请求发送流程
响应处理流程
当前代码的4层验证
是否可以省略IP验证#xff1f;
运行流程总结
代码分析
创建ICMP连接
构造数据包并发送
监…目录前言ICMP 时间戳探测存活主机原理基本工作原理时间戳消息结构探测逻辑技术优势代码设计思路整体架构设计请求发送流程响应处理流程当前代码的4层验证是否可以省略IP验证运行流程总结代码分析创建ICMP连接构造数据包并发送监听并分析响应输出结果源代码其它前言这里进行第二种常用的icmp探测方法通过发送时间戳请求进行探测下面我详细讲解一下。ICMP 时间戳探测存活主机原理基本工作原理ICMPInternet Control Message Protocol时间戳探测利用 ICMP 协议中的时间戳请求/回复机制ICMP 时间戳请求(Type 13)向目标主机发送包含当前时间戳的请求包ICMP 时间戳回复(Type 14)存活的主机会回复包含三个时间戳的响应包时间戳消息结构时间戳消息体包含三个关键时间戳Originate Timestamp请求发起时间由发送方填充Receive Timestamp目标接收时间由接收方填充Transmit Timestamp回复发送时间由接收方填充探测逻辑发送ICMP时间戳请求(Type 13) → 目标主机 → 接收ICMP时间戳回复(Type 14) ↓ ↓ 设置唯一标识符 验证标识符匹配 记录发送时间 提取时间戳信息 等待响应 判断主机存活状态技术优势绕过简单过滤某些网络可能允许 ICMP 时间戳而禁止 ICMP Echo提供额外信息可以获得网络延迟和时间同步信息协议层探测在网络层工作不依赖传输层端口代码设计思路整体架构设计基于并发生产者-消费者模型主线程 ↓ 生成扫描任务 → 协程池(20个并发) → 发送ICMP时间戳请求 ↓ ↓ 等待所有任务完成 接收并解析响应 ↓ ↓ 汇总结果显示 更新存活主机列表请求发送流程1. 创建原始ICMP套接字 2. 生成唯一标识符(PID 序列号) 3. 构造时间戳请求数据 4. 序列化ICMP消息 5. 发送到目标IP响应处理流程1. 设置读取超时等待响应 2. 验证响应来源IP匹配 3. 解析ICMP消息类型(Type 14) 4. 提取并验证标识符匹配 5. 记录存活主机信息当前代码的4层验证IP地址匹配sourceAddr.String() ! Ip消息类型验证rm.Type ! ipv4.ICMPTypeTimestampReply数据长度验证len(responseData) 16ID/Seq匹配responseID pid responseSeq uint16(seq)是否可以省略IP验证可以省略原因如下技术层面pid是进程ID的低16位全局唯一性很高seq是递增序列号在短时间内重复概率极低两者组合的碰撞概率几乎为零运行流程总结初始化阶段准备目标列表初始化数据结构并发探测阶段启动多个协程并发发送时间戳请求响应处理阶段异步接收并验证响应数据结果汇总阶段收集所有探测结果并输出统计信息这种设计既保证了扫描效率又确保了程序的稳定性和准确性能够有效地发现网络中响应 ICMP 时间戳请求的存活主机。代码分析创建ICMP连接// 创建ICMP连接 conn, err : icmp.ListenPacket(ip4:icmp, 0.0.0.0) if err ! nil { return } defer conn.Close()构造数据包并发送// 生成唯一ID和序列号 pid : uint16(os.Getpid() 0xffff) currentTime : uint32(time.Now().UnixNano() / 1e6) // 毫秒时间戳 // 构造时间戳请求数据 (20字节) timestampData : make([]byte, 20) binary.BigEndian.PutUint16(timestampData[0:2], pid) // ID (2字节) binary.BigEndian.PutUint16(timestampData[2:4], uint16(seq)) // Seq (2字节) binary.BigEndian.PutUint32(timestampData[4:8], currentTime) // Originate (4字节) binary.BigEndian.PutUint32(timestampData[8:12], 0) // Receive (4字节) binary.BigEndian.PutUint32(timestampData[12:16], 0) // Transmit (4字节) // 剩余4字节填充0 // 创建ICMP时间戳请求消息 msg : icmp.Message{ Type: ipv4.ICMPTypeTimestamp, // Type 13 - 时间戳请求 Code: 0, Body: icmp.RawBody{ Data: timestampData, }, } // 序列化消息 wb, err : msg.Marshal(nil) if err ! nil { return } // 解析目标地址 host, err : net.ResolveIPAddr(ip4, Ip) if err ! nil { return } // 发送时间戳请求 _, err conn.WriteTo(wb, host) if err ! nil { return }生成PIDpid : uint16(os.Getpid() 0xffff)作用生成唯一的 ICMP 消息标识符用于匹配请求和响应。分解说明os.Getpid() // 获取当前进程的PID进程ID例如12345 0xffff // 按位与操作取低16位0xffff 65535 uint16(...) // 转换为16位无符号整数生成时间戳currentTime : uint32(time.Now().UnixNano() / 1e6)作用生成当前时间戳用于 ICMP 时间戳请求的 Originate 字段。分解说明time.Now().UnixNano() // 获取当前时间的纳秒数例如1672531200000000000 / 1e6 // 除以1000000将纳秒转换为毫秒 uint32(...) // 转换为32位无符号整数标识符字段 (0-3字节)binary.BigEndian.PutUint16(timestampData[0:2], pid) // ID binary.BigEndian.PutUint16(timestampData[2:4], uint16(seq)) // Seq将32位无符号整数pid以大端序Big-Endian格式写入字节切片timestampData的第0到第1个位置。位置字节0-3ID字段(2字节)进程标识用于区分不同扫描进程Seq字段(2字节)序列号用于区分同一进程的不同请求大端序网络字节序确保跨平台兼容时间戳字段 (4-15字节)binary.BigEndian.PutUint32(timestampData[4:8], currentTime) // Originate binary.BigEndian.PutUint32(timestampData[8:12], 0) // Receive binary.BigEndian.PutUint32(timestampData[12:16], 0) // Transmit三个时间戳的作用Originate(4-7字节)请求发起时间由发送方填充Receive(8-11字节)请求接收时间由目标主机填充初始为0Transmit(12-15字节)回复发送时间由目标主机填充初始为0时间戳格式32位无符号整数表示从UTC时间1900年1月1日午夜开始的毫秒数实际实现中常用相对时间戳填充字段 (16-19字节)剩余4字节自动为0make([]byte, 20)初始化为0ICMP消息封装msg : icmp.Message{ Type: ipv4.ICMPTypeTimestamp, // Type 13 Code: 0, Body: icmp.RawBody{ Data: timestampData, }, }ICMP类型和代码Type 13时间戳请求 (Timestamp Request)Type 14时间戳回复 (Timestamp Reply)Code 0时间戳消息的代码字段始终为0序列化消息// 序列化消息 wb, err : msg.Marshal(nil) if err ! nil { return }msg.Marshal()ICMP消息的序列化方法nil可选的缓冲区参数传入nil表示自动创建缓冲区wb返回的字节切片wire bytes - 网络字节err错误信息序列化失败时返回监听并分析响应// 设置总超时 deadline : time.Now().Add(3 * time.Second) for { // 检查总超时 if time.Now().After(deadline) { return } // 设置读取超时 conn.SetReadDeadline(time.Now().Add(200 * time.Millisecond)) // 读取响应 rb : make([]byte, 1500) n, sourceAddr, err : conn.ReadFrom(rb) if err ! nil { if netErr, ok : err.(net.Error); ok netErr.Timeout() { continue // 超时继续等待 } return } // 检查响应来源是否匹配目标IP if sourceAddr.String() ! Ip { continue } // 解析ICMP消息 rm, err : icmp.ParseMessage(ipv4.ICMPTypeTimestampReply.Protocol(), rb[:n]) if err ! nil { continue } // 检查是否为时间戳回复 (Type 14) if rm.Type ! ipv4.ICMPTypeTimestampReply { continue } // 提取消息体数据 var responseData []byte switch body : rm.Body.(type) { case *icmp.RawBody: responseData body.Data default: continue } // 验证响应数据长度 if len(responseData) 16 { continue } // 解析响应中的ID和序列号 responseID : binary.BigEndian.Uint16(responseData[0:2]) responseSeq : binary.BigEndian.Uint16(responseData[2:4]) // 检查ID和序列号是否匹配 if responseID pid responseSeq uint16(seq) { mu.Lock() survival[Ip] up mu.Unlock() return // 收到响应退出循环 } }分析响应// 解析ICMP消息 rm, err : icmp.ParseMessage(ipv4.ICMPTypeTimestampReply.Protocol(), rb[:n]) //告诉解析器这是ICMP协议的数据解析出完整的ICMP消息结构 if err ! nil { continue } // 检查是否为时间戳回复 (Type 14) if rm.Type ! ipv4.ICMPTypeTimestampReply { //检查消息类型只处理ICMPTypeTimestampReply continue }上面的代码是让程序按照icmp的形式解析数据下面的代码才是检查消息类型// 示例 ipv4.ICMPTypeEchoReply.Protocol() // 返回 1 (ICMP协议号) ipv4.ICMPTypeEchoReply // 返回 0 (Echo Reply类型值)消息体数据提取var responseData []byte switch body : rm.Body.(type) { case *icmp.RawBody: responseData body.Data default: continue }作用从解析后的ICMP消息中提取原始数据体类型断言过程rm.Body是interface{}类型可能是多种消息体类型检查是否是*icmp.RawBody类型时间戳回复使用RawBody如果是提取body.Data包含原始的20字节时间戳数据如果不是跳过这个响应可能是其他类型的ICMP消息数据长度验证if len(responseData) 16 { continue }作用确保响应数据格式正确为什么是16字节时间戳消息体最小有效结构 0-1: ID (2字节) 2-3: Seq (2字节) 4-7: Originate (4字节) 8-11: Receive (4字节) 12-15: Transmit (4字节) 总计16字节输出结果// 输出结果 fmt.Println(存活主机列表) fmt.Println(IP地址\t\t状态) j : 0 for k, v : range survival { fmt.Printf(%s\t%s\n, k, v) j } usetime : time.Since(start) fmt.Printf(\n存活主机数量%d\n, j) fmt.Printf(运行时间: %v\n, usetime)源代码直接给出最终源代码https://github.com/yty0v0/ReconQuiver/blob/main/internal/discovery/icmp_host/timestamp.go其它在我写完针对多协议端口扫描和主机探测的工具后希望通过文章整理用到的知识点非常欢迎各位大佬指正文章内容的错误和工具的问题。这里附上工具链接 https://github.com/yty0v0/ReconQuiver