Docker及本地环境下tcpreplay注入UDP包至主机网卡无法接收问题
同一主机dummy接口注入UDP数据包后,C套接字无法接收的问题
操作步骤
创建dummy接口
为了在本地模拟另一块以太网接口注入UDP包,我创建了dummy接口,执行以下命令:
sudo modprobe dummy sudo ip link add eth0 type dummy ip link show eth0 sudo ifconfig eth0 hw ether 02:5d:6c:e8:8d:b2 sudo ip addr add 192.168.50.50/24 broadcast 192.168.50.255 dev eth0 sudo ip link set dev eth0 arp on sudo ip link set eth0 promisc off sudo ip link set eth0 multicast on sudo ip link set dev eth0 up
配置完成后,接口信息如下:
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.50.50 netmask 255.255.255.0 broadcast 192.168.50.255 inet6 fe80::5d:6cff:fee8:8db2 prefixlen 64 scopeid 0x20<link> ether 02:5d:6c:e8:8d:b2 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 935342 bytes 1167225106 (1.1 GB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
修改PCAP并注入流量
使用tcprewrite修改.pcap文件的IP和MAC地址以适配dummy接口:
sudo tcprewrite --srcipmap=192.168.50.51:192.168.50.50 --dstipmap=192.168.50.50:192.168.50.50 --infile=my.pcap --enet-dmac=ff:ff:ff:ff:ff:ff,02:5d:6c:e8:8d:b2 --enet-smac=60:76:88:00:00:00,02:5d:6c:e8:8d:b2 --outfile=out.pcap
随后注入UDP流量:
sudo tcpreplay -l 0 -v --intf1=eth0 out.pcap
抓包验证
用Wireshark抓包可见数据包已注入eth0:
33312 20.472560871 192.168.50.50 192.168.50.50 UDP 1248 2368 → 2368 Len=1206
tcpdump抓包显示主机名而非IP,但数据包确实存在:
09:39:10.168498 IP <my_machine_name>.2368 > <my_machine_name>.2368: UDP, length 1206
C语言UDP接收程序
我编写的标准UDP套接字程序已正确绑定,但始终阻塞在recvfrom()处:
#include <iostream> #include <cstring> #include <arpa/inet.h> #include <unistd.h> #include <fcntl.h> #include <iostream> #include <cstring> #include <sys/socket.h> #include <netinet/if_ether.h> #include <netinet/ip.h> #include <arpa/inet.h> #include <netpacket/packet.h> #include <net/ethernet.h> #include <net/if.h> #include <sys/ioctl.h> #define PORT 2368 #define BUFFER_SIZE 2048 int main() { int udp_socket; struct sockaddr_in server_address, client_address; socklen_t client_address_len = sizeof(client_address); char buffer[BUFFER_SIZE]; // Create UDP socket udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (udp_socket < 0) { perror("Error creating socket"); exit(EXIT_FAILURE); } // Bind the socket to a specific address and port memset(&server_address, 0, sizeof(server_address)); server_address.sin_family = AF_INET; server_address.sin_port = htons(PORT); server_address.sin_addr.s_addr = INADDR_ANY; if (bind(udp_socket, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) { perror("Bind error"); close(udp_socket); exit(EXIT_FAILURE); } printf("Listening for UDP packets on port %d...\n", PORT); // Receive and process UDP packets while (1) { int bytes_received = recvfrom(udp_socket, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_address, &client_address_len); if (bytes_received < 0) { perror("recvfrom error"); close(udp_socket); exit(EXIT_FAILURE); } // Process the received packet (contained in 'buffer') printf("Received UDP packet from %s:%d with length: %d\n", inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port), bytes_received); // Print the packet contents for (int i = 0; i < bytes_received; ++i) { printf("%02x ", buffer[i]); } printf("\n"); } // Close the UDP socket (not reached in this example) close(udp_socket); return 0; }
Docker环境测试
我也在Docker环境中测试,执行命令:
docker run --net host --rm -t -v /home/myhostFolder:/data -i dgarros/tcpreplay /usr/bin/tcpreplay --intf1=eth0 docker.pcap
在本地Docker接口中可见tcpreplay发出的数据包,但上述C语言套接字程序仍阻塞在recvfrom()处。
问题
请问这是什么原因?是否是tcpreplay在同一台电脑注入数据包存在限制?
内容的提问来源于stack exchange,提问作者Alberto Lara
相关产品推荐
相关产品推荐

