我想发送一个syn数据包到我的httpd服务器并获得响应的syn-ack数据包.但是当我使用Wireshark监视时,数据包正在由我的本地接口发送,lo
而不是eth0
.
我已经尝试设置一些不同的值,setsockopt
你可以在下面的代码中看到,但似乎没有工作,它总是使用lo
接口,而不是eth0
.我不知道tcp数据包是否有什么问题导致它通过本地接口,或者是否是其他东西.
#include#include #include #include #include #include #include #include #include #define PCKT_LEN 8192 unsigned short csum(unsigned short *buf, int len) { unsigned long sum; for(sum=0; len>0; len--) sum += *buf++; sum = (sum >> 16) + (sum &0xffff); sum += (sum >> 16); return (unsigned short)(~sum); } int main(int argc, char** argv) { char *buffer = new char[PCKT_LEN](); class iphdr *ip = (struct iphdr *) buffer; class tcphdr *tcp = (struct tcphdr *) (buffer + sizeof(struct iphdr)); class sockaddr_in sin; int sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP); if(sd < 0) { perror("socket() error"); exit(-1); } else { printf("socket()-SOCK_RAW and tcp protocol is OK.\n"); } sin.sin_family = AF_INET; // Address family sin.sin_port = htons(atoi("2345")); // Source port inet_pton(AF_INET, "192.168.1.11", &(sin.sin_addr.s_addr)); // Dest IP - ERROR WAS WRONG IP ip->ihl = 5; ip->version = 4; ip->tos = 16; ip->tot_len = sizeof(class iphdr) + sizeof(class tcphdr); ip->id = htons(54321); ip->frag_off = 0; ip->ttl = 32; ip->protocol = 6; // TCP ip->check = 0; // Done by kernel inet_pton(AF_INET, "192.168.1.10", &(ip->saddr)); // Source IP inet_pton(AF_INET, "192.168.1.11", &(ip->daddr)); // Destination IP // The TCP structure tcp->source = htons(atoi("2345")); tcp->dest = htons(atoi("80")); // Destination port tcp->seq = htonl(1); tcp->ack_seq = random(); tcp->doff = 5; tcp->syn = 1; tcp->ack = 0; tcp->window = htons(32767); tcp->check = 0; // Done by kernel tcp->rst = 0; tcp->urg_ptr = 0; ip->check = csum((unsigned short *) buffer, (sizeof(class iphdr) + sizeof(class tcphdr))); // Bind socket to interface int iface = 1; const int *val = &iface; char *opt = "eth0"; if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(iface)) < 0) { //if(setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, opt, 4) < 0) { perror("setsockopt() error"); exit(-1); } else printf("setsockopt() is OK\n"); if(sendto(sd, buffer, ip->tot_len, 0, (sockaddr*)&sin, sizeof(class sockaddr_in)) < 0) { perror("sendto() error"); exit(-1); } else printf("Send OK!"); close(sd); return 0; }
我的界面:
# ip a 1: lo:mtu 65536 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000 link/ether 00:0c:29:6e:82:29 brd ff:ff:ff:ff:ff:ff inet 192.168.1.10/24 brd 192.168.1.255 scope global eth0 inet6 fe80::20c:29ff:fe6e:8229/64 scope link valid_lft forever preferred_lft forever
编辑
... #include#include ... struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth0"); if(ioctl(sd, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl failed!"); return EXIT_FAILURE; } if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, &ifr, sizeof(ifr)) < 0) { perror("setsockopt() error"); exit(-1); } printf("setsockopt() is OK\n");
但它仍然通过lo
接口.它是否与我的虚拟机中的桥接网络接口有关?
编辑2
我现在比较了我的原始ip数据包和hping2发送的数据包,唯一不同的是接口ID(在帧中指定),以及以太网层不包含任何MAC地址信息.hping2通过eth0
接口发送并包含所有MAC地址信息.我的程序发送它lo
并且不包含任何MAC信息(可能它是通过lo
接口发送的,因为它不包含数据包中的任何MAC地址信息???).看这张图片:
我还将hping2的源代码与我的代码进行了比较,以了解如何构建原始IP数据包,我看不到任何会使数据包通过lo
接口的内容,就像我的情况一样.而且我还没有弄清楚为什么我的程序不会在我的数据包中包含任何MAC地址.我的数据包中的其他所有内容都等于hping2数据包中的内容,但随机化的序列号除外.
还有其他想法吗?