def build_ip_packet(pkt_len, protocol, saddr, daddr, message, pkt_id=1, flags_df=0, flags_mf=0, offset=0): """创建IP数据包 :param pkt_len:包长度 :param saddr: bytes类型的源地址 :param daddr: bytes类型的目的地址 :param message:消息内容 :param pkt_id: 包ID :param flags_df: 分段df位 :param flags_mf:分段mf位 :param offset:包偏移 :return ip_pkt: """ if pkt_len < __IP_HDR_SIZE: raise ValueError("the value of pkt_len must be less than 20") if protocol < 0 or protocol > 255: raise ValueError("the value of protocol is wrong") tpl = b'E\x00\x00\x14\x00\x01\x00\x00@\x00z\xea\x00\x00\x00\x00\x00\x00\x00\x00' L = list(tpl) # 修改地址 csum = (L[10] << 8) | L[11] csum = checksum.calc_checksum_for_ip_change(tpl[12:16], saddr, csum) csum = checksum.calc_checksum_for_ip_change(tpl[16:20], daddr, csum) L[12:16] = saddr L[16:20] = daddr # 修改包长度 old_v = (L[2] << 8) | L[3] new_v = pkt_len csum = fn_utils.calc_incre_csum(csum, old_v, new_v) L[2:4] = ((pkt_len & 0xff00) >> 8, pkt_len & 0x00ff,) # 修改包ID old_v = (L[4] << 8) | L[5] new_v = pkt_id csum = fn_utils.calc_incre_csum(csum, old_v, new_v) L[4:6] = ((pkt_id & 0xff00) >> 8, pkt_id & 0x00ff,) # 修改flags以及offset old_v = (L[6] << 8) | L[7] new_v = (flags_df << 14) | (flags_mf << 13) | offset csum = fn_utils.calc_incre_csum(csum, old_v, new_v) L[6:8] = ((new_v & 0xff00) >> 8, new_v & 0x00ff,) # 修改协议 old_v = L[9] new_v = protocol csum = fn_utils.calc_incre_csum(csum, old_v, new_v) L[9] = protocol # 修改校检和 # L[10:12] = (0, 0,) # csum = fn_utils.calc_csum(bytes(L), 20) L[10:12] = ((csum & 0xff00) >> 8, csum & 0x00ff,) return b"".join((bytes(L), message,))
def calc_checksum_for_ip_change(old_ip_packet, new_ip_packet, old_checksum, is_ipv6=False): """ ip地址改变之后重新获取校检码 :param old_ip_packet: :param new_ip_packet: :param old_checksum: :param is_ipv6:是否是ipv6 :return: """ final_checksum = old_checksum a = 0 b = 1 # tmpcsum = old_checksum if is_ipv6: n = 8 else: n = 2 i = 0 while i < n: old_field = (old_ip_packet[a] << 8) | old_ip_packet[b] new_field = (new_ip_packet[a] << 8) | new_ip_packet[b] # final_checksum = checksum.calc_incre_checksum(final_checksum, old_field, new_field) final_checksum = fn_utils.calc_incre_csum(final_checksum, old_field, new_field) a = a + 2 b = b + 2 i += 1 return final_checksum
def modify_port(port, mbuf, flags=0): """修改TCP/SCTP/UDP/UDPLite端口 :param port: :param mbuf: :param flags: 0表示修改源端口,1表示修改目的端口 :return: """ protocols = ( 6, 17, 132, 136, ) ip_ver = mbuf.ip_version() p = __get_protocol(mbuf) if p not in protocols: raise ValueError("unsupport IP protocol for modify port") if ip_ver == 4: hdrlen = __get_ip4_hdrlen(mbuf) else: hdrlen = 40 if flags == 0: port_off = hdrlen else: port_off = hdrlen + 2 mbuf.offset = port_off # SCTP特别处理 if p == 132: mbuf.replace(utils.number2bytes(port, 2)) return old_port = utils.bytes2number(mbuf.get_part(2)) if p in ( 6, 136, ): csum_offset = hdrlen + 6 else: csum_offset = hdrlen + 16 mbuf.offset = csum_offset csum = utils.bytes2number(mbuf.get_part(2)) mbuf.offset = port_off mbuf.replace(utils.number2bytes(port, 2)) # 如果旧的校检和为0,说明不需要进行校检和计算 if csum == 0: return mbuf.offset = csum_offset csum = fn_utils.calc_incre_csum(csum, old_port, port) mbuf.replace(utils.number2bytes(csum, 2))
def calc_checksum_for_ip_change(old_ip_packet, new_ip_packet, old_checksum): """ ip地址改变之后重新获取校检码 :param old_ip_packet: :param new_ip_packet: :param old_checksum: :return: """ final_checksum = old_checksum a = 0 b = 1 # tmpcsum = old_checksum for i in range(2): old_field = (old_ip_packet[a] << 8) | old_ip_packet[b] new_field = (new_ip_packet[a] << 8) | new_ip_packet[b] # final_checksum = checksum.calc_incre_checksum(final_checksum, old_field, new_field) final_checksum = fn_utils.calc_incre_csum(final_checksum, old_field, new_field) a = a + 2 b = b + 2 return final_checksum
def build_ip_packet(pkt_len, protocol, saddr, daddr, message, pkt_id=1, flags_df=0, flags_mf=0, offset=0): """创建IP数据包 :param pkt_len:包长度 :param saddr: bytes类型的源地址 :param daddr: bytes类型的目的地址 :param message:消息内容 :param pkt_id: 包ID :param flags_df: 分段df位 :param flags_mf:分段mf位 :param offset:包偏移 :return ip_pkt: """ if pkt_len < __IP_HDR_SIZE: raise ValueError("the value of pkt_len must be less than 20") if protocol < 0 or protocol > 255: raise ValueError("the value of protocol is wrong") tpl = b'E\x00\x00\x14\x00\x01\x00\x00@\x00z\xea\x00\x00\x00\x00\x00\x00\x00\x00' L = list(tpl) # 修改地址 csum = (L[10] << 8) | L[11] csum = checksum.calc_checksum_for_ip_change(tpl[12:16], saddr, csum) csum = checksum.calc_checksum_for_ip_change(tpl[16:20], daddr, csum) L[12:16] = saddr L[16:20] = daddr # 修改包长度 old_v = (L[2] << 8) | L[3] new_v = pkt_len csum = fn_utils.calc_incre_csum(csum, old_v, new_v) L[2:4] = ( (pkt_len & 0xff00) >> 8, pkt_len & 0x00ff, ) # 修改包ID old_v = (L[4] << 8) | L[5] new_v = pkt_id csum = fn_utils.calc_incre_csum(csum, old_v, new_v) L[4:6] = ( (pkt_id & 0xff00) >> 8, pkt_id & 0x00ff, ) # 修改flags以及offset old_v = (L[6] << 8) | L[7] new_v = (flags_df << 14) | (flags_mf << 13) | offset csum = fn_utils.calc_incre_csum(csum, old_v, new_v) L[6:8] = ( (new_v & 0xff00) >> 8, new_v & 0x00ff, ) # 修改协议 old_v = L[9] new_v = protocol csum = fn_utils.calc_incre_csum(csum, old_v, new_v) L[9] = protocol # 修改校检和 # L[10:12] = (0, 0,) # csum = fn_utils.calc_csum(bytes(L), 20) L[10:12] = ( (csum & 0xff00) >> 8, csum & 0x00ff, ) return b"".join(( bytes(L), message, ))
def __handle_ipv4_dgram_from_tunnel(self, session_id, is_udplite=False): mbuf = self.__mbuf mbuf.offset = 4 mbuf.offset = 6 frag_off = utils.bytes2number(mbuf.get_part(2)) df = (frag_off & 0x4000) >> 14 mf = (frag_off & 0x2000) >> 13 offset = frag_off & 0x1fff if offset == 0: sts_saddr, sts_daddr, sport, dport = self.__get_ipv4_dgram_pkt_addr_info( ) if dport == 0: return False # 把源地址和checksum设置为0 mbuf.offset = 12 mbuf.replace(b"\0\0\0\0") mbuf.offset = 10 mbuf.replace(b"\0\0") ## if offset != 0: mbuf.offset = 0 self.send_message_to_handler(-1, self.__raw_fileno, mbuf.get_data()) return _id = "%s-%s" % ( sts_saddr, sport, ) fileno = -1 if session_id in self.__dgram_proxy: pydict = self.__dgram_proxy[session_id] if _id in pydict: fileno = pydict[_id] if fileno < 0: fileno = self.create_handler(-1, traffic_pass.p2p_proxy, session_id, ( sts_saddr, sport, ), mtu=self.__ip4_mtu, is_udplite=is_udplite, is_ipv6=False) if fileno < 0: return self.get_handler(fileno).add_permit(( sts_daddr, dport, )) _, new_sport = self.get_handler(fileno).getsockname() hdrlen = self.__get_ip4_hdrlen() # 替换源端口 mbuf.offset = hdrlen mbuf.replace(utils.number2bytes(new_sport, 2)) mbuf.offset = hdrlen + 6 if not is_udplite: mbuf.replace(b"\0\0") else: csum = utils.bytes2number(mbuf.get_part(2)) csum = fn_utils.calc_incre_csum(csum, sport, new_sport) mbuf.replace(utils.number2bytes(csum, 2)) if session_id not in self.__dgram_proxy: self.__dgram_proxy[session_id] = {} pydict = self.__dgram_proxy[session_id] pydict[_id] = fileno mbuf.offset = 0 self.send_message_to_handler(-1, self.__raw_fileno, mbuf.get_data())
def __handle_ipv4_dgram_from_tunnel(self, session_id, is_udplite=False): mbuf = self.__mbuf mbuf.offset = 4 mbuf.offset = 6 frag_off = utils.bytes2number(mbuf.get_part(2)) df = (frag_off & 0x4000) >> 14 mf = (frag_off & 0x2000) >> 13 offset = frag_off & 0x1fff if offset == 0: sts_saddr, sts_daddr, sport, dport = self.__get_ipv4_dgram_pkt_addr_info() if dport == 0: return False # 把源地址和checksum设置为0 mbuf.offset = 12 mbuf.replace(b"\0\0\0\0") mbuf.offset = 10 mbuf.replace(b"\0\0") ## if offset != 0: mbuf.offset = 0 self.send_message_to_handler(-1, self.__raw_fileno, mbuf.get_data()) return _id = "%s-%s" % (sts_saddr, sport,) fileno = -1 if session_id in self.__dgram_proxy: pydict = self.__dgram_proxy[session_id] if _id in pydict: fileno = pydict[_id] if fileno < 0: fileno = self.create_handler(-1, traffic_pass.p2p_proxy, session_id, (sts_saddr, sport,), mtu=self.__ip4_mtu, is_udplite=is_udplite, is_ipv6=False) if fileno < 0: return self.get_handler(fileno).add_permit((sts_daddr, dport,)) _, new_sport = self.get_handler(fileno).getsockname() hdrlen = self.__get_ip4_hdrlen() # 替换源端口 mbuf.offset = hdrlen mbuf.replace(utils.number2bytes(new_sport, 2)) mbuf.offset = hdrlen + 6 if not is_udplite: mbuf.replace(b"\0\0") else: csum = utils.bytes2number(mbuf.get_part(2)) csum = fn_utils.calc_incre_csum(csum, sport, new_sport) mbuf.replace(utils.number2bytes(csum, 2)) if session_id not in self.__dgram_proxy: self.__dgram_proxy[session_id] = {} pydict = self.__dgram_proxy[session_id] pydict[_id] = fileno mbuf.offset = 0 self.send_message_to_handler(-1, self.__raw_fileno, mbuf.get_data())