Необходимо генерировать tcp пакеты с установленным флагом SYN.
Создаю RAW-сокет и через него посылаю 'tcp'-пакет с установленным
<SYN>. Но столкнулся с неприятной проблемой, когда удаленная машина в ответ отправляет пакет
<SYN,ACK>, моя почему то в ответ шлет пакет
<RST>, что приводит к сбросу данного соединения на удаленной машине.
Подскажите, как побороть данную проблему?
#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;
}