我做了一个触发我问题的示例:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <time.h>
#include <linux/if_ether.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <iostream>
enum {
IP_ERR
};
int main(int argc, char **argv) {
int fd;
sockaddr_ll device;
// tcp and ip syn data
unsigned char ipTcp[] = {0x45, 0x00, 0x00, 0x28, 0x23, 0xc6, 0x00, 0x00, 0x40, 0x06, 0x59, 0x08, 0x7f, 0x00, 0x00, 0x01,
0x7f, 0x00, 0x00, 0x01, 0x0f, 0xa1, 0x0b, 0xb8, 0x6b, 0x8b, 0x45, 0x67, 0x00, 0x00, 0x00, 0x00,
0x50, 0x02, 0xaa, 0xaa, 0x3a, 0xea, 0x00, 0x00};
// if any argument, send syn frame using packet socket
// otherwise, send using raw socket
bool asPacket = argc > 1;
if (asPacket) {
// send as packet
fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
if (fd == -1) {
throw IP_ERR;
}
memset(&device, 0, sizeof(device));
if (!(device.sll_ifindex = if_nametoindex("lo"))) {
throw IP_ERR;
}
device.sll_family = AF_PACKET;
device.sll_protocol = htons(ETH_P_IP);
std::cout << sendto(fd, ipTcp, 40, 0, (struct sockaddr *) &device, sizeof(device)) << std::endl;
} else {
// send as raw socket
fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (fd == -1) {
throw IP_ERR;
}
sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(3000);
sin.sin_addr.s_addr = htonl(0x7f000001);
std::cout << sendto(fd, ipTcp, 40, 0, (struct sockaddr *) &sin, sizeof(sin)) << std::endl;
}
}
如果你在Linux上编译它并使用sudo运行,它将从端口4001上的127.0.0.1发送一个SYN到127.0.0.1到端口3000.这可以工作并显示在Wireshark中,Linux内核将自动发送RST端口3000,因为我们没有服务器。
但是,如果您将参数传递给此程序,它将发送完全相同的SYN但使用数据包套接字而不是原始套接字,这也将显示在Wireshark中,具有相同的内容(TCP / IP)。问题是,内核没有用RST响应,我不能让这个SYN从服务器触发任何SYN-ACK。我发送的数据包套接字似乎没有正确到达目标,即使我使用的接口“lo”是我机器上的环回接口。
这是为什么?数据包套接字是否也应该触发相同的RST响应?我无法得到它(数据包套接字)来触发任何类型的反应,即使它在Wireshark中显示为相同。