Linux C 原始套接字 TCP 握手 [英] Linux C raw socket TCP handsake

查看:40
本文介绍了Linux C 原始套接字 TCP 握手的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 C 中的原始套接字(在 Debian 系统上)创建 TCP 连接,但我很难让它工作.它会发送一个数据包,但我没有得到服务器的任何响应.我已经测试并将数据包与从 nmap 发送的数据包进行了比较,但我看不出任何重大差异.

这里是服务器端收到的TCP包,服务器端从不发送SYN ACK包(我在服务器端用Wireshark监控)

没有.时间源目的地协议长度信息75 1.893700000 192.168.1.129 192.168.1.114 TCP 74 56540→445 [SYN] Seq=0 Win=1024 Len=0 MSS=1460 SACK_PERM=1 WSval=18Sec6r=18Sec6r=1TS0帧 75:线路上的 74 个字节(592 位),接口 0 上捕获的 74 个字节(592 位)以太网 II,Src:Vmware_77:f0:a0 (00:0c:29:77:f0:a0),Dst:IntelCor_07:f9:e5 (e8:b1:fc:07:f9:e5)Internet 协议版本 4,Src:192.168.1.129 (192.168.1.129),Dst:192.168.1.114 (192.168.1.114)版本:4标头长度:20 字节区分服务字段:0x00(DSCP 0x00:默认;ECN:0x00:Not-ECT(不支持 ECN 的传输))总长度:60标识:0xb88d (47245)标志:0x00片段偏移:0存活时间:255协议:TCP (6)标头校验和:0x7eea [验证已禁用]来源:192.168.1.129 (192.168.1.129)目的地:192.168.1.114 (192.168.1.114)[来源 GeoIP:未知][目的地 GeoIP:未知]传输控制协议,Src 端口:56540(56540),Dst 端口:445(445),Seq:0,Len:0源端口:56540 (56540)目的端口:445 (445)[流指数:3][TCP 段长度:0]序号:0(相对序号)确认编号:0标头长度:40 字节.... 0000 0000 0010 = 标志:0x002 (SYN)窗口大小值:1024[计算窗口大小:1024]校验和:0x7ff8 [验证已禁用]紧急指针:0选项:(20 字节)、最大段大小、允许 SACK、窗口缩放、无操作 (NOP)、时间戳最大段大小:1460 字节种类:最大段大小 (2)长度:4MSS 值:1460TCP SACK 允许选项:True种类:SACK 允许 (4)长度:2窗口比例:7(乘以 128)种类:窗秤 (3)长度:3班次:7[乘数:128]无操作 (NOP)类型:1时间戳:TSval 863195,TSecr 0种类:时间戳选项 (8)长度:10时间戳值:863195时间戳回显回复:00000 e8 b1 fc 07 f9 e5 00 0c 29 77 f0 a0 08 00 45 00 ........)w....E.0010 00 3c b8 8d 00 00 ff 06 7e ea c0 a8 01 81 c0 a8 .<......~.......0020 01 72 dc dc 01 bd db 0f 13 02 00 00 00 00 a0 02 .r........0030 04 00 7f f8 00 00 02 04 05 b4 04 02 03 03 07 01 .....................0040 08 0a 00 0d 2b db 00 00 00 00 ....+.....

这是我的代码,我知道它很乱,我只是想学习如何使用原始套接字

#include #include #include #include #include #include #include #include #include #include 结构 ipheader {unsigned char iph_ihl:4,/* 小端 */iph_ver:4;无符号字符 iph_tos;无符号短整数 iph_len;unsigned short int iph_ident;unsigned short int iph_offset:13,/* 小端*/iph_flags:3;无符号字符 iph_ttl;无符号字符 iph_protocol;无符号短整数 iph_chksum;无符号整数 iph_sourceip;无符号整数 iph_destip;};结构tcpheader {u_int16_t tcph_srcport;u_int16_t tcph_destport;u_int32_t tcph_seqnum;u_int32_t tcph_acknum;u_int16_ttcph_ns:1,tcph_reserved:3,tcph_offset:4,tcph_fin:1,tcph_syn:1,tcph_rst:1,tcph_psh:1,tcph_ack:1,tcph_urg:1,tcph_ece:1,tcph_cwr:1;u_int16_t tcph_win;u_int16_t tcph_chksum;u_int16_t tcph_urgptr;};struct tcpheaderOptions{u_int16_ttcph_mssOpt:8,tcph_mssLen:8;u_int16_ttcph_mss;u_int16_ttcph_sack:8,tcph_sackLen:8;u_int16_ttcph_winOpt:8,tcph_winLen:8;u_int32_ttcph_win:8,tcph_winNOP:8,tcph_timeOpt:8,tcph_timeLen:8;u_int32_t tcph_time;u_int32_t tcph_timeEcho;};unsigned short/* 该函数生成头校验和 */csum (unsigned short *buf, int nwords){无符号长和;for (sum = 0; nwords > 0; nwords--)总和 += *buf++;sum = (sum >> 16) + (sum & 0xffff);sum += (sum >> 16);返回〜总和;}int main(void){字符数据报[4096];char data[] = "你好,我叫基思,这是我的第一个数据包";memset(数据报,0,4096);struct ipheader *IPInfo = (struct ipheader *) 数据报;struct tcpheader *TCPHeader = (struct tcpheader *) (datagram + sizeof(struct ipheader));struct tcpheaderOptions *TCPOptions = (struct tcpheaderOptions *) (datagram + sizeof(struct tcpheader) + sizeof(struct ipheader));结构 sockaddr_in 罪;//目的地sin.sin_family = AF_INET;sin.sin_port = htons(4);sin.sin_addr.s_addr = inet_addr("192.168.1.114");IPInfo-> iph_ver = 4;//我们使用的是什么IP版本?v4IPInfo->iph_ihl = 5;//以字节为单位的IP头大小IPInfo-> iph_tos = 0;//服务0x00的IP头类型是正常的IPInfo->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader) + sizeof(struct tcpheaderOptions);//IP数据报的IP长度IPInfo-> iph_ident = htonl(54321);//IP头ID(分片时使用)IPInfo-> iph_offset = 0;//IP分片偏移IPInfo-> iph_ttl = 255;//IP TTLIPInfo-> iph_protocol = 6;//传输层协议(6为TCP,1为ICMP,17为UDP)IPInfo->iph_chksum = 0;//校验和IPInfo-> iph_sourceip = inet_addr("192.168.1.129");//来源//IPInfo->iph_destip = sin.sin_addr.s_addr;IPInfo-> iph_destip = inet_addr("192.168.1.114");字符源[20];字符 dest[20];inet_ntop(AF_INET, &(IPInfo->iph_sourceip), source, 20);inet_ntop(AF_INET, &(IPInfo->iph_destip), dest, 20);printf("来源:%s\n", 来源);printf("目的地:%s\n", dest);//IPInfo->ip_dst.s_addr = inet_addr("192.168.1.114");TCPHeader->tcph_srcport = htons(56540);//源端口TCPHeader->tcph_destport = htons(445);//目的端口srand(时间(空));TCPHeader->tcph_seqnum = rand();//序列号TCPHeader->tcph_acknum = 0;//ACK包TCPHeader->tcph_reserved = 0;//未使用TCPHeader->tcph_offset = 10;//TCPHeader->tcph_cwr = 0;TCPHeader->tcph_ns = 0;TCPHeader->tcph_syn = 1;TCPHeader->tcph_rst = 0;TCPHeader->tcph_psh = 0;TCPHeader->tcph_ack = 0;TCPHeader->tcph_urg = 0;TCPHeader->tcph_ece = 0;TCPHeader->tcph_cwr = 0;TCPHeader->tcph_ns = 0;TCPHeader->tcph_win = htons(1024);TCPHeader->tcph_chksum = 0;TCPHeader->tcph_urgptr = 0;TCPOptions->tcph_mssOpt = 2;TCPOptions->tcph_mssLen = 4;TCPOptions->tcph_winOpt = 3;TCPOptions->tcph_winLen = 3;TCPOptions->tcph_sack = 4;TCPOptions->tcph_sackLen = 2;TCPOptions->tcph_win = 7;TCPOptions->tcph_winNOP = 1;TCPOptions->tcph_mss = htons(1460);TCPOptions->tcph_timeOpt = 8;TCPOptions->tcph_timeLen = 10;TCPOptions->tcph_time = 0xdb2b0d00;//添加数据//strcpy(datagram + sizeof(struct ipheader) + sizeof(struct tcpheader),data);TCPHeader->tcph_chksum = csum((unsigned short *) datagram,TCPHeader->tcph_offset >> 1);IPInfo->iph_chksum = csum((unsigned short *) datagram, IPInfo->iph_len >> 1);int sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);如果(sockfd == -1){perror("sockfd");退出(1);}//设置 IP_HDRINCL 以便系统不会向我的数据包添加标头{整数一 = 1;const int *val = &one;如果(setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,val,sizeof(one))<0){perror("setsockopt");返回-1;}别的printf("使用你自己的标题\n");}//创建一个原始套接字来发送信息if(sendto(sockfd, datagram, IPInfo->iph_len, 0, (struct sockaddr *) &sin, sizeof (sin)) <0)perror("发送");别的printf("发送\n");printf("发送序列号:%d\n",TCPHeader->tcph_seqnum);//现在我们将等待接收返回的消息memset(数据报,0,4096);int 结果 = recv(sockfd,datagram,sizeof(datagram),0);printf("结果:%d\n",results);IPInfo = (struct ipheader *) 数据报;TCPHeader = (struct tcpheader * ) (datagram + (IPInfo->iph_ihl * 4));printf("数据包:IPInfo->iph_ihl %d\n",IPInfo->iph_ihl);printf("ACK num = %d\n",TCPHeader->tcph_ack);字符源1[20];字符 dest1[20];inet_ntop(AF_INET, &(IPInfo->iph_sourceip), source, 20);inet_ntop(AF_INET, &(IPInfo->iph_destip), dest, 20);printf("来源:%s\n",source1);printf("目标:%s\n",dest1);printf("ipheader 的大小 %d\n",sizeof(struct ipheader));printf("tcpheader 的大小 %d\n",sizeof(struct tcpheader));返回0;}

解决方案

在wireshark 中启用校验和验证,这样你至少可以确定你没有计算错误的校验和(在 IP 或 TCP 标头中) – 不

谢谢,我的 TCP 校验和无效 – Keith

I'm trying to create a TCP connection using raw sockets in C (on a Debian system) but I'm having a hard time getting it working. It will send a packet but I dont get any response from the server. I have tested and compared the packet with a packet sent from nmap and I cant see any major differences.

Here is the TCP packet received on the server side, the server side never sends a SYN ACK packet (I'm monitoring using Wireshark on the server side)

No.     Time           Source                Destination           Protocol Length Info
     75 1.893700000    192.168.1.129         192.168.1.114         TCP      74         56540→445 [SYN] Seq=0 Win=1024 Len=0 MSS=1460 SACK_PERM=1 WS=128 TSval=863195 TSecr=0

Frame 75: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on interface 0
Ethernet II, Src: Vmware_77:f0:a0 (00:0c:29:77:f0:a0), Dst: IntelCor_07:f9:e5     (e8:b1:fc:07:f9:e5)
Internet Protocol Version 4, Src: 192.168.1.129 (192.168.1.129), Dst: 192.168.1.114 (192.168.1.114)
Version: 4
Header Length: 20 bytes
Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
Total Length: 60
Identification: 0xb88d (47245)
Flags: 0x00
Fragment offset: 0
Time to live: 255
Protocol: TCP (6)
Header checksum: 0x7eea [validation disabled]
Source: 192.168.1.129 (192.168.1.129)
Destination: 192.168.1.114 (192.168.1.114)
[Source GeoIP: Unknown]
[Destination GeoIP: Unknown]
Transmission Control Protocol, Src Port: 56540 (56540), Dst Port: 445 (445), Seq: 0, Len: 0
Source Port: 56540 (56540)
Destination Port: 445 (445)
[Stream index: 3]
[TCP Segment Len: 0]
Sequence number: 0    (relative sequence number)
Acknowledgment number: 0
Header Length: 40 bytes
.... 0000 0000 0010 = Flags: 0x002 (SYN)
Window size value: 1024
[Calculated window size: 1024]
Checksum: 0x7ff8 [validation disabled]
Urgent pointer: 0
Options: (20 bytes), Maximum segment size, SACK permitted, Window scale, No-Operation (NOP), Timestamps
    Maximum segment size: 1460 bytes
        Kind: Maximum Segment Size (2)
        Length: 4
        MSS Value: 1460
    TCP SACK Permitted Option: True
        Kind: SACK Permitted (4)
        Length: 2
    Window scale: 7 (multiply by 128)
        Kind: Window Scale (3)
        Length: 3
        Shift count: 7
        [Multiplier: 128]
    No-Operation (NOP)
        Type: 1
    Timestamps: TSval 863195, TSecr 0
        Kind: Time Stamp Option (8)
        Length: 10
        Timestamp value: 863195
        Timestamp echo reply: 0

0000  e8 b1 fc 07 f9 e5 00 0c 29 77 f0 a0 08 00 45 00   ........)w....E.
0010  00 3c b8 8d 00 00 ff 06 7e ea c0 a8 01 81 c0 a8   .<......~.......
0020  01 72 dc dc 01 bd db 0f 13 02 00 00 00 00 a0 02   .r..............
0030  04 00 7f f8 00 00 02 04 05 b4 04 02 03 03 07 01   ................
0040  08 0a 00 0d 2b db 00 00 00 00                     ....+.....

And here is my code, i know it is messy, i'm just trying to learn how to use raw sockets

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <time.h>

struct ipheader {
 unsigned char          iph_ihl:4, /* Little-endian */
                        iph_ver:4;
 unsigned char          iph_tos;
 unsigned short int     iph_len;
 unsigned short int     iph_ident;
 unsigned short int     iph_offset:13,  /* Little-endian*/
                        iph_flags:3;
 unsigned char          iph_ttl;
 unsigned char          iph_protocol;
 unsigned short int     iph_chksum;
 unsigned int           iph_sourceip;
 unsigned int           iph_destip;
};

struct tcpheader {
 u_int16_t      tcph_srcport;
 u_int16_t      tcph_destport;
 u_int32_t      tcph_seqnum;
 u_int32_t      tcph_acknum;
 u_int16_t
                tcph_ns:1,
                tcph_reserved:3,
                tcph_offset:4,
                tcph_fin:1,
                tcph_syn:1,
                tcph_rst:1,
                tcph_psh:1,
                tcph_ack:1,
                tcph_urg:1,
                tcph_ece:1,
                tcph_cwr:1;
 u_int16_t      tcph_win;
 u_int16_t      tcph_chksum;
 u_int16_t      tcph_urgptr;
};

struct tcpheaderOptions
{

    u_int16_t 
        tcph_mssOpt:8,
        tcph_mssLen:8;
    u_int16_t
        tcph_mss;
    u_int16_t
        tcph_sack:8,
        tcph_sackLen:8;
    u_int16_t
        tcph_winOpt:8,
        tcph_winLen:8;
    u_int32_t
        tcph_win:8,
        tcph_winNOP:8,
        tcph_timeOpt:8,
        tcph_timeLen:8;
    u_int32_t tcph_time;
    u_int32_t tcph_timeEcho;
};

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)
{
  char datagram[4096];
  char data[] = "Hello my name is Keith, this is my first packet";
  memset(datagram,0,4096);
  struct ipheader *IPInfo = (struct ipheader *) datagram;
  struct tcpheader *TCPHeader = (struct tcpheader *) (datagram + sizeof(struct ipheader));
  struct tcpheaderOptions *TCPOptions = (struct tcpheaderOptions *) (datagram + sizeof(struct tcpheader) + sizeof(struct ipheader));
  struct sockaddr_in sin;               //Te destination
  sin.sin_family = AF_INET;
  sin.sin_port = htons(4);
  sin.sin_addr.s_addr = inet_addr("192.168.1.114");

  IPInfo->iph_ver       = 4;            //What IP version are we using? v4
  IPInfo->iph_ihl       = 5;            //The IP header size in bytes
  IPInfo->iph_tos       = 0;            //The IP header type of service 0x00 is normal
  IPInfo->iph_len       = sizeof(struct ipheader) + sizeof(struct tcpheader) + sizeof(struct tcpheaderOptions);            //The IP length of the IP datagram
  IPInfo->iph_ident     = htonl(54321);         //The IP header ID (used when fragmented)
  IPInfo->iph_offset    = 0;            //IP fragment offset
  IPInfo->iph_ttl       = 255;          //The IP TTL
  IPInfo->iph_protocol          = 6;            //The transport layer protocol (6 for TCP, 1 for ICMP, 17 for UDP)
  IPInfo->iph_chksum    = 0;            //Checksum
  IPInfo->iph_sourceip  = inet_addr("192.168.1.129"); //source
//  IPInfo->iph_destip = sin.sin_addr.s_addr;
  IPInfo->iph_destip    = inet_addr("192.168.1.114");
char source[20];
char dest[20];
inet_ntop(AF_INET, &(IPInfo->iph_sourceip), source, 20);
inet_ntop(AF_INET, &(IPInfo->iph_destip), dest, 20);
printf("Source: %s\n", source);
printf("Dest: %s\n", dest);
  //IPInfo->ip_dst.s_addr       = inet_addr("192.168.1.114");
  TCPHeader->tcph_srcport       = htons(56540);           //The source port
  TCPHeader->tcph_destport      = htons(445);          //The destination port
  srand(time(NULL));
  TCPHeader->tcph_seqnum        = rand();          //the sequence number
  TCPHeader->tcph_acknum        = 0;                 //ACK packet
  TCPHeader->tcph_reserved      = 0;                    //Not used
  TCPHeader->tcph_offset        = 10;                 //
  TCPHeader->tcph_cwr           = 0;
  TCPHeader->tcph_ns            = 0;
  TCPHeader->tcph_syn           = 1;
  TCPHeader->tcph_rst           = 0;
  TCPHeader->tcph_psh           = 0;
  TCPHeader->tcph_ack           = 0;
  TCPHeader->tcph_urg           = 0;
  TCPHeader->tcph_ece           = 0;
  TCPHeader->tcph_cwr           = 0;
  TCPHeader->tcph_ns            = 0;
  TCPHeader->tcph_win           = htons(1024);
  TCPHeader->tcph_chksum        = 0;
  TCPHeader->tcph_urgptr        = 0;
  TCPOptions->tcph_mssOpt       = 2;
  TCPOptions->tcph_mssLen       = 4;
  TCPOptions->tcph_winOpt       = 3;
  TCPOptions->tcph_winLen       = 3;
  TCPOptions->tcph_sack         = 4;
  TCPOptions->tcph_sackLen      = 2;
  TCPOptions->tcph_win          = 7;
  TCPOptions->tcph_winNOP       = 1;
  TCPOptions->tcph_mss          = htons(1460);
  TCPOptions->tcph_timeOpt      = 8;
  TCPOptions->tcph_timeLen      = 10;
  TCPOptions->tcph_time         = 0xdb2b0d00;
  //Adding the data
  //strcpy(datagram + sizeof(struct ipheader) + sizeof(struct tcpheader),data);
  TCPHeader->tcph_chksum = csum((unsigned short *) datagram,TCPHeader->tcph_offset >> 1);
  IPInfo->iph_chksum = csum((unsigned short *) datagram, IPInfo->iph_len >> 1);


  int sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
  if(sockfd == -1) {
    perror("sockfd");
    exit(1);
  }

  //Setting IP_HDRINCL so that the system doesnt add headers to my packets
  {
    int one = 1;
    const int *val = &one;
    if(setsockopt(sockfd,IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) {
      perror("setsockopt");
      return -1;
    }
    else
      printf("Using your own header\n");
  }
  //Creating a raw socket to send info on
    if(sendto(sockfd, datagram, IPInfo->iph_len, 0, (struct sockaddr *) &sin, sizeof (sin)) < 0)
      perror("send");
    else
      printf("sending\n");

  printf("Sent sequence number: %d\n",TCPHeader->tcph_seqnum);

        //Now we will wait to receive a message back
        memset(datagram,0,4096);
        int results = recv(sockfd,datagram,sizeof(datagram),0);
        printf("Results: %d\n",results);
        IPInfo = (struct ipheader *) datagram;
        TCPHeader = (struct tcpheader * ) (datagram + (IPInfo->iph_ihl * 4));
        printf("Packet: IPInfo->iph_ihl %d\n",IPInfo->iph_ihl);
        printf("ACK num = %d\n",TCPHeader->tcph_ack);

char source1[20];
char dest1[20];
inet_ntop(AF_INET, &(IPInfo->iph_sourceip), source, 20);
inet_ntop(AF_INET, &(IPInfo->iph_destip), dest, 20);    

    printf("Source: %s\n",source1);
    printf("Dest: %s\n",dest1);

    printf("Size of ipheader %d\n",sizeof(struct ipheader));
    printf("size of tcpheader %d\n",sizeof(struct tcpheader));

  return 0;
}

解决方案

Enable checksum validation in wireshark, so you're at least sure you're not calculating wrong checksums (in either the IP or TCP header) – nos

Thanks, my TCP checksum was invalid – Keith

这篇关于Linux C 原始套接字 TCP 握手的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆