原始套接字TCP握手不起作用

时间:2014-07-14 02:02:52

标签: c sockets networking network-programming raw-sockets

我正在尝试使用原始套接字模拟TCP握手。为了测试,我在同一台机器上使用服务器和客户端。我使用原始套接字的代码是一个被动服务器,它监听SYN并响应SYN / ACK。但是,我无法从客户端获取ACK。我使用tcpdump来读取清楚地显示我的数据包离开服务器的痕迹。这是跟踪:

13:49:35.389518 IP (tos 0x0, ttl 64, id 51534, offset 0, flags [DF], proto TCP (6), length 60)
    localhost.3333 > localhost.9999: Flags [S], cksum 0xfe30 (incorrect -> 0xd31d), seq 914929523, win 43690, options [mss 65495,sackOK,TS val 588877032 ecr 0,nop,wscale 7], length 0
        0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
        0x0010:  003c c94e 4000 4006 736b 7f00 0001 7f00  .<.N@.@.sk......
        0x0020:  0001 0d05 270f 3688 b773 0000 0000 a002  ....'.6..s......
        0x0030:  aaaa fe30 0000 0204 ffd7 0402 080a 2319  ...0..........#.
        0x0040:  8ce8 0000 0000 0103 0307                 ..........
13:49:35.389642 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    localhost.9999 > localhost.3333: Flags [S.], cksum 0xf9cb (incorrect -> 0x9b6d), seq 584475847, ack 914929524, win 43690, options [mss 65495,sackOK,TS val 588877032 ecr 588877032,nop,wscale 7], length 0
        0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
        0x0010:  003c 0000 4000 4006 3cba 7f00 0001 7f00  .<..@.@.<.......
        0x0020:  0001 270f 0d05 22d6 64c7 3688 b774 a012  ..'...".d.6..t..
        0x0030:  aaaa f9cb 0000 0204 ffd7 0402 080a 2319  ..............#.
        0x0040:  8ce8 2319 8ce8 0103 0307                 ..#.......
13:49:36.646081 IP (tos 0x0, ttl 64, id 29569, offset 0, flags [DF], proto TCP (6), length 60)
    localhost.3333 > localhost.9999: Flags [S], cksum 0xfe30 (incorrect -> 0x7c87), seq 1169489315, win 43690, options [mss 65495,sackOK,TS val 588877346 ecr 0,nop,wscale 7], length 0
        0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
        0x0010:  003c 7381 4000 4006 c938 7f00 0001 7f00  .<s.@.@..8......
        0x0020:  0001 0d05 270f 45b4 fda3 0000 0000 a002  ....'.E.........
        0x0030:  aaaa fe30 0000 0204 ffd7 0402 080a 2319  ...0..........#.
        0x0040:  8e22 0000 0000 0103 0307                 ."........
13:49:37.645510 IP (tos 0x0, ttl 64, id 29570, offset 0, flags [DF], proto TCP (6), length 60)
    localhost.3333 > localhost.9999: Flags [S], cksum 0xfe30 (incorrect -> 0x7b8d), seq 1169489315, win 43690, options [mss 65495,sackOK,TS val 588877596 ecr 0,nop,wscale 7], length 0
        0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
        0x0010:  003c 7382 4000 4006 c937 7f00 0001 7f00  .<s.@.@..7......
        0x0020:  0001 0d05 270f 45b4 fda3 0000 0000 a002  ....'.E.........
        0x0030:  aaaa fe30 0000 0204 ffd7 0402 080a 2319  ...0..........#.
        0x0040:  8f1c 0000 0000 0103 0307                 ..........

我明白不能简单地读取SYN数据包,因此我使用libpcap库来读取SYN数据包。我使用iptables来过滤RST,因为我没有人在服务器端监听(它是一个原始套接字)。当我试图用TCP的基本套接字函数模拟它并捕获它的跟踪它看起来与我的完全相同,除了我没有从客户端得到我的ACK。我不确定问题是什么。多年来一直坚持这一点。我发布了原始套接字创建的代码:

/ ** p_ip - SYN包的IP头| p_tcp - SYN包的TCP头| s_seq - SYN数据包的seq no * /

void send_syn_ack(int s_seq, struct ipheader *p_ip, struct tcpheader *p_tcp, __u8 *p_tcpopt)
{
    printf("seq is: %lu\n", ntohl(s_seq));

    char buffer[PKT_LEN];
    struct ipheader *ip = (struct ipheader *) buffer;
    struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof(struct ipheader));
    struct tcp_options *tcpoptions = (struct tcp_options *) (buffer + sizeof(struct tcpheader) + sizeof(struct ipheader));
    int one = 1;
    const int *val = &one;

    struct sockaddr_in sin;
    memset(&buffer, 0, sizeof(buffer));

    ip -> iph_ihl = 5;
    ip -> iph_ver = 4;
    ip -> iph_tos = 0;
    ip -> iph_len = htons(sizeof(struct ipheader) + sizeof(struct tcpheader) + 20);
    ip -> iph_ident = 0;
    ip -> iph_offset = 0x40;
     ip -> iph_ttl = 64;
    ip -> iph_protocol = 6;
    ip -> iph_chksum = 0;
    ip -> iph_sourceip = p_ip -> iph_sourceip;
    ip -> iph_destip = p_ip -> iph_destip;
    //ip -> ip_sum = in_cksum((unsigned short *)&ip, sizeof(ip));

    tcp -> tcph_srcport = p_tcp -> tcph_destport;
    tcp -> tcph_destport = p_tcp -> tcph_srcport;
    tcp -> tcph_seqnum = htonl(584475847);
    tcp -> tcph_acknum = htonl(ntohl(p_tcp -> tcph_seqnum) + 1);
    tcp -> tcph_hlen = 10;
    tcp -> tcph_syn = 1;
    tcp -> tcph_ack = 1;
    tcp -> tcph_win = htons(43690);
    //tcp -> tcph_chksum = (in_cksum_tcp( ntohl(ip -> iph_sourceip), ntohl(ip -> iph_destip), (buffer), 40));
    tcp -> tcph_chksum = 0;
    tcp -> tcph_urgptr = 0;
    //tcp.th_sum = in_cksum_tcp(ip.ip_src.s_addr, ip.ip_dst.s_addr, (unsigned short *)&tcp, sizeof(tcp))
    //ip -> iph_chksum = (in_cksum(buffer, sizeof(struct ipheader)));
    ip -> iph_chksum = htons(0xfe30);
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = (tcp -> tcph_srcport);
    sin.sin_addr.s_addr = (ip -> iph_sourceip);

    printf("Packet Information:\n");
    printf("Source: %s.%u\nDestination: %s.%u\nPacket Length: %d \n", printIP(ip -> iph_sourceip), ntohs(tcp -> tcph_srcport), printIP(ip -> iph_destip), ntohs(tcp -> tcph_destport), ntohs(ip -> iph_len));
    printf("Seq No: %lu \nAck No: %lu \n", ntohl(tcp -> tcph_seqnum), ntohl(tcp -> tcph_acknum));

    struct tcp_options *tmpopts = readOptions(p_tcpopt);
    memcpy(tcpoptions, tmpopts, 20);
    //tcp -> tcph_chksum = in_cksum_tcp(ip -> iph_sourceip, ip -> iph_destip, buffer + 20, 40);
    tcp -> tcph_chksum = htons(0xfe30);
    if ((sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
            perror("raw socket");
            exit(1);
    }

    if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
    {
            perror("ERROR: setsockopt() can't be performed!");
            exit(1);
    }
    else
            printf(">> setsockopt() is OK\n");

    int sent_length;

    if ((sent_length = sendto(sd, buffer, 60, 0, (struct sockaddr *)&sin, sizeof(sin))) < 0)  {
            perror("sendto");
            exit(1);
    }
    else
    {
     printf("Sent %d bytes\n", sent_length);
    }

}

我多年来一直坚持这个问题。有些人可以找出我需要看的问题吗?

更新: iptables规则:

Chain INPUT (policy DROP 27 packets, 864 bytes)


pkts bytes target     prot opt in     out     source               destination         
  813 48600 DROP       tcp  --  any    any     anywhere             anywhere             tcp dpt:9999
 173K   17M fail2ban-ssh  tcp  --  any    any     anywhere             anywhere             multiport dports ssh
3536K  720M ufw-before-logging-input  all  --  any    any     anywhere             anywhere            
3536K  720M ufw-before-input  all  --  any    any     anywhere             anywhere            
2745K  468M ufw-after-input  all  --  any    any     anywhere             anywhere            
55829 2150K ufw-after-logging-input  all  --  any    any     anywhere             anywhere            
55829 2150K ufw-reject-input  all  --  any    any     anywhere             anywhere            
55829 2150K ufw-track-input  all  --  any    any     anywhere             anywhere            

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ufw-before-logging-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-before-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-after-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-after-logging-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-reject-forward  all  --  any    any     anywhere             anywhere            

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       tcp  --  any    any     anywhere             anywhere             tcp spt:9999flags: RST/RST
 833K 1132M ufw-before-logging-output  all  --  any    any     anywhere             anywhere            
 833K 1132M ufw-before-output  all  --  any    any     anywhere             anywhere            
61973 3938K ufw-after-output  all  --  any    any     anywhere             anywhere            
61973 3938K ufw-after-logging-output  all  --  any    any     anywhere             anywhere            
61973 3938K ufw-reject-output  all  --  any    any     anywhere             anywhere            
61973 3938K ufw-track-output  all  --  any    any     anywhere             anywhere            

正常套接字连接已建立跟踪:

13:50:13.739038 IP (tos 0x0, ttl 64, id 53527, offset 0, flags [DF], proto TCP (6), length 60)
    localhost.3333 > localhost.4040: Flags [S], cksum 0xfe30 (incorrect -> 0x23fb), seq 732324684, win 43690, options [mss 65495,sackOK,TS val 588886619 ecr 0,nop,wscale 7], length 0
        0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
        0x0010:  003c d117 4000 4006 6ba2 7f00 0001 7f00  .<..@.@.k.......
        0x0020:  0001 0d05 0fc8 2ba6 634c 0000 0000 a002  ......+.cL......
        0x0030:  aaaa fe30 0000 0204 ffd7 0402 080a 2319  ...0..........#.
        0x0040:  b25b 0000 0000 0103 0307                 .[........
13:50:13.739050 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    localhost.4040 > localhost.3333: Flags [S.], cksum 0xfe30 (incorrect -> 0x1502), seq 2134096447, ack 732324685, win 43690, options [mss 65495,sackOK,TS val 588886619 ecr 588886619,nop,wscale 7], length 0
        0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
        0x0010:  003c 0000 4000 4006 3cba 7f00 0001 7f00  .<..@.@.<.......
        0x0020:  0001 0fc8 0d05 7f33 ba3f 2ba6 634d a012  .......3.?+.cM..
        0x0030:  aaaa fe30 0000 0204 ffd7 0402 080a 2319  ...0..........#.
        0x0040:  b25b 2319 b25b 0103 0307                 .[#..[....
13:50:13.739064 IP (tos 0x0, ttl 64, id 53528, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.3333 > localhost.4040: Flags [.], cksum 0xfe28 (incorrect -> 0xe746), seq 1, ack 1, win 342, options [nop,nop,TS val 588886619 ecr 588886619], length 0
        0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
        0x0010:  0034 d118 4000 4006 6ba9 7f00 0001 7f00  .4..@.@.k.......
        0x0020:  0001 0d05 0fc8 2ba6 634d 7f33 ba40 8010  ......+.cM.3.@..
        0x0030:  0156 fe28 0000 0101 080a 2319 b25b 2319  .V.(......#..[#.
        0x0040:  b25b                                     .[
13:50:13.739084 IP (tos 0x0, ttl 64, id 53529, offset 0, flags [DF], proto TCP (6), length 58)
    localhost.3333 > localhost.4040: Flags [P.], cksum 0xfe2e (incorrect -> 0xe76c), seq 1:7, ack 1, win 342, options [nop,nop,TS val 588886619 ecr 588886619], length 6
        0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
        0x0010:  003a d119 4000 4006 6ba2 7f00 0001 7f00  .:..@.@.k.......
        0x0020:  0001 0d05 0fc8 2ba6 634d 7f33 ba40 8018  ......+.cM.3.@..
        0x0030:  0156 fe2e 0000 0101 080a 2319 b25b 2319  .V........#..[#.
        0x0040:  b25b 4090 b5bc 097f                      .[@.....
13:50:13.739089 IP (tos 0x0, ttl 64, id 2075, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.4040 > localhost.3333: Flags [.], cksum 0xfe28 (incorrect -> 0xe740), seq 1, ack 7, win 342, options [nop,nop,TS val 588886619 ecr 588886619], length 0
        0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
        0x0010:  0034 081b 4000 4006 34a7 7f00 0001 7f00  .4..@.@.4.......
        0x0020:  0001 0fc8 0d05 7f33 ba40 2ba6 6353 8010  .......3.@+.cS..
        0x0030:  0156 fe28 0000 0101 080a 2319 b25b 2319  .V.(......#..[#.
        0x0040:  b25b                                     .[

2 个答案:

答案 0 :(得分:1)

您是否尝试使用您感兴趣的iptables过滤数据包?我的意思是,我不确定你遇到的这个问题,也许作为提示你可以使用iptables来过滤带有SYN标志的数据包,并查看数据包是否丢弃数据包。

由于您在同一台计算机上使用服务器和客户端,因此数据包不会发送到您的NIC,但是,数据包将被发送到虚拟环回接口(您可以在Google上找到&# 34; loopback iptables&#34;)。

这不是如何解决问题,但是,获得一些关于如何修复它的提示可能会有用。我从来没有使用过原始套接字,所以我能帮助的就是这些东西。另一点是,您尝试连接的端口号必须设置为接受新连接,这意味着必须&#34;绑定&#34;。

祝你好运。

答案 1 :(得分:1)

我试图根据您发布的数据进行猜测:

首先,校验和不正确。如果您依靠NIC计算校验和,则不会对发往localhost的消息执行此操作。

其次,你能展示你正在使用的所有iptables规则吗?如果使用libpcap,则应使用将TCP消息丢弃到端口9999的规则。

第三,如果客户端使用AF_INET流套接字(&#34;普通&#34;套接字),请添加以下规则:

iptables -A INPUT -p tcp --dport 9999 -j DROP

删除其他DROP规则。