绑定到设备的原始套接字未接收所有数据包
Raw socket bound to device not receiving all packets
我有一个原始套接字设置绑定到一个已经处于混杂模式的设备:
int sock = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);
if(sock == -1)
{
return -1;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, "eth0", IFNAMSIZ);
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
{
close(sock);
return -2;
}
while(1) {
packet_size = recvfrom(sock , buffer , 65536 , 0 , NULL, NULL);
// packet processing...
}
我的问题是我只在我的套接字上接收数据包,其 IP 目标与我绑定的设备 (eth0) 的 IP 相匹配。如何接收设备正在接收的所有 TCP 数据包?我可以在 Wireshark 中看到设备上的所有 TCP 数据包,但我在原始套接字中看到的唯一数据包是那些寻址到设备 IP 的数据包。
收到仅指向您设备 IP 的数据包的原因是您正在使用 PF_INET
原始套接字。当使用 PF_INET
原始套接字时 - skb
在跨越堆栈时面临不同的健全性检查(见下文)。
F.e。 :
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
/*...*/
/* When the interface is in promisc. mode, drop all the crap
* that it receives, do not try to analyse it.
*/
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;
所以调用跟踪是这样的:__netif_receive_skb_core()
->ip_rcv()
->...->ip_local_deliver()
->...->raw_local_deliver()
- >raw_rcv()
->...->tcp_rcv()
(您可以通过trace-cmd
查看trace)。
但是 tcpdump/Wireshark 在 __netif_receive_skb_core()
左右获取数据包,即在进行一些健全性检查之前。因此,差异使您感到困惑。
因此,如果您希望 skb
绕过大部分 Linux 内核网络堆栈 - 您应该使用 PF_PACKET
原始套接字。
我有一个原始套接字设置绑定到一个已经处于混杂模式的设备:
int sock = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);
if(sock == -1)
{
return -1;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, "eth0", IFNAMSIZ);
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
{
close(sock);
return -2;
}
while(1) {
packet_size = recvfrom(sock , buffer , 65536 , 0 , NULL, NULL);
// packet processing...
}
我的问题是我只在我的套接字上接收数据包,其 IP 目标与我绑定的设备 (eth0) 的 IP 相匹配。如何接收设备正在接收的所有 TCP 数据包?我可以在 Wireshark 中看到设备上的所有 TCP 数据包,但我在原始套接字中看到的唯一数据包是那些寻址到设备 IP 的数据包。
收到仅指向您设备 IP 的数据包的原因是您正在使用 PF_INET
原始套接字。当使用 PF_INET
原始套接字时 - skb
在跨越堆栈时面临不同的健全性检查(见下文)。
F.e。 :
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
/*...*/
/* When the interface is in promisc. mode, drop all the crap
* that it receives, do not try to analyse it.
*/
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;
所以调用跟踪是这样的:__netif_receive_skb_core()
->ip_rcv()
->...->ip_local_deliver()
->...->raw_local_deliver()
- >raw_rcv()
->...->tcp_rcv()
(您可以通过trace-cmd
查看trace)。
但是 tcpdump/Wireshark 在 __netif_receive_skb_core()
左右获取数据包,即在进行一些健全性检查之前。因此,差异使您感到困惑。
因此,如果您希望 skb
绕过大部分 Linux 内核网络堆栈 - 您应该使用 PF_PACKET
原始套接字。