File size: 2,088 Bytes
3c8ff75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// ipUtils.js

/**
 * 解析 IPv4 数据包的目标地址
 * @param {Buffer} packet - IP 数据包
 * @returns {string} 目标 IP 地址
 */
function parseDestinationIP(packet) {
  // IP 头部长度 (通常是 20 字节)
  const headerLength = (packet[0] & 0x0F) * 4;
  
  // 检查是否有足够的字节来解析 IP 头部
  if (packet.length < headerLength + 4) {
    throw new Error('数据包太短,无法解析目标 IP');
  }
  
  // 目标 IP 地址在 IP 头部的第 16-19 字节
  const destIP = `${packet[16]}.${packet[17]}.${packet[18]}.${packet[19]}`;
  return destIP;
}

/**
 * 解析 IPv4 数据包的目标端口 (适用于 TCP/UDP)
 * @param {Buffer} packet - IP 数据包
 * @returns {number} 目标端口号
 */
function parseDestinationPort(packet) {
  // IP 头部长度
  const headerLength = (packet[0] & 0x0F) * 4;
  
  // 检查协议 (6 = TCP, 17 = UDP)
  const protocol = packet[9];
  
  // TCP/UDP 头部中的端口字段位置
  if (protocol === 6 || protocol === 17) {
    // 检查是否有足够的字节来解析端口
    if (packet.length < headerLength + 4) {
      throw new Error('数据包太短,无法解析目标端口');
    }
    
    // 目标端口在 TCP/UDP 头部的第 2-3 字节
    const destPort = (packet[headerLength + 2] << 8) + packet[headerLength + 3];
    return destPort;
  }
  
  // 对于其他协议返回默认端口 0
  return 0;
}

/**
 * 验证是否为有效的 IPv4 数据包
 * @param {Buffer} packet - 待验证的数据包
 * @returns {boolean} 是否为有效的 IPv4 数据包
 */
function isValidIPv4Packet(packet) {
  // 检查数据包是否为空
  if (!packet || packet.length < 20) {
    return false;
  }
  
  // 检查 IP 版本 (应该是 4)
  const version = (packet[0] >> 4) & 0x0F;
  if (version !== 4) {
    return false;
  }
  
  // 检查 IP 头部长度
  const headerLength = (packet[0] & 0x0F) * 4;
  if (headerLength < 20 || headerLength > packet.length) {
    return false;
  }
  
  return true;
}

module.exports = {
  parseDestinationIP,
  parseDestinationPort,
  isValidIPv4Packet
};