How to tunnel multicast traffic

multicastnetcattcpdumptcpreplay

I am trying to receive multicast on 1 machine, forward it to another machine, and then replay it on that machine.

  • test_env: the machine which has access to the original multicast stream
  • mcast_sender: the machine which I'm trying to forward the multicast to and re-multicast from

What I've tried so far:

Combining tcpdump, netcat and tcpreplay I've attempted the following:

on test_env:

I have a python script which performs an IGMP join and just sits there forever, reading from the socket and discarding the data (just keeping the socket open)

$ ./mcast_sub INADDR_ANY 239.194.5.1 21001 &

Now the interface in question will be receiving multicast data, so I can run a tcp_dump:

$ sudo tcpdump -i eth5 host 239.194.5.1 > /tmp/capture.pcap

I can now run tail on the pcap file, and pipe it to netcat

$ tail -f /tmp/capture.pcap -n+1 | nc -l 12345

on mcast_sender:

On mcast_sender I can then receive this data from the netcat port, and dump it to a local file there:

$ nc test_env 12345 > /tmp/capture.pcap

Using tcpreplay I can then read the capture file on mcast_sender and replay it

$ sudo tcpreplay --intf1=eth8 /tmp/capture.pcap

My problem:

The tcpdumpnetcat pipeline seems to be working. I've verified that I am writing a file on mcast_sender.

However, when I attempt to run tcpreplay on it, I get an error:

$ sudo tcpreplay --intf1=eth8 /tmp/capture.pcap
Failed: Error opening pcap file: unknown file format

Questions:

  • Is it possible to do what I'm trying here?
  • Why is the file written on mcast_sender invalid?
  • Is there a better way to achieve what I'm trying to do here?

Best Answer

This isn't working because you need to set tcpdump's stdout to be line buffered

From man tcpdump:

-l     Make stdout line buffered.  
         Useful if you want to see the data while capturing it.  

       E.g.
            tcpdump -l | tee dat 
            tcpdump -l > dat & tail -f dat

You can also do away with the intermediate file and netcat by piping the output of tcpdump directly into tcpreplay.

This is achieved by running the tcpdump over an ssh session, dumping the output to stdout, and piping that to stdin of tcpreplay:

Run a command over an ssh session:

$ ssh remote_server "command"

Run tcpdump and output to stdout, line buffered:

$ sudo tcpdump ... -l -w -

Run tcpreplay reading from stdin:

$ sudo tcpreplay ... -

Putting it all together:

$ ssh test_env "sudo tcpdump -i eth5 host 239.194.5.1 -l -w -" | 
    sudo tcpreplay --intf1=eth8 -