使用C++将完整的以太网数据包发送到特定的ip

Send full ethernet packet to specific ip using C++

本文关键字:ip 以太网 C++ 使用 数据包      更新时间:2023-10-16

我正在尝试将一个完整的数据包发送到特定的IP地址。关键是,我已经有了完整的二进制数据包,我不希望它被封装到任何额外的数据包标头中。这是我的逻辑:

std::string destination_ip = "127.0.0.1";
uint16_t destination_port = 8080;
int socket_fd;
struct sockaddr_in socket_attrs;
if ((socket_fd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))) < 0)
{
printf("Socket creation errorn");
return false;
}
memset(&socket_attrs, '0', sizeof(socket_attrs));
socket_attrs.sin_family = AF_INET;
socket_attrs.sin_port = htons(destination_port);
if(inet_pton(AF_INET, destination_ip.c_str(), &socket_attrs.sin_addr)<=0)
{
printf("Invalid IP address/ IP address not supportedn");
return false;
}
if (connect(socket_fd, (struct sockaddr *)&socket_attrs, sizeof(socket_attrs)) < 0)
{
printf("Connection Failedn");
return false;
}
if((write(socket_fd , <PACKET_DATA> , <PACKET_SIZE>)) < 0){
std::cout << "Error sending packets to the network" << std::endl;
exit(1);
}

输出:

Connection Failed

有人能帮我实现目标吗?

请特别使用libpcap、pcap_inject()。

您不能使用socket(),也不能使用IPPROTO_RAW,因为在这种情况下,L2(eth)和L3(ip)也将被操作系统的ip堆栈伪造。

您需要将数据包直接插入网卡。如果你想将其发送到不同于原始IP的IP,你必须"编辑"数据包内容。

从此处粘贴的示例:http://www.microhowto.info/howto/send_an_arbitrary_ethernet_frame_using_libpcap.html

char pcap_errbuf[PCAP_ERRBUF_SIZE];
pcap_errbuf[0]='';
pcap_t* pcap=pcap_open_live(if_name,65536,0,0,pcap_errbuf);
if (pcap_errbuf[0]!='') {
fprintf(stderr,"%s",pcap_errbuf);
}
if (!pcap) {
exit(1);
}
if (pcap_inject(pcap, <PACKET_DATA> , <PACKET_SIZE> )==-1) {
pcap_perror(pcap,0);
pcap_close(pcap);
exit(1);
}
pcap_close(pcap)

如果你不想编辑IP目的地,只有当你没有在两个对等端之间切换/路由器时,数据包才能到达线路的另一端。

作为替代方案,OP建议使用隧道。它实际上是有效的(我用tcpreplay测试了它)——你可以使用GRE隧道,它实际上也可以传输以太网流量。

在两个对等体上,您可以建立gretap隧道。我使用了以下命令:

在主机A上(其IP地址为192.168.1.211):

ip link add gretap1 type gretap local 192.168.1.211 remote 192.168.1.64
ip link set gretap1 up

在主机B上(其IP地址为192.168.1.64):

ip link add gretap1 type gretap local 192.168.1.64 remote 192.168.1.211
ip link set gretap1 up

在这一点上,可以使用L2 GRE隧道,并让它使用gretap1接口传输ETH流量。在一个对等机上,我用命令将流量注入隧道:

tcpreplay -i gretap1 test.pcap

在另一个对等体上,验证了流量是使用wireshark或tcpdump在gretap1接口上捕获的。

不幸的是,这个设置有一个问题:隧道的MTU比网络的MTU小,所以不能保证你能重放所有的数据包。