Необходимо генерировать tcp пакеты с установленным флагом SYN. Создаю RAW-сокет и через него посылаю 'tcp'-пакет с установленным <SYN>. Но столкнулся с неприятной проблемой, когда удаленная машина в ответ отправляет пакет <SYN,ACK>, моя почему то в ответ шлет пакет <RST>, что приводит к сбросу данного соединения на удаленной машине. Подскажите, как побороть данную проблему? Код (Text): #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #include <stdarg.h> #include <errno.h> #include <inttypes.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <netinet/ip_icmp.h> static const char ip_src[] = "192.168.20.220"; static const char ip_dst[] = "192.168.20.236"; static const char *progname; struct tcphdr tcp; struct { struct ip ip; struct icmp icmp; } msg; struct { struct { struct in_addr ip_src, ip_dst; uint16_t ptcl; uint16_t len; } ptcp; struct tcphdr tcp; } pack; static void errprint(const char *fmt, ...) { va_list args; if (progname != NULL) fprintf(stderr,"%s: ",progname); va_start(args,fmt); vfprintf(stderr,fmt,args); va_end(args); exit(1); } static uint16_t ip_sum_calc(const uint8_t *buff, int len) { const uint16_t *p = (const uint16_t *)buff; uint32_t sum = 0; int i; for (i = 0; i < len / 2; i++) { sum += p[i]; if (sum > 0xffff) sum = (sum & 0xffff) + 1; } sum = ~sum; return sum; } static void print_hex(const uint8_t *buff, int len) { int i = 0; while (i < len) { printf("0x%02x ",buff[i++]); if ((i % 4) == 0) putchar('\n'); } } static void create_msg(void) { char ch; int i; /* prepare 'icmp' */ msg.icmp.icmp_type = ICMP_ECHO; msg.icmp.icmp_code = 0; msg.icmp.icmp_cksum = 0; msg.icmp.icmp_id = rand(); msg.icmp.icmp_seq = 0; ch = 'a'; for (i = 0; i < sizeof(struct icmp) - sizeof(struct icmphdr); i++, ch++) ((char *)&msg.icmp.icmp_dun.id_data[0])[i] = ch; msg.icmp.icmp_cksum = ip_sum_calc((uint8_t *)&msg.icmp,sizeof(msg.icmp)); /* prepare 'ip' */ msg.ip.ip_v = 4; msg.ip.ip_hl = 5; msg.ip.ip_tos = 0; msg.ip.ip_len = htons(sizeof(msg)); msg.ip.ip_id = htons(rand()); msg.ip.ip_off = htons(IP_DF); msg.ip.ip_ttl = 64; msg.ip.ip_p = IPPROTO_ICMP; msg.ip.ip_sum = 0; msg.ip.ip_src.s_addr = inet_addr(ip_src); msg.ip.ip_dst.s_addr = inet_addr(ip_dst); msg.ip.ip_sum = htons(ip_sum_calc((void *)&msg.ip,sizeof(msg.ip))); } void create_tcp(void) { memset(&pack,0,sizeof(pack)); pack.ptcp.ip_src.s_addr = inet_addr(ip_src); pack.ptcp.ip_dst.s_addr = inet_addr(ip_dst); pack.ptcp.ptcl = htons(IPPROTO_TCP); pack.ptcp.len = htons(sizeof(pack.tcp)); pack.tcp.source = htons(1000); pack.tcp.dest = htons(448); pack.tcp.seq = htonl(101); pack.tcp.doff = 5; pack.tcp.syn = 1; pack.tcp.window = 1024; pack.tcp.check = ip_sum_calc((void *)&pack,sizeof(pack)); } int main(int argc, char **argv) { char buff[1024]; struct sockaddr_in addr; int raw_socket; int res,tmp; progname = argv[0]; srand(time(NULL)); create_msg(); create_tcp(); raw_socket = socket(PF_INET,SOCK_RAW,IPPROTO_TCP); if (raw_socket < 0) errprint("Failed execute 'socket': %s\n",strerror(errno)); tmp = 1; // res = setsockopt(raw_socket,IPPROTO_IP,IP_HDRINCL,&tmp,sizeof(tmp)); // if (res < 0) // errprint("Failed execute 'setsockopt': %s\n",strerror(errno)); printf("to:\n"); print_hex((uint8_t *)&pack,sizeof(pack)); memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = 448; addr.sin_addr.s_addr = inet_addr(ip_dst); // res = sendto(raw_socket,&msg,sizeof(msg),0, // (struct sockaddr *)&addr,sizeof(addr)); res = sendto(raw_socket,&pack.tcp,sizeof(pack.tcp),0, (struct sockaddr *)&addr,sizeof(addr)); if (res < 0) errprint("Failed execute 'sendto': %s\n",strerror(errno)); addr.sin_family = AF_INET; addr.sin_port = IPPROTO_TCP; addr.sin_addr.s_addr = inet_addr(ip_dst); tmp = sizeof(addr); res = recvfrom(raw_socket,buff,sizeof(buff),0, (struct sockaddr *)&addr,&tmp); if (res < 0) errprint("Failed execute 'recvfrom': %s\n",strerror(errno)); printf("from:\n"); print_hex(buff,res); sleep(10); close(raw_socket); return 0; }
ессно. Syn/ack приходит в tcp/ip stack который проверяет список сокетов и посылает rst. Побороть это надо так - посылать syn от виртуального IP адреса (но с той же подсети) и прописывать вирт. MAC address. То есть, это не будет никак связяно с реальным stack-ом. На втором компе пропиши static arp запись.