我编写了在 Ubuntu 上运行的模拟握手过程的 c/c++ 代码。
//Create a raw socket
int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);
//some address resolution
strcpy(source_ip , "192.168.1.9");
sin.sin_family = AF_INET;
sin.sin_port = htons(1235);
sin.sin_addr.s_addr = inet_addr ("192.168.1.6");
if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
{
perror("Error setting IP_HDRINCL");
exit(0);
}
{
//Send the packet
if (sendto (s, datagram, iph->tot_len , 0, (struct sockaddr *) &sin, sizeof (sin)) < 0)
{
perror("sendto failed");
}
//Data send successfully
else
{
printf ("Packet Send. Length : %d \n" , iph->tot_len);
}
}
int l;
if( recvfrom(s,buffer,4096,0, (struct sockaddr *) &sin, &l)<0)
{
perror("sendto failed");
}
//Data send successfully
else
{
printf ("Packet recv. ");
}
printf ("Enter number to end: ");
int numm=getchar();
close(s);
return 0;
代码首先将 SYN 数据包发送到在 Windows 上运行的 192.168.1.6:1235。
SYN包正确到达192.168.1.6:1235
SYN-ACK 正确到达 Ubuntu (192.168.1.9:1234)。
但是 Wireshark 中显示的是 RST 而不是 ACK。
我在 192.168.1.6 上运行 netcat –l –p 1235
我尝试了以下所有方法:
- 在源计算机 (ubuntu) 中使用 netcat 打开发送 SYN 时使用的相同端口 (1234)。
- 默认情况下禁用 ubuntu 中的防火墙。
- 我写了一段小代码,让这台机器成为我在 SYN 中使用的同一端口 (1234) 上的服务器。
- 我更新了发送 SYN 数据包的代码以解锁套接字,除非我插入一些字符。
但是没有人解决这个问题。
最佳答案
当您使用原始套接字时,您的操作系统不会意识到连接的存在,因为您基本上实现了自己的 TCP/IP 堆栈并绕过了操作系统。
您的操作系统看到一个未经请求的数据包并使用 RST
进行响应,以指示对正在响应您使用原始套接字发送的数据包的远程系统的主动拒绝。
要绕过它,请使用路由到您所在的子网但未使用原始套接字在机器上分配的 IP 地址,这样操作系统就不会响应,然后从它传输并以一种“混杂模式”收听响应。您的网卡应该支持观察不是发往它的数据包,因此您可以监控适当路由的流量。
关于networking - 在握手过程的第三步用 RST 代替 ACK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25728580/