While playing with network packets, you may need to replay traffic by reading from a previously saved pcap
file. In that case, you'd like to read the pcap
file and modify the source or destination IP addresses before sending them.
Let us use Scapy
to read a previously saved pcap
file. If you don't have a pcap
file, you can use the Saving packets in the pcap format using pcap dumper recipe of this chapter to do that.
Then, parse the arguments from the command line and pass them to a send_packet()
function along with the parsed raw packets.
Listing 9.6 gives the code for replaying traffic by reading from a saved pcap
file, as follows:
#!/usr/bin/env python # Python Network Programming Cookbook -- Chapter - 9 # This program is optimized for Python 2.7. # It may run on any other version with/without modifications. import argparse from scapy.all import * def send_packet(recvd_pkt, src_ip, dst_ip, count): """ Send modified packets""" pkt_cnt = 0 p_out = [] for p in recvd_pkt: pkt_cnt += 1 new_pkt = p.payload new_pkt[IP].dst = dst_ip new_pkt[IP].src = src_ip del new_pkt[IP].chksum p_out.append(new_pkt) if pkt_cnt % count == 0: send(PacketList(p_out)) p_out = [] # Send rest of packet send(PacketList(p_out)) print "Total packets sent: %d" %pkt_cnt if __name__ == '__main__': # setup commandline arguments parser = argparse.ArgumentParser(description='Packet Sniffer') parser.add_argument('--infile', action="store", dest="infile", default='pcap1.pcap') parser.add_argument('--src-ip', action="store", dest="src_ip", default='1.1.1.1') parser.add_argument('--dst-ip', action="store", dest="dst_ip", default='2.2.2.2') parser.add_argument('--count', action="store", dest="count", default=100, type=int) # parse arguments given_args = ga = parser.parse_args() global src_ip, dst_ip infile, src_ip, dst_ip, count = ga.infile, ga.src_ip, ga.dst_ip, ga.count try: pkt_reader = PcapReader(infile) send_packet(pkt_reader, src_ip, dst_ip, count) except IOError: print "Failed reading file %s contents" % infile sys.exit(1)
If you run this script, it will read the saved pcap
file, pcap1.pcap
, by default and send the packet after modifying the source and destination IP addresses to 1.1.1.1
and 2.2.2.2
respectively, as shown in the following output. If you use the tcpdump
utility, you can see these packet transmissions.
# python 9_6_replay_traffic.py ... Sent 3 packets. Total packets sent 3 ---- # tcpdump src 1.1.1.1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes ^C18:44:13.186302 IP 1.1.1.1.www > ARennes-651-1-107-2.w2- 2.abo.wanadoo.fr.39253: Flags [P.], seq 2543332484:2543332663, ack 3460668268, win 65535, length 179 1 packets captured 3 packets received by filter 0 packets dropped by kernel
This recipe reads a saved pcap
file, pcap1.pcap
, from the disk using the PcapReader()
function of Scapy
that returns an iterator of packets. The command-line arguments are parsed if they are supplied. Otherwise, the default value is used as shown in the preceding output.
The command-line arguments and the packet list are passed to the send_packet()
function. This function places the new packets in the p_out
list and keeps track of the processed packets. In each packet, the payload is modified, thus changing the source and destination IPs. In addition to this, the checksum
packet is deleted as it was based on the original IP address.
After processing one of the packets, it is sent over the network immediately. After that, the remaining packets are sent in one go.
3.135.247.68