Inspirel banner

YAMI4 Tip #8 - Easy Sniffer

This tip presents an easy way to intercept YAMI4 messages for further analysis.

Even though sniffing network traffic is a general concept that can be used for any kind of traffic, this article was motivated by the work that was done with YAMI4 on very small embedded systems with constrained memory. On such systems it is important to properly predict all buffer sizes that will be needed for communication in order to avoid excessive memory allocations. This is possible only if we know exactly how big are the expected network packets.

There exist specialized network sniffers and traffic analyzers, but simple sniffing does not require anything other than basic Unix/Linux tools - the most important being the standard nc command.

One-way communication

One-way communication takes places when the client connects to the server and sends some data to it, but does not expect any response (and the server does not produce any).

The YAMI4 package contains a simple "print" example, implemented in every supported programming language, which sends data only in one direction. That is, if the server is started in the following way:

$ ./server tcp://localhost:12345
The server is listening on tcp://127.0.0.1:12345

and the client like this:

$ ./client tcp://localhost:12345

then any text that is typed in the client console will be transmitted, line by line, to the server with nothing being sent back.

This is quite easy to intercept with the nc command - run this in a separate terminal:

$ nc -l 12345 > request.bin

Then, run the client as usual and terminate its input stream by pressing Ctrl-D:

$ ./client tcp://localhost:12345
Hello!
^D

You should see a new file named request.bin of size 168 bytes. This is exactly the size of the complete message that is sent from client to server in this particular example.

Interestingly, it is possible to "send" this stored message to the server - start the server again:

$ ./server tcp://localhost:12345
The server is listening on tcp://127.0.0.1:12345

and then send it the already stored message with another invocation of nc in a separate terminal:

$ nc localhost 12345 < request.bin

You should see "Hello!" displayed at the server console.

The exercise above was an easy way to intercept the one-way message and inspect it. Most importantly, it was possible to learn its exact size.

Two-way communication

The two-way communication can be seen in a full client-server roundtrip where the client sends some request to the server and the server sends back a response.

The YAMI4 package has a separate "calculator" example that uses this type of communication.

Intercepting this kind of traffic is more difficult, but it also can be done with a set of simple Unix commands. The only difficulty is to ensure that the reply can be sent back to client over the same physical connection, so the trick is to run two nc commands (to intercept request and response separately) and provide some channel in the opposite direction. A simple pipeline cannot do it, but we can cheat a bit with additional FIFO queue created in the same directory:

$ mkfifo reply-channel

The FIFO is a special file that can be written to and read from at the same time by separate processes - now the complete "sniffer" can be set up with this command:

$ nc -l 12346 < reply-channel | tee request.bin | nc localhost 12345 | tee response.bin > reply-channel

This might look scary, but can be dissected into separate components for better understanding:

Uff!

Note, however, that even though the actual server listens on port 12345, the client should connect to 12346, as this is where our "sniffer" expects connections, so:

$ ./client tcp://localhost:12346 100 5

After receiving response, the client disconnects and this also causes the whole sniffer to close down, leaving two files: request.bin of size 180 and response.bin of size 156.

This exercise can be useful for those programmers who try to debug or implement the YAMI4 communication protocol and for those who work with very tiny embedded devices and need to know what are the expected buffer sizes in order to properly manage available resources.

Previous tip: Connect Or Not