我正在尝试创建一个原始套接字,它在linux下使用ip / tcp头发送和接收消息。 我可以成功绑定到端口并接收tcp消息(即:syn) 但是,消息似乎是由操作系统处理的,但不是我的。我只是它的读者(像wireshark)。 我的原始套接字绑定到端口8888,然后我尝试telnet到该端口。 在wireshark中,它显示端口8888在收到“syn”请求时回复“rst ack”。在我的程序中,它显示它收到一条新消息,并且不会回复任何消息。
任何实际绑定到该端口的方法?(防止操作系统处理它)
以下是我的代码的一部分,我尝试删除那些错误检查以便于阅读
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
int tmp = 1;
const int *val = &tmp;
setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, val, sizeof (tmp));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(8888);
bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
//call recv in loop
答案 0 :(得分:4)
当你的内核收到来自远程主机的SYN / ACK时,它没有发现它已将SYN发送到该IP:PORT组合(从你的原始套接字发送)的记录,这就是为什么它假设已经存在错误并将RST发送到远程主机。通过设置阻止该端口上所有TCP流量的IP过滤器可以解决此问题(请查看iptables联机帮助页)。这样您就不必在内核空间中编程,也不会对现有的内核TCP模块产生任何影响。
答案 1 :(得分:3)
man 7 raw
说:
原始套接字可以利用Linux中的所有IP协议,甚至是内核中具有协议模块的ICMP或TCP等协议。在这种情况下,数据包将传递给内核模块和原始套接字。
我认为这意味着你不能在没有内核干扰的情况下在原始套接字上“做TCP”,除非你的内核缺乏TCP支持 - 当然,这不是你想要的。什么原始套接字适用于实现内核不处理的其他IP协议,或者用于发送精心设计的ICMP数据包等特殊应用程序。
答案 2 :(得分:2)
要访问原始标头,您不要将原始套接字绑定到端口。多数民众赞成没有。
只需编写一个嗅探器,“拾取”所有传入的数据包并找出“你的”数据包。这也可以让您访问所有数据包内容等。
您就是这样做的:
int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;
while(true)
{
saddr_size = sizeof saddr;
//Receive a packet
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size);
if(data_size <0 )
{
printf("Recvfrom error , failed to get packets\n");
return 1;
}
//Now process the packet
ProcessPacket(buffer , data_size);
}
在ProcessPacket函数中分析数据包并查看它们是否属于您的应用程序。
答案 3 :(得分:1)
编辑: 如果您打算编写原始套接字,请检查this。
它有一些如何发送和接收原始数据包的示例。
如果您想使用SOCK_STREAM
和SOCK_SEQPACKET
面向连接的类型套接字:
你需要告诉它在绑定到给定地址后监听:port。
int connectionQueue = 10;
if ( -1 == listen(sockfd, connectionQueue) )
{
// Error occurred
}
之后,您需要使用select验证传入连接的描述符,并接受服务器套接字上的传入连接(这将导致不接受新连接)或专用客户端套接字。