If you ever need to create a network packet and customize the source and destination IP or ports, this recipe can serve as the starting point.
We can take all the useful command-line arguments such as network interface name, protocol name, source IP, source port, destination IP, destination port, and optional TCP flags.
We can use the Scapy
library to create a custom TCP or UDP packet and send it over the network.
Listing 9.5 gives the code for customizing the IP address of a packet, 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 import sys import re from random import randint from scapy.all import IP,TCP,UDP,conf,send def send_packet(protocol=None, src_ip=None, src_port=None, flags=None, dst_ip=None, dst_port=None, iface=None): """Modify and send an IP packet.""" if protocol == 'tcp': packet = IP(src=src_ip, dst=dst_ip)/TCP(flags=flags, sport=src_port, dport=dst_port) elif protocol == 'udp': if flags: raise Exception(" Flags are not supported for udp") packet = IP(src=src_ip, dst=dst_ip)/UDP(sport=src_port, dport=dst_port) else: raise Exception("Unknown protocol %s" % protocol) send(packet, iface=iface) if __name__ == '__main__': # setup commandline arguments parser = argparse.ArgumentParser(description='Packet Modifier') parser.add_argument('--iface', action="store", dest="iface", default='eth0') parser.add_argument('--protocol', action="store", dest="protocol", default='tcp') parser.add_argument('--src-ip', action="store", dest="src_ip", default='1.1.1.1') parser.add_argument('--src-port', action="store", dest="src_port", default=randint(0, 65535)) parser.add_argument('--dst-ip', action="store", dest="dst_ip", default='192.168.1.51') parser.add_argument('--dst-port', action="store", dest="dst_port", default=randint(0, 65535)) parser.add_argument('--flags', action="store", dest="flags", default=None) # parse arguments given_args = parser.parse_args() iface, protocol, src_ip, src_port, dst_ip, dst_port, flags = given_args.iface, given_args.protocol, given_args.src_ip, given_args.src_port, given_args.dst_ip, given_args.dst_port, given_args.flags send_packet(protocol, src_ip, src_port, flags, dst_ip, dst_port, iface)
In order to run this script, enter the following commands:
tcpdump src 192.168.1.66 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes ^C18:37:34.309992 IP 192.168.1.66.60698 > 192.168.1.51.666: Flags [S], seq 0, win 8192, length 0 1 packets captured 1 packets received by filter 0 packets dropped by kernel $ sudo python 9_5_modify_ip_in_a_packet.py WARNING: No route found for IPv6 destination :: (no default route?) . Sent 1 packets.
This script defines a send_packet()
function to construct the IP packet using Scapy
. The source and destination addresses and ports are supplied to it. Depending on the protocol, for example, TCP or UDP, it constructs the correct type of packet. If the packet is TCP, the flags argument is used; if not, an exception is raised.
In order to construct a TCP packet, Sacpy
supplies the IP()
/TCP()
function. Similarly, in order to create a UDP packet, the IP()
/UDP()
function is used.
Finally, the modified packet is sent using the send()
function.
3.139.97.53