我一直在尝试使用原始套接字发送UDP数据包,但是,发送的数据包不会在本地接收。如果发送到远程目的地,则接收相同的分组。测试在KVM下进行。相同的测试似乎在Parallels下工作。
套接字设置为:
raw_socket = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
附加了一个接收过滤器,并将其设置为混杂。正确接收数据包。发送的数据包在Wireshark中接收并正确分析。但是,本地程序(例如nc -l -u -p ...)不接收数据包。如果我将相同的数据包发送到远程目标,则会正确接收数据包。 Wireshark收到数据包这一事实表明它没有被任何iptables规则删除(我还检查了所有DROP规则计数器并且没有丢弃的数据包)。
似乎数据包已被路由但未被网络堆栈重新处理,如果这甚至是有意义的。
它应该是网络课程中的示例代码,目前,我在学生面前丢脸。希望他们都不在这个名单上; - )。
感谢任何帮助, 尤瓦。
关于代码的一些评论。为简洁起见,UDP校验和设置为0,IP校验和从头部计算。两者都由Wireshark验证(并且也由KVM上的远程机器接受)。代码解析消息并在收到的缓冲区上发送回复。 udp_hdr和ip_hdr指向数据包缓冲区(缓冲区)中的相应标头,而有效负载指向L7数据的开头。
这里是代码: { / *处理请求。 * / ssize_t msg_len; int max_len = sizeof(buffer) - (payload - buffer); int tmp_port; in_addr_t tmp_ip; struct ether_addr tmp_ether;
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;
}
}
答案 0 :(得分:0)
让我们写下我们所知道的事实:
1-你告诉你可以在数据包捕获程序中看到数据包(例如Wireshark)
2-你告诉你在发送数据包时无法使用netcat接收数据包 loopback接口。
3-您告诉您在将数据包发送到远程计算机时可以收到数据包。
所以问题出在你的代码或本地机器上。我有一堆建议:
1-在另一台机器上测试代码,并将数据包发送到环回接口并尝试使用netcat捕获它们。
或
2-尝试使用netcat将一堆UDP数据包发送到本地接口,并使用另一个netcat实例接收它们并检查它是否有效;如果它有效,你知道问题在你的代码中,否则问题可能是因为你的本地机器。