Nipper - the Neat Internet Protocol Packet Editor
by Sami Pönkänen and Marko Lyijynen
Nipper - the Neat Internet Protocol Packet EditoR - is a tool for testing networks and network applications. More specifically it is used to create arbitrary packets and to send them to network or directly to applications. Nipper is written in Java and uses portions of C-code and Linux raw sockets.
The need for a tool like Nipper came up in a networking project when we started testing and debugging our software. Numerous tools exist for network testing; those we use most frequently include tcpdump and ethereal for sniffing, ping for connectivity checking and nmap and nessus for scanning of security holes. However, we were unable to find an elegant, simple tool that could create arbitrary IP packets and send them to network or directly to applications.
Instead of coding a quick and dirty, use-and-throw-away type program, we decided to design and implement a customisable tool that would have a simple, user-friendly GUI. In the first place, it would be used quite extensively in the project, and therefore needed to be user-friendly. Further, we also wanted to be able to use it in other projects, meaning it needed to be customisable and extensible, and if possible, able to run on OSes other than Linux (although Linux is what we use most frequently). Java was therefore the natural language to choose.
Nipper turned out to be very usable, and we thought it might prove popular as a starting point for building other tools. Consequently we decided to go open source with Nipper. Nipper was released under VTT Public License.
Nipper's Architecture and Features
Nipper has three main components: PacketEditor is the GUI, PacketEngine is where all the real work is done and Network Interfaces are the components that deliver the packets. See Figure 1 for a diagram of the Nipper internals. The reason for a three-layer architecture is customisability. We wanted the ability to switch between Network Interfaces, to add new protocols to PacketEngine and maybe someday to use one GUI to control many PacketEngines on different hosts.
|Figure 1: Nipper architecture.
PacketEditor takes its input from the user. The user can create new packets, add protocol headers and payload to them and fill in values for different header fields. This input is stored in an XML format description that can be saved and loaded from a file. An example of an XML description is shown in Figure 2.
|<?xml version = '1.0' encoding = 'UTF-8' ?>
<data>GET http://www.vtt.fi HTTP/1.0</data>
|Figure 2: XML description of a HTTP request.
PacketEditor passes the XML description to PacketEngine where the real action happens. PacketEngine builds a number of real packets from the XML input. Inside PacketEngine, different protocols are represented by Java classes that perform the actual conversion of XML parameters to byte-format protocol headers. Each protocol class has a set of rational default values for fields which the user has left blank. Tasks like checksumming and calculation of length fields are also done within the protocol classes. Nipper currently includes basic support for IPv4, IPv6, ICMPv4, TCP and UDP protocols and payload data. Partial implementation of Mobile IPv4 is also included.
After the packets are built, PacketEngine starts sending them one by one. This happens by passing the byte array to a Network Interface component. At present there are two Network Interfaces to choose from: PacketDumper and PacketSender. As the name implies, PacketDumper simply dumps the byte-format packets to a debug window. PacketSender uses the Java Native Interface (JNI) and Linux raw sockets to send the packets to network. Currently PacketSender is able to send both IPv4 and IPv6 packets.
So let's take Nipper for a test drive. As an example we show you how to build and send a packet with IPv4 and UDP headers and a string 'hello world!' as payload. Note that using raw sockets (the PacketSender) requires root privileges.
Figure 3 shows the main window of Nipper. In the lower part of the window is the set of packets with one packet visible. Select the packet and pick IPv4 from the tabs in the top part of the window. Fill in values for different IPv4 fields or leave some fields blank and let Nipper use default values. In Figure 2 we have set the source and destination addresses and the TTL field. Click on 'Add to packet' to add the IPv4 header to the packet you selected earlier. Do the same for UDP and Payload (under the 'Other' tab).
|Figure 3: Nipper mainwindow.
|Figure 4: Network Interface selection.
|Figure 5: Nipper debug window.
Next you need to select a Network Interface. Go to the 'PacketEngine' menu and 'Set network interface'. Available Network Interfaces are listed on the dialogue box shown in Figure 4. Select 'RawSocket'.
Now you are ready to send the packet to network. Open a shell and start tcpdump if you want to see whether the packet causes any reaction. Then click on 'Send packet(s)'. A debug window opens up and if everything goes as planned you should see some activity in your tcpdump and a report as shown in Figure 5.
The verbosity of debug messages can be adjusted via the 'PacketEngine' menu. For more information about using Nipper, consult the Nipper User's Guide, which is available at the open source site of VTT.
Adding new protocols to Nipper is quite straightforward. We suggest taking a closer look at one of the existing protocols and reading the files under doc/ in the Nipper package. The source code includes JavaDoc documentation.
Network Interfaces can also easily be added. One could for instance create a Network Interface that uses the tun/tap device instead of raw sockets. Again, take a look at existing source code and the documentation bundled with Nipper!
Marko Lyijynen, VTT
Tel: +358 9 456 4311
Sami Pönkänen, VTT
Tel: +358 9 456 7232