我使用原始套接字从计算机B发送TCP数据包到计算机A.
首先,我创build一个套接字
int s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
并告诉内核不要填写我的IP头,因为我的数据包括IP头和TCP头
int optval = 1; setsockopt(s, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval));
并设置目的地址
struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(33333); addr.sin_addr.s_addr = inet_addr("192.168.200.135");
并发送数据
sendto(s, data, len, 0, (struct sockaddr*)&addr, sizeof(addr));
我的networking环境如下图所示
在情况A中,两台计算机通过交换机连接。 在情况B中,计算机B连接到路由器,路由器连接到交换机。
我的程序在案例A中正常工作。我可以使用原始套接字在计算机A上接收数据包,并且可以使用wireshark捕获该数据包。
在情况B中,我可以从计算机B ping到计算机A,从B到s到s。我可以在计算机A上使用原始套接字和wireshark捕获在B和A之间发送的TCP数据包。但是,计算机B上的原始套接字无法在A上捕获。似乎路由器不转发我的数据包。 我的数据包有什么问题吗?
我用分组数据发送程序如下:
//data to send char data[48] = { //iphdr: 0x45, 0x00, 0x00, 0x30, //version:4 header_length:5 TOS:0 length:0x30 0x00, 0x01, 0x00, 0x00, //identification:1 flags:0 fragment_offset:0 0x40, 0x06, 0x2f, 0x47, //TTL:0x40 protocol:6(TCP) header_checksum:0x2f47 0xc0, 0xa8, 0x01, 0xa8, //source_IP:192.168.1.168 0xc0, 0xa8, 0xc8, 0x87, //destination_IP:192.168.200.135 //tcphdr: 0x56, 0xce, 0x82, 0x35, //source_port:22222 destination_port:33333 0x00, 0x00, 0x00, 0x00, //sequence_number:0 0x00, 0x00, 0x00, 0x00, //ack_number:0 0x50, 0x00, 0xaa, 0xaa, //header_length:5 window_size:0xaaaa 0xeb, 0xbd, 0x00, 0x00, //checksum:0xebbd urgent_pointer:0 //tcp content: 0x7a, 0x68, 0x73, 0x00, 0x39, 0x30, 0xce, 0x56, }; int len = 48; //open the socket int s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); //don't fill header int optval = 1; setsockopt(s, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval)); //destination addr struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("192.168.200.135"); //send sendto(s, data, len, 0, (struct sockaddr*)&addr, sizeof(addr));
您的TCP标头是错误的,因为它错过了标志。 对于你的测试,你至少应该设置SYN标志。 有可能是其他的东西不正确的标题。
所以如果路由器正在检查TCP报头,它可能会丢弃你的数据包。 如果您的路由器实际上不是路由,而是使用NAT进行数据包转发,或者有防火墙检查端口或连接状态,则会检查TCP标头。