UDP多播客户端没有看到tcpreplay产生的UDP多播流量(UDP multicast clie

2019-08-02 23:46发布

我有两个方案:

  • 服务器...它生成一个选择的多播UDP流量
  • 听者...它打印在所选择的多播(它预订多播和打印任何其接收)的UDP通信。

当我运行某些(其他)机(S)在一台机器和听众的服务器,监听UDP看到流量和打印正确的。 因此,这些项目应该是在一个良好的状态。

然而,当我试图捕捉交通,无论机器上,使用tcpdump:

sudo tcpdump -i eth0 'dst 233.65.120.153' -w 0.pcap

当我后来尝试重播它,不管机器上,用tcpreplay:

sudo tcpreplay -i eth0 0.pcap

没有听众看到这些捕获的数据包:

09:38:40.975604 IP (tos 0x0, ttl 1, id 0, offset 0, flags [DF], proto UDP (17), length 32)
    172.27.6.176.53507 > 233.65.120.153.64968: [udp sum ok] UDP, length 4
    0x0000:  4500 0020 0000 4000 0111 6527 ac1b 06b0  E.....@...e'....
    0x0010:  e941 7899 d103 fdc8 000c 579c 6162 6364  .Ax.......W.abcd
    0x0020:  0000 0000 0000 0000 0000 0000 0000       ..............
09:38:41.975709 IP (tos 0x0, ttl 1, id 0, offset 0, flags [DF], proto UDP (17), length 32)
    172.27.6.176.53507 > 233.65.120.153.64968: [udp sum ok] UDP, length 4
    0x0000:  4500 0020 0000 4000 0111 6527 ac1b 06b0  E.....@...e'....
    0x0010:  e941 7899 d103 fdc8 000c 579c 6162 6364  .Ax.......W.abcd
    0x0020:  0000 0000 0000 0000 0000 0000 0000       ..............
09:38:42.975810 IP (tos 0x0, ttl 1, id 0, offset 0, flags [DF], proto UDP (17), length 32)
    172.27.6.176.53507 > 233.65.120.153.64968: [udp sum ok] UDP, length 4
    0x0000:  4500 0020 0000 4000 0111 6527 ac1b 06b0  E.....@...e'....
    0x0010:  e941 7899 d103 fdc8 000c 579c 6162 6364  .Ax.......W.abcd
    0x0020:  0000 0000 0000 0000 0000 0000 0000       ..............

请注意,即使没有听众看到UDP组播流量,我仍然能看到它,任何机器上,使用tcpdump:

sudo tcpdump -i eth0 'dst 233.65.120.153' -X

我的问题:我应该怎么做(不同的)如果我想tcpreplay我创造这样我可以看到它在应用层面(如我的监听程序),不仅tcpdump的UDP的组播流量?

$猫sender.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define PORT 64968
#define GROUP "233.65.120.153"

main(int argc, char *argv[])
{
     struct sockaddr_in addr;
     int fd, cnt;
     struct ip_mreq mreq;
     char *message="abcd";

     /* Create what looks like an ordinary UDP socket:
        AF_INET    ... IPv4
        SOCK_DGRAM ... UDP
        0          ... required constant
      */
     if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
      perror("socket");
      exit(1);
     }

    /* Set up destination address:
        AF_INET ... IPv4
        GROUP   ... the IP-address of the multicast group
                    to which we want to multicast
        PORT    ... the UDP port that on which we want to multicast
      */
     memset(&addr, 0, sizeof(addr));
     addr.sin_family=AF_INET;
     addr.sin_addr.s_addr=inet_addr(GROUP);
     addr.sin_port=htons(PORT);

     /* now just sendto() our destination! */
     while (1) {
      if (sendto(fd, message, strlen(message), 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
           perror("sendto");
           exit(1);
      }
      sleep(1);
     }
}

$猫listener.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define PORT 64968
#define GROUP "233.65.120.153"
#define MSGBUFSIZE 1000000

char msgbuf[MSGBUFSIZE];

main(int argc, char *argv[])
{
     struct sockaddr_in addr;
     int fd, nbytes,addrlen;
     struct ip_mreq mreq;

     u_int yes=1;

    /* Create what looks like an ordinary UDP socket:
       AF_INET ... IPv4
       SOCK_DGRAM ... UDP
       0 ... required constant
      */
    if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         perror("socket");
         exit(1);
    }

    /* Allow multiple sockets to use the same PORT number:
       SOL_SOCKET ... manipulate properties of the socket API itself
       SO_REUSEADDR ... Allow reuse of local addresses for bind
     */
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
       perror("Reusing ADDR failed");
       exit(1);
       }

     /* set up destination address */
     memset(&addr,0,sizeof(addr));
     addr.sin_family=AF_INET;
     addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
     addr.sin_port=htons(PORT);

     /* bind to receive address */
     if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
      perror("bind");
      exit(1);
     }

     /* use setsockopt() to request that the kernel join a multicast group */
     mreq.imr_multiaddr.s_addr=inet_addr(GROUP);
     mreq.imr_interface.s_addr=htonl(INADDR_ANY);
     if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
      perror("setsockopt");
      exit(1);
     }

     /* now just enter a read-print loop */
     while (1) {
      addrlen=sizeof(addr);
      memset(msgbuf, 0, MSGBUFSIZE);
      if ((nbytes=recvfrom(fd, msgbuf, MSGBUFSIZE,0,
                           (struct sockaddr *) &addr, &addrlen)) < 0) {
           perror("recvfrom");
           exit(1);
      }
      printf("Incoming message size = %d\n", nbytes);
      int i;
      for (i=0; i < nbytes; i++)
              printf("%02x ", ((unsigned char) msgbuf[i]));
      printf("\n");
     }
}

Answer 1:

我们有同样的问题。 随着tcpdump ,我们看到的数据; 然而,在组播客户端/监听器不拾取数据。 然后,我们意识到, 反向路径过滤器 (rp_filter)被拒绝数据包。

禁用RP-过滤器后,客户端/监听器应用程序启动拿起包。 使用以下命令禁用rp_filter:

echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter

在上述中,代替“的eth0”与所述接口接收多播如果比eth0的其他



Answer 2:

在我来说,我需要通过设置正确的目的MAC地址来调整PCAP文件。 另外,校验应重新计算。 是的,都需要“tcpreplay” 2个主机。 如果没有这些我打了很长时间,但只有“tcpdump的”显示重播流,不是我的组播侦听程序:(

这里是链接到我的文章: 通过转储/重播组播饲料步说明



Answer 3:

据我所知,你不能做到这一点在同一个盒子,tcpreplay绕过主机的路由表,并发送流量接口。

你必须开始在不同的盒子你的听众。 并确保组播被启用。 因为默认情况下,交换机将丢弃组播流量。



Answer 4:

This is just a theory, but it might be that the packets are discarded by the receiving side due to their checksums being wrong.

That could happen if the machine where you run tcpdump has IP or UDP checksum offloading enabled. That means the packages you capture locally haven't their checksums calculated yet, which the hardware does before sending them out. When you then tcpreplay those packets, the checksums are not calculated, as tcpreplay works on a lower level than the socket API you used to generate the packets.

In order to verify the correctness of the checksums (both those of the dump file as well as those of the packets spit out by the subsequent tcpreplay), tcpdump -v ... will warn you about wrong checksums. wireshark also colors wrongly checksummed frames differently (unless turned off in the wireshark settings).

Did you try to tcpdump the packets only on the sending host, or also on the receiving host? The latter would remove the checksum errors, if that is indeed your problem.



文章来源: UDP multicast client does not see UDP multicast traffic generated by tcpreplay