使用Wireshark时,我们一般加载已经保存的数据文件或者实时抓取网卡上的数据包,进行数据分析。 有时为了监控远程机器网络流量,我们需要远程抓包,并对抓取的包进行实时分析。这时候,我们需要在远程捕获网络流量,并在本地启动wireshark进行数据分析。为实现这个目的,这时候我们就面临一下几个问题:
1.远程主机上如何抓包:远程主机OS是windows还是linux
2.本地主机和远程主机通过什么连接:ssh、netcat,还是其他协议
3.远程主机数据如何传到本地:是传到named pipe(命名管道)还是stdout
根据wireshark wiki文档,我们知道目前有这三种解决方案:
- /Pipes下文主要讨论这种方式
- /WinPcapRemote - using [WinPcap]'s remote capturing feature (rpcapd) - currently not supported在windows下安装winpcap后,winpcap安装目录下就有rpcapd这个命令行工具,但wireshark目前不支持读取rpcapd的输出,可以用其他工具读取rpcapd的输出。这种方式只限于windows操作系统。
- RMON - use SNMP's RMON to capture - currently not supported ("Remote Packet Capture Using RMON" explains why it doesn't work well)这种方式不清楚怎么用
测试一:named pipe on local machine (本地named pipe测试)
利用管道,将libpcap数据文件作为输入,输出到tshark,开始分析
local machine : 192.168.1.86
hank@gts ~ $mkfifo /tmp/pipe
hank@gts ~ $./tshark -i /tmp/pipe &
hank@gts ~ $cat /home/hank/net-data/iups.cap > /tmp/pipe &
测试二:SSH + pipe
利用ssh登录远程主机,发送抓包命令,并将捕获的数据包发送到本地的named pipe,本地tshark监听该named pipe,有数据即开始分析。
remote machine : 192.168.1.82
local machine : 192.168.1.86
开启一个终端,执行:
hank@gts ~ $mkfifo /tmp/pipe
hank@gts ~ $ssh root@192.168.1.82 "tcpdump -w - -i eth0" > /tmp/pipe
开启另一个终端,执行:
hank@gts ~/wireshark-dev/bin $ ./tshark -i /tmp/pipe
在http://wiki.wireshark.org/CaptureSetup/Pipes中,执行ssh登录时,没有将输出重定向到pipe中去,于是我对该wiki做了修改,修改记录为:
CaptureSetup/Pipes (last edited 2009-05-14 08:02:36 by hankchan)
测试三:netcat
这个测试见《How to monitor packets from a remote interface in real time》 ,该方式设计三台计算机,并且使用了netcat,本地接听某个端口,远程主机将数据发送到该端口。
remote machine : 192.168.1.82
local machine : 192.168.1.86
本地主机执行:
hank@gts ~/wireshark-dev/bin $ nc -l -p 3000
远程主机执行:
[root@localhost ~]# cat /dev/urandom | nc 192.168.1.86 3000
本地另开一个终端,执行:
gts bin # ./tshark -i eth0 -R tcp.port==3000
综上,SSH + pipe 作为远程抓包是十分理想的方案,前提是能ssh登陆远程主机,并且远程主机上有抓包工具。
附英文原文如下:
Step 5: Capture traffic using a remote machine
Make sure you've finished step 4 successfully!
In this step: Don't use your local machine to capture traffic as in the previous steps but use a remote machine to do so.
Remote Capturing is currently very limited:
- /Pipes
- /WinPcapRemote - using [WinPcap]'s remote capturing feature (rpcapd) - currently not supported
- RMON - use SNMP's RMON to capture - currently not supported ("Remote Packet Capture Using RMON" explains why it doesn't work well)
Of course, you can use Wireshark installed on a remote machine in combination with a remote control software (e.g. VNC, Windows Remote Desktop, ...).
XXX - explain special capture filter strings relevant to remote capturing!
Pipes
The following will explain capturing using pipes a bit.
Contents
- Pipes
- Named pipes
- Remote Capture
- Special feeding application
- Stdin
Before pipes, Wireshark could read the captured packets to display either from a file (which had been previously created) or for a network interface (in real time). Since pipes are supported, Wireshark can also read packets from another application, and shows them in real time. This is useful if you want to watch a network in real time, and Wireshark cannot capture from that network, e.g. because it is not an Ethernet network, or it is not on the local machine.
There are three main limitations that you should be aware of:
- It is not currently known whether this works on Windows. If you want to use this on Windows, give it a try and report your results to the development list (and/or update this page). If you want to help testing, you should be able to compile Wireshark from sources.
- This only works with the de facto standard libpcap format version 2.4, as described in Development/LibpcapFileFormat. Some other formats may work in theory, but this has not been tested.
- Capturing from a pipe is inconvenient, because you have to set up the pipe and put a file header into the pipe before you can start the capture. A few patches have been mailed to the development list that could solve this, so if you find the approach inconvenient, try the patches.
XXX - mention to configure live update of the Wireshark window
Named pipes
A named pipe looks like a file, but it is really just a buffer for interprocess communication. One process can send data to it, and another process can read it. There are two main ways to create a named pipe: with mkfifo or using special syntax of the bash shell.
Way 1: mkfifo
If you have a capture file in the right format (from Wireshark or tcpdump), you can do the following:
> mkfifo /tmp/pipe > wireshark -k -i /tmp/pipe & > cat capture.cap > /tmp/pipe &
This should start a capture from the named pipe /tmp/pipe. After you start the last command, a list of packets from the file should start appearing on the screen.
An example of remote capture using pipes can be found in Jesús Roncero's blog.
Way 2: bash
You can do exactly the same with special bash syntax:
> wireshark -k -i
Way 3: python
The following small python script shows how to use python on Windows:
# Win32 Wireshark named pipes example # Requires Python for Windows and the Python for Windows Extensions: # http://www.python.org # http://sourceforge.net/projects/pywin32/ import win32pipe, win32file cf = open(r'c:pipetest.pcap', 'rb') p = win32pipe.CreateNamedPipe( r'.pipewireshark', win32pipe.PIPE_ACCESS_OUTBOUND, win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT, 1, 65536, 65536, 300, None) win32pipe.ConnectNamedPipe(p, None) data = cf.read() win32file.WriteFile(p, data)
Named pipes conclusion
In all of the above cases you cannot use the buttons in Wireshark to (re)start the capture, because the feeding process has no way of knowing that a new capture should be started. Also the feeding process may not be killed after Wireshark terminates. I think it is killed if you stop the capture before closing Wireshark, but I am not quite sure why.
There was a short discussion that the feeding process could detect that the pipe is not connected, and then restart the capture once it is connected again. So maybe this is possible, if you write the feeding process accordingly. There are also two patches that support reading from a TCP network connect (which has a define connection sequence), and from spawned child processes. Both patches should solve this specific problem.
Of course these examples are not really useful, because you could just read the file directly. In a real scenario, the feeding process would be either a remote capture process, or a special application.
Remote Capture
In bash syntax, remote capture is possible with the following command:
> wireshark -k -i
The main problem is that you have to exclude the traffic generated by the ssh session from capturing. Several patches are available to do this, but excluding port 22 is probably the easiest solution for now.
The second problem is that ssh cannot ask for a password on stdin. You should either set up ssh-agent, so that you don't need a password, or you should configure x-askpass to open a window for the password.
This can be worked around by combining SSH with a FIFO.
>mkfifo /tmp/pipe >ssh user@remote-host "tshark -w - not port 22"
In another terminal run the following:
>wireshark -k -i /tmp/pipe
As soon as Wireshark starts "listening" on the pipe, SSH will prompt for the password and allow you to continue. Wireshark can also be switched out for dumpcap and tcpdump can be used in place of tshark with slight variations on the above commands.
Special feeding application
Sometimes you want to display traffic from a network that is not accessible to the usual capture tools like tshark, tcpdump and snoop. You may have your own application to capture the traffic, and Wireshark can read the capture files, but how do you interface it with Wireshark to show traces in real time?
Pipes are the answer. As long as you use the de facto standard libpcap format, you should be able to write the capture to a named pipe, and view the packets in real time with Wireshark reading from this pipe.
Stdin
As described in the man page, you can use the minus sign for the interface name to capture from stdin. Stdin is a file descriptor that is predefined for every process, and it is usually connected to an anonymous pipe by the shell calling the process. So reading from stdin, you should be able to rewrite the command above to
> cat capture.cap | wireshark -k -i -
While the documentation says that Wireshark should be able to capture from stdin (which is an anonymous pipe), it is not clear whether it always works. Some people have reported success, but for me it only works with tshark, not with wireshark. Maybe this is related to the following bug?
Please note: this feature won't work with all versions of libiconv, as it will interpret the - sign as the start of a new parameter, see: bug #265
XXX - is this possible for both command line and interactive usage?