Linux:在KVM下未在本地接收原始套接字发送的数据包
我一直在尝试使用原始套接字发送UDP数据包,但是,发送的数据包不会在本地接收。如果发送到远程目的地,将接收相同的数据包。测试在KVM下进行。同样的测试似乎也在进行 插座设置为: 原始插座=插座(AF_数据包、SOCK_原始、htons(ETH_p_ALL)) 有一个接收过滤器连接,它被设置为滥交。正确接收数据包。发送的数据包在Wireshark中接收并正确分析。但是,本地程序(例如nc-l-u-p…)不接收数据包。如果我将相同的数据包发送到远程目的地,则数据包被正确接收。Wireshark接收数据包的事实表明,它没有被任何iptables规则丢弃(我还检查了所有丢弃规则计数器,没有丢弃的数据包) 如果这有意义的话,看起来数据包被路由了,但没有被网络堆栈重新处理 这应该是网络课程中的一个示例代码,现在,我在学生面前丢了脸。希望他们都不在这个名单上;-) 非常感谢您的帮助, 尤瓦尔 关于代码的一些注释。为简洁起见,UDP校验和设置为0,IP校验和从标头计算。这两个都由Wireshark验证(并且也被KVM上的远程机器接受)。代码解析消息,并在收到的缓冲区上发送回复。udp_hdr和ip_hdr指向数据包缓冲区(buffer)中相应的报头,而负载指向L7数据的开始 代码如下: { /*处理请求*/ 谢谢你的消息; int max_len=sizeof(buffer)-(有效负载-buffer); 国际tmp_港; in_addr_t tmp_ip; 结构乙醚添加tmp乙醚Linux:在KVM下未在本地接收原始套接字发送的数据包,linux,sockets,networking,Linux,Sockets,Networking,我一直在尝试使用原始套接字发送UDP数据包,但是,发送的数据包不会在本地接收。如果发送到远程目的地,将接收相同的数据包。测试在KVM下进行。同样的测试似乎也在进行 插座设置为: 原始插座=插座(AF_数据包、SOCK_原始、htons(ETH_p_ALL)) 有一个接收过滤器连接,它被设置为滥交。正确接收数据包。发送的数据包在Wireshark中接收并正确分析。但是,本地程序(例如nc-l-u-p…)不接收数据包。如果我将相同的数据包发送到远程目的地,则数据包被正确接收。Wireshark接收数
msg_len = parse_and_send (ctx, payload, size, max_len);
if (msg_len < 0)
{
/* Error */
error_print (ctx, "Failed to parse and construct answer.");
continue;
}
if (msg_len == 0)
{
/* No message to send. */
continue;
}
/* Switch sources & destinations and update payload lengths. */
tmp_port = udp_hdr->dest;
udp_hdr->dest = udp_hdr->source;
udp_hdr->source = tmp_port;
udp_hdr->len = htons (msg_len +
(payload - (const uint8_t*) udp_hdr));
tmp_ip = ip_hdr->daddr;
compute_udp_cksum (udp_hdr);
ip_hdr->daddr = ip_hdr->saddr;
ip_hdr->saddr = tmp_ip;
ip_hdr->tot_len = htons (msg_len +
(payload - (const uint8_t*) ip_hdr));
compute_ip_cksum (ip_hdr);
memcpy (tmp_ether.ether_addr_octet, ether_hdr->ether_dhost,
sizeof (tmp_ether));
memcpy (ether_hdr->ether_dhost, ether_hdr->ether_shost, ETH_ALEN);
memcpy (ether_hdr->ether_shost, tmp_ether.ether_addr_octet,
sizeof (tmp_ether));
if (sendto (ctx->raw_socket,
&buffer, msg_len + (payload - buffer), 0,
(struct sockaddr*) &ll_addr, sizeof (ll_addr)) < 0)
{
ERROR_SYSTEM (ctx, "Sending packet");
error_print (ctx, "Failed to send packet");
continue;
}
}
msg_len=parse_和发送(ctx、有效负载、大小、最大长度);
如果(消息长度<0)
{
/*错误*/
错误_print(ctx,“解析和构造答案失败”);
持续
}
如果(msg_len==0)
{
/*没有要发送的消息*/
持续
}
/*切换源和目的地并更新有效负载长度*/
tmp_端口=udp_hdr->dest;
udp_hdr->dest=udp_hdr->source;
udp_hdr->source=tmp_端口;
udp_hdr->len=htons(msg_len+
(有效负载-(常量uint8_t*)udp_hdr));
tmp_ip=ip_hdr->daddr;
计算udp校验和(udp hdr);
ip_hdr->daddr=ip_hdr->SADD;
ip_hdr->SADD=tmp_ip;
ip\U hdr->tot\U len=htons(msg\U len+
(有效载荷-(const uint8_t*)ip_hdr);
计算ip校验和(ip hdr);
memcpy(tmp_ether.ether_addr_octet,ether_hdr->ether_dhost,
sizeof(tmp_乙醚);
memcpy(以太hdr->以太dhost,以太hdr->以太shost,以太ALEN);
memcpy(Ethernet\u hdr->Ethernet\u shost,tmp\u Ethernet.Ethernet\u addr\u八位字节,
sizeof(tmp_乙醚);
如果(发送到)(ctx->raw_插座,
&缓冲区,msg_len+(有效负载-缓冲区),0,
(结构sockaddr*)&ll_addr,大小(ll_addr))<0)
{
错误_系统(ctx,“发送数据包”);
打印错误(ctx,“发送数据包失败”);
持续
}
}
让我们写下我们知道的事实:
1-您说过可以在数据包捕获程序中看到数据包(例如Wireshark)
2-您告诉我,当您将数据包发送到服务器时,无法使用netcat接收数据包
环回接口
3-您告诉我,当您将数据包发送到远程机器时,您可以接收数据包
因此,问题要么在代码中,要么在本地计算机中。我有很多建议:
1-在另一台机器上测试代码,并将数据包发送到环回接口,并尝试使用netcat捕获它们
或
2-尝试使用netcat向本地接口发送一组UDP数据包,并使用另一个netcat实例接收这些数据包,并检查其是否工作;如果成功,您知道问题出在您的代码中,否则问题可能是由于您的本地计算机造成的。如果Wireshark接收到数据包,并不意味着它们没有被丢弃;但是如果你检查一下就可以了。请确切地说明您在shell中用于接收数据包的命令。为了使其更简单,我使用了nc-l-u-p2222。在远程机器上工作正常。在本地机器(带有原始套接字)上,没有收到任何信息。您能给出用于发送数据包的代码吗?下面是代码:显然,上面是代码。无法将代码放入注释中。。。谢谢。谢谢,我知道问题出在我的代码和KVM/OpenStack的结合上。它与同一个VM并行工作,因此它不是Linux的问题。我还知道,使用相同的代码将数据包发送到另一台机器,数据包将通过。我想找到答案的唯一方法就是通过内核跟踪数据包。我对学生们的解决方案是将数据包发送到另一台机器:-)。尤瓦尔。我很抱歉花了很长时间回答,我不在。