import struct
import socket
class IP_Packet:
def __init__(self, source_ip, destination_ip, protocol,payload=b''):
self.version = 4 # IP版本号,IPv4为4,IPv6为6
self.header_length = 5 # IP报头长度(32位字的数量)
self.type_of_service = 0 # 服务类型(通常为0)
self.total_length = 20 + len(payload) # IP报文总长度(字节数)
self.identification = 0 # 标识符
self.flags = 0 # 标志(DF和MF)(通常为0)
self.fragment_offset = 0 # 分片偏移(通常为0)
self.time_to_live = 64 # 生存时间(TTL)
self.protocol = protocol # 上层协议(TCP=6,UDP=17)
self.checksum = 0 # 校验和(初始值为0)
self.source_ip = socket.inet_aton(source_ip) # 源IP地址
self.destination_ip = socket.inet_aton(destination_ip) # 目标IP地址
self.payload = payload # 上层协议数据
def calculate_checksum(self, header):
"""
计算IP报头的校验和
"""
checksum = 0
# 将每个16位字添加到校验和中
for i in range(0, len(header), 2):
checksum += (header[i] << 8) + header[i+1]
# 将溢出位添加到校验和中
while checksum >> 16:
checksum = (checksum & 0xFFFF) + (checksum >> 16)
# 取反得到校验和的补码
checksum = ~checksum & 0xFFFF
return checksum
def pack(self):
"""
将IP报文打包成二进制数据
"""
# 构造IP报头
version_header_length = (self.version << 4) + self.header_length
flags_fragment_offset = (self.flags << 13) + self.fragment_offset
header = struct.pack('!BBHHHBBH4s4s', version_header_length, self.type_of_service, self.total_length,
self.identification, flags_fragment_offset, self.time_to_live, self.protocol,
self.checksum, self.source_ip, self.destination_ip)
# 计算IP报头的校验和
self.checksum = self.calculate_checksum(header)
# 重新构造IP报头,更新校验和字段
header = struct.pack('!BBHHHBBH4s4s', version_header_length, self.type_of_service, self.total_length,
self.identification, flags_fragment_offset, self.time_to_live, self.protocol,
self.checksum, self.source_ip, self.destination_ip)
# 打包IP报文数据和上层协议数据
packet = header + self.payload
return packet
if __name__ == "__main__":
ip = IP_Packet('192.168.198.1', '192.168.198.1', protocol=socket.IPPROTO_TCP,payload=b'')
packet = ip.pack()
print(packet)