• 使用 Python 代码实现 ICMP Timestamp 请求和回应


    具体代码如下: 

    1. import socket
    2. import struct
    3. import time
    4. # 构建ICMP Timestamp请求数据包
    5. def build_icmp_request():
    6. # IP头部
    7. header = b'\x08\x00\x00\x00\x00\x00\x00\x00'
    8. # ICMP头部
    9. icmp_type = 13 # ICMP Timestamp请求类型
    10. icmp_code = 0
    11. icmp_checksum = 0
    12. icmp_id = 12345
    13. icmp_seq = 1
    14. # 时间戳数据
    15. timestamp = int(time.time())
    16. # 使用struct.pack()函数将icmp_id、icmp_seq和timestamp打包成二进制数据
    17. # !HHd表示使用网络字节序进行打包,H表示一个无符号短整数(2字节),d表示一个双精度浮点数(8字节)
    18. icmp_data = struct.pack('!HHd', icmp_id, icmp_seq, timestamp)
    19. # 计算ICMP校验和
    20. # 使用struct.pack()函数将icmp_type、icmp_code、icmp_checksum、icmp_id、icmp_seq和timestamp + 1打包成二进制数据
    21. # !BBHHHd表示使用网络字节序进行打包,B表示一个无符号字节(1字节),H表示一个无符号短整数(2字节),d表示一个双精度浮点数(8字节)
    22. icmp_checksum = calculate_checksum(
    23. struct.pack('!BBHHHd', icmp_type, icmp_code, icmp_checksum, icmp_id, icmp_seq, timestamp + 1))
    24. # 构建ICMP Timestamp请求数据包
    25. icmp_request = struct.pack('!BBHHHd', icmp_type, icmp_code, icmp_checksum, icmp_id, icmp_seq, timestamp) + icmp_data
    26. return header + icmp_request
    27. # 计算校验和
    28. # 1. `checksum = 0`:初始化变量`checksum`为0,用于计算校验和。
    29. #
    30. # 2. `countTo = (len(data) // 2) * 2`:计算需要进行校验和计算的数据的长度,将其除以2取整并乘以2,以确保数据长度为偶数。
    31. #
    32. # 3. `for count in range(0, countTo, 2):`:使用循环遍历数据,每次迭代处理两个字节的数据。
    33. #
    34. # 4. `thisVal = data[count + 1] * 256 + data[count]`:将两个字节的数据合并为一个16位的整数,其中高位字节乘以256后与低位字节相加。
    35. #
    36. # 5. `checksum = checksum + thisVal`:将计算得到的整数与之前的校验和相加。
    37. #
    38. # 6. `checksum = checksum & 0xffffffff`:将校验和限制在32位范围内。
    39. #
    40. # 7. `if countTo < len(data):`:检查数据长度是否为奇数。
    41. #
    42. # 8. `checksum = checksum + data[len(data) - 1]`:如果数据长度为奇数,将最后一个字节与校验和相加。
    43. #
    44. # 9. `checksum = checksum & 0xffffffff`:将校验和限制在32位范围内。
    45. #
    46. # 10. `checksum = (checksum >> 16) + (checksum & 0xffff)`:将校验和的高16位和低16位相加。
    47. #
    48. # 11. `checksum = checksum + (checksum >> 16)`:将结果的高16位与低16位再相加。
    49. #
    50. # 12. `answer = ~checksum`:将校验和取反。
    51. #
    52. # 13. `answer = answer & 0xffff`:将校验和限制在16位范围内。
    53. #
    54. # 14. `answer = answer >> 8 | (answer << 8 & 0xff00)`:将校验和的字节顺序进行反转。
    55. #
    56. # 15. `return answer`:返回计算得到的校验和。
    57. def calculate_checksum(data):
    58. checksum = 0
    59. countTo = (len(data) // 2) * 2
    60. for count in range(0, countTo, 2):
    61. thisVal = data[count + 1] * 256 + data[count]
    62. checksum = checksum + thisVal
    63. checksum = checksum & 0xffffffff
    64. if countTo < len(data):
    65. checksum = checksum + data[len(data) - 1]
    66. checksum = checksum & 0xffffffff
    67. checksum = (checksum >> 16) + (checksum & 0xffff)
    68. checksum = checksum + (checksum >> 16)
    69. answer = ~checksum
    70. answer = answer & 0xffff
    71. answer = answer >> 8 | (answer << 8 & 0xff00)
    72. return answer
    73. # 发送ICMP Timestamp请求并接收回应
    74. def send_icmp_request(destination):
    75. # 构建ICMP Timestamp请求数据包
    76. icmp_request = build_icmp_request()
    77. # 创建原始套接字
    78. # socket.socket()函数用于创建一个新的套接字对象。此处使用AF_INET参数指定使用IPv4协议族,SOCK_RAW参数指定使用原始套接字类型,IPPROTO_ICMP参数指定使用ICMP协议
    79. sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
    80. # 设置套接字的选项
    81. # setsockopt()函数用于设置套接字选项的值。IPPROTO_IP参数表示要设置的选项属于IP协议,IP_HDRINCL参数表示要设置的选项是IP头部的包含选项,1表示要启用该选项
    82. sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
    83. # 发送ICMP Timestamp请求数据包
    84. # sendto()方法用于发送数据到指定的目标地址。icmp_request参数是要发送的数据包,(destination, 0)参数表示目标地址和端口,其中destination是目标主机的IP地址,0表示端口号
    85. sock.sendto(icmp_request, (destination, 0))
    86. # 接收ICMP回应数据包
    87. # recvfrom()方法用于从套接字接收数据。1024参数表示一次最多接收的数据大小
    88. data, address = sock.recvfrom(1024)
    89. # 解析ICMP回应数据包
    90. icmp_reply = struct.unpack('!BBHHHd', data[20:36])
    91. # 提取时间戳信息
    92. timestamp = icmp_reply[5]
    93. return timestamp
    94. def main():
    95. # 示例用法
    96. destination = '192.168.134.128' # 目标主机IP地址
    97. timestamp = send_icmp_request(destination)
    98. print(f'Timestamp from {destination}: {timestamp}')
    99. if __name__ == '__main__':
    100. main()

    运行结果: 

  • 相关阅读:
    mysql索引失效的几种情况
    兼容PostgreSQL,Google推出全管理型数据库AlloyDB,工作效率翻番
    红色旅游AR互动体验将景区推向更广泛的市场
    “阿里”又爆新作,Github新开源303页Spring全家桶高级笔记
    MATLAB - 用命令行设计 MPC 控制器
    Docker部署并启动RabbitMQ
    【精品】将两个字符串进行加密和解密的Java工具类
    小程序无感刷新
    centos7安装mysql8
    Canal整合SpringBoot详解(一)
  • 原文地址:https://blog.csdn.net/2302_82189125/article/details/138127250