c - 使用 RAW 套接字发送 SYN 后未收到 SYN/ACK

标签 c sockets tcp raw-sockets

我正在向同一网络中的网络服务器发送 TCP SYN 数据包(无负载)。我正在使用sniffex.c 用于捕获数据包。

问题是,在我发送 SYN 数据包后,我没有收到来自服务器的 SYN/ACK 数据包。

在 sniffex.c 中: 我使用我的 LAN IP 作为源 ip。 我已将过滤器设置为 "tcp" 。 我正在发送到端口 80

当我打印发送的数据包的字段时,在使用 sniffex 捕获它之后,所有字段都被正确打印,因此我假设发送的数据包的结构使得服务器可以理解它。

当我使用浏览器连接到网络服务器时,成功接收到 SYN/ACK。

另一个相关查询:如何设置过滤器,以便仅获取与此对话相关的数据包(黑白我的电脑和网络服务器)

我使用的是 UBUNTU 14.04

编辑:我尝试发送数据包的 c 文件

#define __USE_BSD   /* use bsd'ish ip header */
#include <sys/socket.h> /* these headers are for a Linux system, but */
#include <netinet/in.h> /* the names on other systems are easy to guess.. */
#include <netinet/ip.h>
#define __FAVOR_BSD /* use bsd'ish tcp header */
#include <netinet/tcp.h>
#include <unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<errno.h>
#include<sys/socket.h>
#include<sys/types.h>

#define P 80        /* lets flood the sendmail port */

unsigned short      /* this function generates header checksums */
csum (unsigned short *buf, int nwords)
{
  unsigned long sum;
  for (sum = 0; nwords > 0; nwords--)
    sum += *buf++;
  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  return ~sum;
}

int 
main (void)
{
  int s = socket (AF_INET, SOCK_RAW, IPPROTO_TCP);
  printf("s=%d\n",s);   /* open raw socket */
  char datagram[4096];  /* this buffer will contain ip header, tcp header,
               and payload. we'll point an ip header structure
               at its beginning, and a tcp header structure after
               that to write the header values into it */
  struct ip *iph = (struct ip *) datagram;
  struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));
  struct sockaddr_in sin;
            /* the sockaddr_in containing the dest. address is used
               in sendto() to determine the datagrams path */

  sin.sin_family = AF_INET;
  sin.sin_port = htons (P);/* you byte-order >1byte header values to network
                  byte order (not needed on big endian machines) */
  sin.sin_addr.s_addr = inet_addr ("xxx.xxx.xxx.xxx");

  memset (datagram, 0, 4096);   /* zero out the buffer */

/* we'll now fill in the ip/tcp header values, see above for explanations */
  iph->ip_hl = 5;
  iph->ip_v = 4;
  iph->ip_tos = 0;
  iph->ip_len = sizeof (struct ip) + sizeof (struct tcphdr);    /* no payload */
  iph->ip_id = htonl (54321);   /* the value doesn't matter here */
  iph->ip_off = 0;
  iph->ip_ttl = 255;
  iph->ip_p = 6;
  iph->ip_sum = 0;      /* set it to 0 before computing the actual checksum later */
  iph->ip_src.s_addr = inet_addr ("xxx.xxx.xxx.xxx");/* SYN's can be blindly spoofed */
  iph->ip_dst.s_addr = sin.sin_addr.s_addr;
  tcph->th_sport = htons (2000);    /* arbitrary port */
  tcph->th_dport = htons (P);
  tcph->th_seq = random();/* in a SYN packet, the sequence is a random */
  tcph->th_ack = 0;/* number, and the ack sequence is 0 in the 1st packet */
  tcph->th_x2 = 5;
  tcph->th_off = 5;     /* first and only tcp segment */
  tcph->th_flags = TH_SYN;  /* initial connection request */
  tcph->th_win = htonl (65535); /* maximum allowed window size */
  tcph->th_sum = 0;/* if you set a checksum to zero, your kernel's IP stack
              should fill in the correct checksum during transmission */
  tcph->th_urp = 0;

  iph->ip_sum = csum ((unsigned short *) datagram, iph->ip_len >> 1);

/* finally, it is very advisable to do a IP_HDRINCL call, to make sure
   that the kernel knows the header is included in the data, and doesn't
   insert its own header into the packet before our data */

                /* lets do it the ugly way.. */
    int one = 1;
   // const int *val = &one;
    if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, &one, sizeof (one)) < 0)
      printf ("Warning: Cannot set HDRINCL!\terrno = %d\n",errno);




 // while (1)
   // {
      if (sendto (s,        /* our socket */
          datagram, /* the buffer containing headers and data */
          iph->ip_len,  /* total length of our datagram */
          0,        /* routing flags, normally always 0 */
          (struct sockaddr *) &sin, /* socket addr, just like in */
          sizeof (sin)) < 0)        /* a normal send() */
    printf ("error\n");
      else
    printf ("SUCCESS\n\n\n\n");
    //}
char buffer[8192];
memset (buffer, 0, 8192);
int n;
//while(n=read (s, buffer, 8192) > 0)
//{
//printf("n=%d\n",n);

 //printf ("Caught tcp packet: %s\n", buffer);
 //memset (buffer, 0, 8192);
//}

  return 0;
}

最佳答案

[聊天摘要] 除了 iph->ip_off 问题之外,您可能还需要自己计算 TCP 校验和(您的操作系统可能不会为您计算)。有用的信息在这里:http://www.tcpipguide.com/free/t_TCPChecksumCalculationandtheTCPPseudoHeader-2.htmhttp://www.netfor2.com/tcpsum.htm

此外,tcph->th_seq = htonl(23456); 也可能有用。

关于c - 使用 RAW 套接字发送 SYN 后未收到 SYN/ACK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29877735/

相关文章:

mysql - gem mysql2 未安装在 ruby​​ on rails 上

java - Java套接字错误 "Thread-0"

c - 在网络环境中从 Brother TD-4100N 打印机检索打印机状态

java - TCP Server 无法接收 GPRS Modem 发送的数据

unit-testing - 什么是用于单元测试的好的无效 IP 地址?

c - 哪个更好? 32 位 MCU 中的 int8_t 与 int32_t

c - 奇怪的宏结构

c++ - 为什么要在套接字的 'recv' 方法上设置保守的最大字节大小?

c++ - C 套接字文件传输损坏的数据

我可以在我的 C 程序中使用 OpenGL 进行图形处理吗?