How to sniff network packets on a remote server with Wireshark
My current task at work is to migrate one of our Radius servers from FreeRADIUS to our custom implementation.
While there are some conventions in place, while working around these technologies I have observed that the presence and compositions of some fields can be rather arbitrary, and heavily depend on who is sending you the Radius packets. So I decided to first take a good look at what was coming through.
I’m not really a network guy but I really enjoy digging in unfamiliar areas to see what’s under the hood, and this seemed too great an opportunity not to seize it.
I have sniffed network packets with tcpdump
before, but I did so with the finesse of a caveman, ssh’ing in the remote instance, running tcpdump
directly in the shell, and then accessing the instance via sFTP
to download the .pcap
file to finally open it in Wireshark.
This time when approaching the problem, I guessed that there must have been a way to hook up Wireshark directly with the remote instance, and it turns out I was right! It was actually rather easy, these were the steps:
DISCLAIMER: These instructions are for Unix-based systems, so Linux and Mac. The steps would probably look similar on Windows but the commands will definitely differ.
- Create a named pipe via the command
mkfifo
- Start Wireshark from the shell, with instructions to listen to the newly created pipe
- Run
tcpdump
viassh
directly from my local shell into the remote shell and routed the output to the named pipe
Let’s review the steps in greater detail:
Create a named pipe
mkfifo /tmp/remote
This is a bash command to create a pipe with a name. If you are not familiar with pipes think of it as a queue. It appears as a file in your filesystem but it doesn’t actually write on disk. Anything that is routed to it will just reside in memory so it’s not a way to store data, but only a non-opinionated way to allow different systems to communicate.
I’ve called the pipe remote
and placed it in the root tmp
folder but you can call it whatever and place it wherever.
This pipe will be receiving the output from the tcpdump
process being run remotely while Wireshark will be listening from it.
Start Wireshark from the shell
wireshark -k -i /tmp/remote
wireshark
starts wireshark
-k
starts recording immediately
-i /tmp/remote
defines the pipe that we just created as an input source
Here we are starting a recording session on Wireshark and instructing it to listen from our newly created pipe as its sole input source.
Run tcpdump
on your remote server and route the output to the named pipe
ssh -i ".ssh/your_key.pem" user@1.2.3.4 "sudo tcpdump -U -n -w - -i ens5 udp and '(port 1812 or port 1813)'" > /tmp/remote
This is the one-liner that definitely took a little more work than the rest. Let’s get into it:
ssh -i ".ssh/your_key.pem" user@server ... > /tmp/remote
This is your typical ssh
command to reach a remote instance. The -i
flag might not be necesssary in some cases. The important thing here is that by placing a string after the user/server combination it will try to execute it after logging into the remote server, similar to a docker run
execution.
Notice how at the end of the tcpdump
command the output is directed towards our named pipe.
Now let’s look at the tcpdump
command:
sudo tcpdump -U -n -w - -i ens5 udp and '(port 1812 or port 1813)'
-U
: This option makestcpdump
write packets to a file as soon as they are received. This is really important because thanks to it Wireshark will start displaying packets as soon as they’re dropped in the pipe, instead of having to wait for the capture session to finish.-n
: This option preventstcpdump
from converting addresses (like IP addresses, port numbers, etc.) to names.-w -
: This option tellstcpdump
to write the raw packets to standard output (-
).-i ens5
: This option specifies the network interface thattcpdump
should listen on. In this case, it's listening onens5
.ens5
is an AWS-specific interface. Normally it would beeth0
.udp
: The RADIUS protocol runs over UDP and that’s why we’re specifying it here.'(port 1812 or port 1813)'
:tcpdump
syntax meaning to capture packets traveling through port 1812 OR port 1813. Other logical operators likeand
andnot
are available to mix and match conditions.
Result
Damn it felt satisfying to see those packets rolling in!