gpt4 book ai didi

linux - 环回接口(interface)上的原始套接字是否可能?

转载 作者:IT王子 更新时间:2023-10-29 00:22:11 27 4
gpt4 key购买 nike

我们正在尝试通过原始套接字与监听 Linux 环回接口(interface)的服务器进行通信,服务器似乎没有从我们这里获得一个数据包。我们发送的数据包在 Wireshark 中是可见的。

环回上的原始套接字是否可能? (请不要问我们为什么需要它:这里解释起来太复杂了)

编辑:这就是我们打开它的方式

_I_RawSocket = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)))

memset( &ifr, 0, sizeof( ifr ) );
strcpy( ifr.ifr_ifrn.ifrn_name, _InterfaceName);

ioctl( _I_RawSocket, SIOCGIFINDEX, &ifr )

memset( &sll, 0, sizeof( sll ) );
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_protocol = htons( ETH_P_ALL );

bind( _I_RawSocket, (struct sockaddr *) &sll, sizeof( sll ))

服务器是 lighttpd,可以通过本地主机上的普通套接字访问。netstat --raw 打印空表,但我绝对确定我们在普通 eth 设备上有两个功能性原始套接字。

最佳答案

原始套接字在使用 bind() 和 connect() 时表现特别不稳定,但我无法确认您的问题出在它们身上。我建议您采用更直接的方法:

发件人

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define DEST "127.0.0.1"

int main(int argc, char **argv)
{

int s;
struct sockaddr_in dst_addr;
char packet[50];

struct iphdr *ip = (struct iphdr *)packet;

if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("error:");
exit(EXIT_FAILURE);
}

dst_addr.sin_family = AF_INET;
dst_addr.sin_port = 0; /* not needed in SOCK_RAW */
inet_pton(AF_INET, DEST, (struct in_addr *)&dst_addr.sin_addr.s_addr);
memset(dst_addr.sin_zero, 0, sizeof(dst_addr.sin_zero));

memset(packet, 'A', sizeof(packet)); /* payload will be all As */

ip->ihl = 5;
ip->version = 4;
ip->tos = 0;
ip->tot_len = htons(40);
ip->frag_off = 0; /* NF */
ip->ttl = 64;
ip->protocol = IPPROTO_RAW; /* this has to be IPPROTO_RAW */
ip->check = 0;
ip->saddr = dst_addr.sin_addr.s_addr;
ip->daddr = dst_addr.sin_addr.s_addr;

while(42) {
sleep(5);
if (sendto(s, packet, sizeof(packet), 0,
(struct sockaddr *)&dst_addr, (socklen_t)sizeof(dst_addr)) < 0)
perror("uh oh:");
}
return(0);
}

接收者

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>


int main(int argc, char **argv)
{
int s;
struct sockaddr_in src_addr;
char packet[50];

if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("error:");
exit(EXIT_FAILURE);
}

memset(packet, 0, sizeof(packet));
socklen_t *len = (socklen_t *)sizeof(src_addr);
int fromlen = sizeof(src_addr);

while(42) {
if (recvfrom(s, &packet, sizeof(packet), 0,
(struct sockaddr *)&src_addr, &fromlen) < 0)
perror("uh oh:");

int i = sizeof(struct iphdr); /* print the payload */
for(; i < sizeof(packet); i++) {
printf("%c", packet[i]);
}
printf("\n");
}
return(0);
}

我希望它们的行为与您希望的完全一样。阅读 man 7 raw 以了解其工作原理的详细信息,更重要的是 man 7 packet 如果您想扩展它。另外,请注意 IPPROTO_RAW 暗示 IP_HDRINCL 套接字选项,这就是我们自己构建 ip header 的原因 - 尽管 IP 校验和和总长度仍然由内核计算和填充。

编辑:此外,如果您想要一个原始套接字来将有效数据发送到像 lighttpd 这样的应用程序,您必须将 protocol 参数与 socket() 并为 IP header 字段提供有效值。正确的以太网 header 不是强制性的 - 内核堆栈将为您填充唯一重要的字段。

关于linux - 环回接口(interface)上的原始套接字是否可能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3335277/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com