UDP多播客户端看不到tcpreplay生成的UDP多播流量

UDP多播客户端看不到tcpreplay生成的UDP多播流量,udp,multicast,tcpdump,Udp,Multicast,Tcpdump,我有两个项目: 服务器。。。它在选定的多播上生成UDP通信 听众。。。它在选定的多播上打印UDP流量 (它订阅多播并打印 无论它收到什么) 当我在一台机器上运行服务器,在另一台机器上运行侦听器时,侦听器会看到UDP通信并正确打印。因此,这些项目应该处于良好状态 但是,当我尝试使用tcpdump在任何机器上捕获流量时: sudo tcpdump -i eth0 'dst 233.65.120.153' -w 0.pcap sudo tcpdump -i eth0 'dst 233.65.12

我有两个项目:

  • 服务器。。。它在选定的多播上生成UDP通信
  • 听众。。。它在选定的多播上打印UDP流量 (它订阅多播并打印 无论它收到什么)
当我在一台机器上运行服务器,在另一台机器上运行侦听器时,侦听器会看到UDP通信并正确打印。因此,这些项目应该处于良好状态

但是,当我尝试使用tcpdump在任何机器上捕获流量时:

sudo tcpdump -i eth0 'dst 233.65.120.153' -w 0.pcap
sudo tcpdump -i eth0 'dst 233.65.120.153' -X
当我稍后尝试在任何机器上用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' -w 0.pcap
sudo tcpdump -i eth0 'dst 233.65.120.153' -X
我的问题:如果我想tcpreplay我正在创建的UDP多播通信量,以便我可以在应用程序级别(例如我的侦听器程序)上看到它,而不仅仅是通过tcpdump,我应该做些什么(不同的做法)

$cat 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);
     }
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义端口64968
#定义组“233.65.120.153”
main(int argc,char*argv[])
{
地址中的结构sockaddr\u;
int-fd,cnt;
结构ip_mreq mreq;
char*message=“abcd”;
/*创建看起来像普通UDP套接字的内容:
AF_INET…IPv4
SOCK_DGRAM…UDP
0…所需常数
*/
if((fd=套接字(AF_INET,SOCK_DGRAM,0))<0){
佩罗(“插座”);
出口(1);
}
/*设置目标地址:
AF_INET…IPv4
组…多播组的IP地址
我们要多播到的
端口…要在其上进行多播的UDP端口
*/
memset(&addr,0,sizeof(addr));
地址sinu family=AF\u INET;
地址sin\u addr.s\u addr=inet\u addr(组);
地址sin_端口=htons(端口);
/*现在只发送到我们的目的地*/
而(1){
if(发送到(fd,message,strlen(message),0,(struct sockaddr*)&addr,sizeof(addr))<0){
perror(“sendto”);
出口(1);
}
睡眠(1);
}
}
$cat 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");
     }
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义端口64968
#定义组“233.65.120.153”
#定义MSGBUFSIZE 1000000
字符msgbuf[MSGBUFSIZE];
main(int argc,char*argv[])
{
地址中的结构sockaddr\u;
int fd,nbytes,addrlen;
结构ip_mreq mreq;
u_int yes=1;
/*创建看起来像普通UDP套接字的内容:
AF_INET…IPv4
SOCK_DGRAM…UDP
0…所需常数
*/
if((fd=套接字(AF_INET,SOCK_DGRAM,0))<0){
佩罗(“插座”);
出口(1);
}
/*允许多个套接字使用相同的端口号:
SOL_套接字…操纵套接字API本身的属性
所以_REUSEADDR…允许为绑定重用本地地址
*/
if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes))<0){
perror(“重用地址失败”);
出口(1);
}
/*设置目标地址*/
memset(&addr,0,sizeof(addr));
地址sinu family=AF\u INET;
地址sin_addr.s_addr=htonl(INADDR_ANY);/*N.B.:与发件人不同*/
地址sin_端口=htons(端口);
/*绑定到接收地址*/
if(bind(fd,(struct sockaddr*)&addr,sizeof(addr))<0){
佩罗(“绑定”);
出口(1);
}
/*使用setsockopt()请求内核加入多播组*/
mreq.imr\u multiaddr.s\u addr=inet\u addr(组);
mreq.imr\u interface.s\u addr=htonl(INADDR\u ANY);
if(setsockopt(fd、IPPROTO_IP、IP_ADD_MEMBERSHIP和mreq、sizeof(mreq))<0){
perror(“setsockopt”);
出口(1);
}
/*现在只需进入一个读打印循环*/
而(1){
addrlen=sizeof(addr);
memset(msgbuf,0,MSGBUFSIZE);
如果((nbytes=recvfrom)(fd,msgbuf,MSGBUFSIZE,0,
(结构sockaddr*)&addr,&addrlen))<0){
perror(“recvfrom”);
出口(1);
}
printf(“传入消息大小=%d\n”,n字节);
int i;
对于(i=0;i
据我所知,不能在同一个框中执行此操作,tcpreplay会绕过主机的 路由表并向接口发送通信量


您必须在不同的框中启动侦听器。并确保启用了多播。因为在默认情况下,交换机会丢弃多播通信。

我们也遇到了同样的问题。通过
tcpdump
我们看到了数据;但是,多播客户端/侦听器没有拾取数据。然后我们意识到反向路径过滤器(rp\u过滤器)正在拒绝数据包

禁用rp筛选器后,客户端/侦听器应用程序开始拾取数据包。使用以下命令禁用rp_过滤器:

echo 0>/proc/sys/net/ipv4/conf/eth0/rp\u过滤器


在上面的示例中,如果不是eth0,请将“eth0”替换为接收多播的接口。在我的示例中,我需要通过设置正确的目标MAC地址来调整pcap文件。还应重新计算校验和。是的,“tcpreplay”需要2台主机。没有这些,我挣扎了很长时间,但只有“tcpdump”显示了重播的流,而不是我的多播监听应用程序:(


这是我的文章的链接:

这只是一个理论,但可能是由于数据包的校验和错误而被接收方丢弃

如果运行tcpdump的计算机启用了IP或UDP校验和卸载,则可能会发生这种情况。这意味着您在本地捕获的包尚未计算其校验和,而硬件在将其发送出去之前会这样做。然后tcpreplay这些包时