Exemplo n.º 1
0
class ICMPPacket:
    def __init__(self, wan_int, packet):
        self.packet = packet
        self.wan_int = wan_int

        self.Checksum = Checksums()

    def Create(self):
        self.AssignValues()
        self.CreateICMP()
        self.AssembleICMP()
        self.CreateIPv4()
        self.AssembleIPv4()

        self.ip_chk = self.Checksum.IPv4(self.ipv4_header)
        self.icmp_chk = self.Checksum.ICMP(self.icmp_header +
                                           self.icmp_payload)

    def AssignValues(self):
        self.l2pro = 0x0800
        Int = Interface()
        self.smac = Int.MAC(self.wan_int)
        self.dmac = self.packet.src_mac
        self.src_ip = Int.IP(self.wan_int)
        self.dst_ip = self.packet.src_ip
        self.icmp_payload = self.packet.ipv4_header + self.packet.udp_header

    def AssembleEthernet(self):
        self.ethernet_header = struct.pack(
            '!6s6sH', binascii.unhexlify(self.dmac.replace(":", "")),
            binascii.unhexlify(self.smac.replace(":", "")), self.l2pro)

    def CreateIPv4(self):
        ip_ver = 4
        ip_vhl = 5
        self.ip_ver = (ip_ver << 4) + ip_vhl
        ip_dsc = 0
        ip_ecn = 0
        self.ip_dfc = (ip_dsc << 2) + ip_ecn
        self.ip_tol = 20 + len(
            self.icmp_payload + self.icmp_header)  # +8 for original udp header
        self.ip_idf = 0
        ip_rsv = 0
        ip_dtf = 0
        ip_mrf = 0
        ip_frag_offset = 0

        self.ip_flg = (ip_rsv << 7) + (ip_dtf << 6) + (ip_mrf << 5) + (
            ip_frag_offset)
        self.ip_ttl = 255
        self.ip_proto = ICMP
        self.ip_chk = 0
        self.ip_saddr = inet_aton(self.src_ip)
        self.ip_daddr = inet_aton(self.dst_ip)

    def AssembleIPv4(self):
        self.ipv4_header = struct.pack('!BBHHHBB', self.ip_ver, self.ip_dfc,
                                       self.ip_tol, self.ip_idf, self.ip_flg,
                                       self.ip_ttl, self.ip_proto)
        self.ipv4_header += struct.pack('<H', self.ip_chk)
        self.ipv4_header += struct.pack('!4s4s', self.ip_saddr, self.ip_daddr)

    def CreateICMP(self):
        self.icmp_type = 3
        self.icmp_code = 3
        self.icmp_chk = 0
        self.icmp_id = 1
        self.icmp_seq = 0
        self.padding = 0

    def AssembleICMP(self):
        self.icmp_header = struct.pack('!2B', self.icmp_type, self.icmp_code)
        self.icmp_header += struct.pack('<H', self.icmp_chk)
        self.icmp_header += struct.pack(
            '!2H',
            self.icmp_id,
            self.icmp_seq,
        )
Exemplo n.º 2
0
class TCPPacket:
    def __init__(self, wan_int, packet):
        self.packet = packet
        self.wan_int = wan_int

        self.Checksum = Checksums()

    def Create(self):
        self.AssignValues()
        self.CreateIPv4()
        self.CreateTCP()

        self.AssembleIPv4()
        self.AssembleTCP()

        self.ipv4_checksum = self.Checksum.IPv4(self.ipv4_header)
        self.tcp_checksum = self.PseudoHeader()

    def AssignValues(self):
        self.l2pro = 0x0800
        Int = Interface()
        self.smac = Int.MAC(self.wan_int)
        self.dmac = self.packet.src_mac
        self.src_ip = Int.IP(self.wan_int)
        self.dst_ip = self.packet.src_ip
        self.src_port = self.packet.dst_port
        self.dst_port = self.packet.src_port

        self.sport = struct.pack('!H', self.src_port)
        #        print(self.packet.seq_number)
        self.ack_number = self.packet.seq_number + 1
## -- L2 - Ethernet Section ---- ##

    def AssembleEthernet(self):
        self.ethernet_header = struct.pack(
            '!6s6sH', binascii.unhexlify(self.dmac.replace(':', '')),
            binascii.unhexlify(self.smac.replace(':', '')), self.l2pro)

## -- L3 - IP Section ---- ##

    def CreateIPv4(self):
        ip_ver = 4
        ip_vhl = 5
        self.ip_ver = (ip_ver << 4) + ip_vhl
        ip_dsc = 0
        ip_ecn = 0
        self.ip_dfc = (ip_dsc << 2) + ip_ecn
        self.ip_tol = 20 + 20  # ---- [ Total Length]
        self.ip_idf = 1  # ---- [ Identification ]
        ip_rsv = 0  # ---- [ Flags ]
        ip_dtf = 0
        ip_mrf = 0
        ip_frag_offset = 0

        self.ip_flg = (ip_rsv << 7) + (ip_dtf << 6) + (ip_mrf << 5) + (
            ip_frag_offset)
        self.ip_ttl = 255  # ---- [ Total Length ]
        self.ip_proto = TCP  # ---- [ Protocol ]
        self.ipv4_checksum = 0  # ---- [ Check Sum ]
        self.ip_saddr = inet_aton(self.src_ip)  # ---- [ Source Address ]
        self.ip_daddr = inet_aton(self.dst_ip)  # ---- [ Destination Address ]

    def AssembleIPv4(self):
        self.ipv4_header = struct.pack(
            '!2B3H2B',
            self.ip_ver,  # IP Version
            self.ip_dfc,  # Differentiate Service Field
            self.ip_tol,  # Total Length
            self.ip_idf,  # Identification
            self.ip_flg,  # Flags
            self.ip_ttl,  # Time to leave
            self.ip_proto  # protocol
        )
        self.ipv4_header += struct.pack(
            '<H',
            self.ipv4_checksum  # Checksum
        )
        self.ipv4_header += struct.pack(
            '!4s4s',
            self.ip_saddr,  # Source IP
            self.ip_daddr  # Destination IP
        )

## -- L4 - UDP Section ---- ##

    def CreateTCP(self):
        self.tcp_seq = 0
        self.tcp_ack_seq = self.ack_number
        self.tcp_hdr_len = 80

        tcp_urg = 0
        tcp_ack = 1
        tcp_psh = 0
        tcp_rst = 1
        tcp_syn = 0
        tcp_fin = 0

        tcp_doff = 5
        self.tcp_offset_res = (tcp_doff << 4) + 0
        self.tcp_flags = tcp_fin + (tcp_syn << 1) + (tcp_rst << 2) + (
            tcp_psh << 3) + (tcp_ack << 4) + (tcp_urg << 5)

        self.tcp_wdw = htons(0)
        self.tcp_checksum = 0
        self.tcp_urg_ptr = 0
        self.padding = b'\x00' * 12

    def AssembleTCP(self):
        self.tcp_header = struct.pack('!2H2L2B3H', self.src_port,
                                      self.dst_port, self.tcp_seq,
                                      self.tcp_ack_seq, self.tcp_offset_res,
                                      self.tcp_flags, self.tcp_wdw,
                                      self.tcp_checksum, self.tcp_urg_ptr)

    def PseudoHeader(self):
        pseudo_header = b''
        pseudo_header += inet_aton(self.src_ip)
        pseudo_header += inet_aton(self.dst_ip)
        pseudo_header += struct.pack('!2BH', 0, 6, 54)
        pseudo_header += self.sport + self.tcp_header[
            2:16] + b'\x00\x00' + self.tcp_header[18:]

        tcp_checksum = self.Checksum.TCP(pseudo_header)

        return tcp_checksum
Exemplo n.º 3
0
class Packet:
    def __init__(self, response_ip, query_type):
        self.response_ip = response_ip
        self.query_type = query_type

        self.response_code = 0
        self.answer_count = 0
        self.dns_payload = b''

        self.Checksum = Checksums()

    def CreateHeaders(self):
        self.CreateDNS()
        self.CreateUDP()
        self.CreateIPv4()
        self.AssembleIPv4()
        self.ip_chk = self.Checksum.IPv4(self.ipv4_header)

    def Assemble(self):
        self.AssembleEthernet()
        self.AssembleIPv4()
        self.AssembleUDP()
        self.AssembleDNS()

        dns_response = self.ethernet_header + self.ipv4_header + self.udp_header
        dns_response += self.dns_header + self.dns_payload

        return dns_response

    def BuildPayload(self):
        self.BuildQuery()
        # if AAAA record will set response code to refuse and not give an answer
        if (self.query_type == AAAA_RECORD):
            self.response_code = 5
        # if local dns record returns none due to error, will inform client of error
        elif (not self.response_ip):
            self.response_code = 2
            print('SERVER FAILURE')
        # standard query response from remote server or for local dns record
        else:
            self.answer_count = 1
            self.BuildQueryResponse()

    def SplitPacket(self, packet):
        self.dst_mac = packet.src_mac
        self.src_mac = packet.dst_mac
        self.src_ip = packet.dst_ip
        self.dst_ip = packet.src_ip
        self.src_port = DNS_PORT
        self.dst_port = packet.src_port
        self.dns_id = packet.dns_id
        self.qname = packet.request

        self.l2pro = 0x0800

    def AssembleEthernet(self):
        self.ethernet_header = struct.pack(
            '!6s6sH', binascii.unhexlify(self.dst_mac.replace(':', '')),
            binascii.unhexlify(self.src_mac.replace(':', '')), self.l2pro)

    def CreateIPv4(self):
        ip_ver = 4
        ip_vhl = 5
        self.ip_ver = (ip_ver << 4) + ip_vhl
        ip_dsc = 0
        ip_ecn = 0
        self.ip_dfc = (ip_dsc << 2) + ip_ecn
        self.ip_tol = 20 + self.udp_length
        self.ip_idf = 0
        ip_rsv = 0
        ip_dtf = 0
        ip_mrf = 0
        ip_frag_offset = 0

        self.ip_flg = (ip_rsv << 7) + (ip_dtf << 6) + (ip_mrf << 5) + (
            ip_frag_offset)
        self.ip_ttl = 255
        self.ip_proto = IPPROTO_UDP
        self.ip_chk = 0
        self.ip_saddr = inet_aton(self.src_ip)
        self.ip_daddr = inet_aton(self.dst_ip)

    def AssembleIPv4(self):
        self.ipv4_header = struct.pack('!2B3H2B', self.ip_ver, self.ip_dfc,
                                       self.ip_tol, self.ip_idf, self.ip_flg,
                                       self.ip_ttl, self.ip_proto)
        self.ipv4_header += struct.pack('<H', self.ip_chk)
        self.ipv4_header += struct.pack('!4s4s', self.ip_saddr, self.ip_daddr)

    def CreateUDP(self):
        self.udp_length = self.dns_length + 8
        self.udp_chk = 0

    def AssembleUDP(self):
        self.udp_header = struct.pack('!4H', self.src_port, self.dst_port,
                                      self.udp_length, self.udp_chk)

    def CreateDNS(self):
        self.id = self.dns_id
        self.qr = 1
        self.opcode = 0
        self.aa = 0
        self.tc = 0
        self.rd = 1
        self.ra = 1
        self.z = 0
        self.rcode = self.response_code
        self.qdcount = 1
        self.ancount = self.answer_count
        self.nscount = 0
        self.arcount = 0

        self.dns_length = 12 + len(self.dns_payload)

    def AssembleDNS(self):
        self.p1 = (self.qr << 7) | (self.opcode << 3) | (self.aa << 2) | (
            self.tc << 1) | (self.rd << 0)
        self.p2 = (self.ra << 7) | (self.z << 4) | (self.rcode << 0)

        self.dns_header = struct.pack('!H2B4H', self.id, self.p1, self.p2,
                                      self.qdcount, self.ancount, self.nscount,
                                      self.arcount)

    def BuildQuery(self):
        self.qclass = 1

        split_url = self.qname.split('.')
        for part in split_url:
            self.dns_payload += struct.pack('B', len(part))
            for char in part:
                self.dns_payload += struct.pack('B', ord(char))

        self.dns_payload += b'\x00'
        self.dns_payload += struct.pack('!2H', self.query_type, self.qclass)

    def BuildQueryResponse(self):
        # assigning vars
        self.rrname = b'\xc0\x0c'
        self.type = self.query_type
        self.rclass = 1
        self.ttl = 300
        self.rdlen = 4
        self.rdata = inet_aton(self.response_ip)

        #packing vars
        self.dns_payload += struct.pack('!2s2HLH4s', self.rrname, self.type,
                                        self.rclass, self.ttl, self.rdlen,
                                        self.rdata)
class Packet:
    def __init__(self, response_ip, packet):
        self.response_ip = response_ip
        self.packet = packet

        self.Checksum = Checksums()

        self.dns_payload = b''

    def Start(self):
        self.SplitPacket()
        self.CreateQueryResponse()
        self.CreateDNS()
        self.CreateUDP()
        self.CreateIPv4()
        self.AssembleIPv4()
        self.ip_chk = self.Checksum.IPv4(self.ipv4_header)

    def SplitPacket(self):
        self.smac = self.packet.smac
        self.dmac = self.packet.dmac
        self.dst_ip = self.packet.src
        self.src_ip = self.packet.dst
        self.src_port = DNS
        self.dst_port = self.packet.sport
        self.dnsID = self.packet.dnsID
        self.url = self.packet.qname.lower()

        self.l2pro = 0x0800

    def AssembleEthernet(self):
        self.ethernet_header = struct.pack(
            '!6s6sH', binascii.unhexlify(self.smac.replace(":", "")),
            binascii.unhexlify(self.dmac.replace(":", "")), self.l2pro)

    def CreateIPv4(self):
        ip_ver = 4
        ip_vhl = 5
        self.ip_ver = (ip_ver << 4) + ip_vhl
        ip_dsc = 0
        ip_ecn = 0
        self.ip_dfc = (ip_dsc << 2) + ip_ecn
        self.ip_tol = 20 + self.udp_len
        self.ip_idf = 0
        ip_rsv = 0
        ip_dtf = 0
        ip_mrf = 0
        ip_frag_offset = 0

        self.ip_flg = (ip_rsv << 7) + (ip_dtf << 6) + (ip_mrf << 5) + (
            ip_frag_offset)
        self.ip_ttl = 255
        self.ip_proto = IPPROTO_UDP
        self.ip_chk = 0
        self.ip_saddr = inet_aton(self.src_ip)
        self.ip_daddr = inet_aton(self.dst_ip)

    def AssembleIPv4(self):
        self.ipv4_header = struct.pack('!2B3H2B', self.ip_ver, self.ip_dfc,
                                       self.ip_tol, self.ip_idf, self.ip_flg,
                                       self.ip_ttl, self.ip_proto)
        self.ipv4_header += struct.pack('<H', self.ip_chk)
        self.ipv4_header += struct.pack('!4s4s', self.ip_saddr, self.ip_daddr)

    def CreateUDP(self):
        self.udp_sport = DNS
        self.udp_dport = self.dst_port
        self.udp_len = self.dnsL + 8 + 6
        self.udp_chk = 0

    def AssembleUDP(self):
        self.udp_header = struct.pack('!4H', self.udp_sport, self.udp_dport,
                                      self.udp_len, self.udp_chk)

    def CreateDNS(self):
        self.id = self.dnsID
        self.qr = 1
        self.opcode = 0
        self.aa = 0
        self.tc = 0
        self.rd = 1
        self.ra = 1
        self.z = 0
        self.ad = 0
        self.cd = 0
        self.rcode = 0
        self.qdcount = 1
        self.ancount = 1
        self.nscount = 0
        self.arcount = 0
        self.dnsL = self.dnsRL + 12

    def AssembleDNS(self):
        self.p1 = (self.qr << 7) | (self.opcode << 3) | (self.aa << 2) | (
            self.tc << 1) | (self.rd << 0)
        self.p2 = (self.ra << 7) | (self.z << 6) | (self.ad << 5) | (
            self.cd << 4) | (self.rcode << 0)

        self.dns_header = struct.pack('!H2B4H', self.id, self.p1, self.p2,
                                      self.qdcount, self.ancount, self.nscount,
                                      self.arcount)

    def CreateQueryResponse(self):
        self.qname = self.url
        self.qtype = 1
        self.qclass = 1

        self.rrname = b'\xc0\x0c'
        self.type = 1
        self.rclass = 1
        self.ttl = 300
        self.rdlen = 4
        self.rdata = inet_aton(self.response_ip)
        self.urlTTL = len(self.url) * 2
        self.dnsRL = self.urlTTL + 14 + 2

    def AssembleQueryResponse(self):
        split_url = self.url.split('.')
        for part in split_url:
            self.dns_payload += struct.pack('B', len(part))
            for char in part:
                self.dns_payload += struct.pack('B', ord(char))

        self.dns_payload += b'\x00'
        self.dns_payload += struct.pack('!2H', self.qtype, self.qclass)
        self.dns_payload += self.dns_payload
        self.dns_payload += struct.pack('!LH4s', self.ttl, self.rdlen,
                                        self.rdata)
class PacketManipulation:
    def __init__(self, packet_headers, net_info, data, connection,
                 from_server):
        self.Checksum = Checksums()
        self.packet_headers = packet_headers
        self.dst_mac, self.wan_subnet = net_info
        self.data = data
        self.connection = connection
        self.from_server = from_server

        self.tcp_header_length = 0
        self.dst_ip = None
        self.nat_port = None
        self.payload = b''

        if (from_server):
            self.src_mac = connection['LAN']['MAC']
            self.src_ip = connection['Server']['IP']
            self.dst_ip = connection['Client']['IP']
            self.client_port = connection['Client']['Port']
            self.client_port = struct.pack('!H', connection['Client']['Port'])
        else:
            self.src_mac = connection['NAT']['MAC']
            self.src_ip = connection['NAT']['IP']
            self.nat_port = connection['NAT']['Port']
            self.nat_port = struct.pack('!H', self.nat_port)
            self.dst_ip = self.packet_headers.dst
            self.dst_port = self.data[36:38]

    def Start(self):
        self.CheckDestination()
        self.TCP()
        self.PsuedoHeader()
        self.RebuildHeaders()

    def CheckDestination(self):
        if (self.dst_ip in self.wan_subnet):
            Int = Interface()
            dst_mac = Int.IPtoMAC(self.dst_ip)
            if (not dst_mac):
                run(f'ping {self.dst_ip} -c 1', shell=True)
                self.dst_mac = Int.IPtoMAC(self.dst_ip)
            else:
                self.dst_mac = dst_mac

    ''' Parsing TCP information like sequence and acknowledgement number amd calculated tcp header
    length to be used by other classes for offset/proper indexing of packet contents.
    Returning all relevant information back to HeaderParse Start method to be redistributed to other classes
    based on need '''

    def TCP(self):
        bit_values = [32, 16, 8, 4]

        tcp = self.data[34:94]
        tmp_length = bin(tcp[12])[2:6]

        for i, bit in enumerate(tmp_length):
            if (bit == '1'):
                self.tcp_header_length += bit_values[i]

        self.tcp_header = self.data[34:34 + self.tcp_header_length]
        self.tcp_length = len(self.data) - 34
        if (len(self.data) > 34 + self.tcp_header_length):
            self.payload = self.data[34 + self.tcp_header_length:]

    def PsuedoHeader(self):
        psuedo_header = b''
        psuedo_header += inet_aton(self.src_ip)
        psuedo_header += inet_aton(self.dst_ip)
        psuedo_header += struct.pack('!2BH', 0, 6, self.tcp_length)
        if (self.from_server):
            psuedo_header += self.tcp_header[
                0:2] + self.client_port + self.tcp_header[
                    4:16] + b'\x00\x00' + self.tcp_header[18:]
        else:
            psuedo_header += self.nat_port + self.tcp_header[
                2:16] + b'\x00\x00' + self.tcp_header[18:]
        psuedo_packet = psuedo_header + self.payload

        tcp_checksum = self.Checksum.TCP(psuedo_packet)
        self.tcp_checksum = struct.pack('<H', tcp_checksum)

    def RebuildHeaders(self):
        ethernet_header = self.RebuildEthernet()
        ip_header = self.RebuildIP()
        tcp_header = self.RebuildTCP()

        self.send_data = ethernet_header + ip_header + tcp_header + self.payload

    def RebuildEthernet(self):
        eth_header = struct.pack(
            '!6s6s', binascii.unhexlify(self.dst_mac.replace(':', '')),
            binascii.unhexlify(self.src_mac.replace(':', '')))
        eth_header += self.packet_headers.eth_proto

        return eth_header

    def RebuildIP(self):
        ipv4_header = b''
        ipv4_header += self.packet_headers.ipv4H[:10]
        ipv4_header += b'\x00\x00'
        ipv4_header += inet_aton(self.src_ip)
        ipv4_header += inet_aton(self.dst_ip)

        if (len(self.packet_headers.ipv4H) > 20):
            ipv4_header += self.packet_headers.ipv4H[20:]

        ipv4_checksum = self.Checksum.IPv4(ipv4_header)
        ipv4_checksum = struct.pack('<H', ipv4_checksum)
        ipv4_header = ipv4_header[:10] + ipv4_checksum + ipv4_header[12:]

        return ipv4_header

    def RebuildTCP(self):
        if (self.from_server):
            tcp_header = self.tcp_header[:2] + self.client_port + self.tcp_header[
                4:16] + self.tcp_checksum + b'\x00\x00'
        else:
            tcp_header = self.nat_port + self.tcp_header[
                2:16] + self.tcp_checksum + b'\x00\x00'

        if (self.tcp_header_length > 20):
            tcp_header += self.tcp_header[20:self.tcp_header_length]

        return tcp_header
Exemplo n.º 6
0
class CreatePacket:
    def __init__(self, connection, to_server=False):
        self.connection = connection
        self.to_server = to_server

        self.Checksum = Checksums()
    
    def Create(self):
        self.AssignValues()
        self.CreateIPv4()
        self.CreateTCP()

        self.AssembleIPv4()
        self.AssembleTCP()

        self.ipv4_checksum = self.Checksum.IPv4(self.ipv4_header)
        self.tcp_checksum = self.PseudoHeader()

    def AssignValues(self):
        self.l2pro = 0x0800
        self.nat_port = struct.pack('!H', self.connection['NAT']['Port'])
        self.client_port = struct.pack('!H', self.connection['Client']['Port'])

        if (self.to_server):
            self.smac = self.connection['NAT']['MAC']
            self.src_ip = self.connection['NAT']['IP']
            self.sport = self.connection['NAT']['Port']
            self.dmac = self.connection['DFG']['MAC']
            self.dst_ip = self.connection['Server']['IP']
            self.dport = self.connection['Server']['Port']
        else:
            self.smac = self.connection['LAN']['MAC']
            self.src_ip = self.connection['Server']['IP']
            self.sport = self.connection['Server']['Port']
            self.dmac = self.connection['Client']['MAC']
            self.dst_ip = self.connection['Client']['IP']
            self.dport = self.connection['Client']['Port']
        
## -- L2 - Ethernet Section ---- ##
    def AssembleEthernet(self):
        self.ethernet_header = struct.pack('!6s6sH' ,
        binascii.unhexlify(self.dmac.replace(":","")),
        binascii.unhexlify(self.smac.replace(":","")),
        self.l2pro)

## -- L3 - IP Section ---- ##        
    def CreateIPv4(self):
        ip_ver = 4
        ip_vhl = 5
        self.ip_ver = (ip_ver << 4 ) + ip_vhl
        ip_dsc = 0
        ip_ecn = 0
        self.ip_dfc = (ip_dsc << 2 ) + ip_ecn
        self.ip_tol = 20 + 20                   # ---- [ Total Length]        
        self.ip_idf = 1                     # ---- [ Identification ]        
        ip_rsv = 0                          # ---- [ Flags ]
        ip_dtf = 0
        ip_mrf = 0
        ip_frag_offset = 0

        self.ip_flg = (ip_rsv << 7) + (ip_dtf << 6) + (ip_mrf << 5) + (ip_frag_offset)        
        self.ip_ttl = 255                           # ---- [ Total Length ]        
        self.ip_proto = IPPROTO_TCP                 # ---- [ Protocol ]        
        self.ipv4_checksum = 0           # ---- [ Check Sum ]        
        self.ip_saddr = inet_aton(self.src_ip)      # ---- [ Source Address ]        
        self.ip_daddr = inet_aton(self.dst_ip)      # ---- [ Destination Address ]
    
    def AssembleIPv4(self):
        self.ipv4_header = struct.pack('!2B3H2B' ,
        self.ip_ver,        # IP Version 
        self.ip_dfc,        # Differentiate Service Field
        self.ip_tol,        # Total Length
        self.ip_idf,        # Identification
        self.ip_flg,        # Flags
        self.ip_ttl,        # Time to leave
        self.ip_proto        # protocol
        )    
        self.ipv4_header += struct.pack('<H' ,
        self.ipv4_checksum         # Checksum
        )
        self.ipv4_header += struct.pack('!4s4s' ,
        self.ip_saddr,        # Source IP 
        self.ip_daddr        # Destination IP
        )

## -- L4 - UDP Section ---- ##            
    def CreateTCP(self):          
        self.tcp_seq = 696969
        self.tcp_ack_seq = 0
        self.tcp_hdr_len = 80

        tcp_urg = 0
        tcp_ack = 0
        tcp_psh = 0
        tcp_rst = 1
        tcp_syn = 0
        tcp_fin = 0

        tcp_doff = 5
        self.tcp_offset_res = (tcp_doff << 4) + 0
        self.tcp_flags = tcp_fin + (tcp_syn << 1) + (tcp_rst << 2) + (tcp_psh << 3) + (tcp_ack << 4) + (tcp_urg << 5)

        self.tcp_wdw = htons(5840)
        self.tcp_checksum = 0
        self.tcp_urg_ptr = 0
        self.padding = b'\x00'*12

    def AssembleTCP(self):
        self.tcp_header = struct.pack('!2H2L2B3H',
        self.sport,
        self.dport,
        self.tcp_seq,
        self.tcp_ack_seq,
        self.tcp_offset_res,
        self.tcp_flags,
        self.tcp_wdw,
        self.tcp_checksum,
        self.tcp_urg_ptr
        )

    def PseudoHeader(self):
        pseudo_header = b''
        pseudo_header += inet_aton(self.src_ip)
        pseudo_header += inet_aton(self.dst_ip)
        pseudo_header += struct.pack('!2BH', 0, 6, 54)
        if (self.to_server):
            pseudo_header += self.nat_port + self.tcp_header[2:16] + b'\x00\x00' + self.tcp_header[18:]
        else:                   
            pseudo_header += self.tcp_header[0:2] + self.client_port + self.tcp_header[4:16] + b'\x00\x00' + self.tcp_header[18:]     
        pseudo_packet = pseudo_header
        
        tcp_checksum = self.Checksum.TCP(pseudo_packet)

        return tcp_checksum