brainfreak
brainfreak

Reputation: 137

Raw socket TCP handshake not working

I am trying to simulate a TCP handshake using raw sockets. For testing, i am using server and client on the same machine. My code that uses raw sockets is a passive server that listens for SYN and respondswith SYN/ACK. However, i am not able to get the ACK back from the client. I used tcpdump to read the traces which clearly shows my packet leaving the server. This is the trace:

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@[email protected]......
        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.@[email protected]......
        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.@[email protected]......
        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                 ..........

I understood that one cannot simply read the SYN packet and so i used libpcap libraries to read the SYN packets. I used iptables to filter the RST from being sent for a SYN since i have no one listening on the server end(its a raw socket). When i tried to simulate the same with basic socket functions for TCP and captured it's trace it looks exactly identical to mine except that i don't get my ACK from client. I am not sure what the problem is. Been stuck with this for ages. i am posting the code for raw socket creation:

/** p_ip - IP header of SYN packet | p_tcp - TCP header of SYN packet | s_seq - seq no of SYN packet */

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);
    }

}

I have been stuck with this problem for ages. Can some figure out the problem i need to look at?

Update: iptables rules:

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            

Normal Sockets connection established trace:

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  .<..@[email protected].......
        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..@[email protected].......
        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  .:..@[email protected].......
        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..@[email protected].......
        0x0020:  0001 0fc8 0d05 7f33 ba40 2ba6 6353 8010  .......3.@+.cS..
        0x0030:  0156 fe28 0000 0101 080a 2319 b25b 2319  .V.(......#..[#.
        0x0040:  b25b                                     .[

Upvotes: 1

Views: 1603

Answers (2)

rodolk
rodolk

Reputation: 5907

I'm trying to guess based on the data you posted:

First, the checksum is incorrect. If you are relying on NIC calculating the checksum, it won't do it for messages going to localhost.

Second, can you show all iptables rules you are using? If you use libpcap, you should use a rule that drops TCP messages to port 9999.

Third, if the client is using AF_INET stream sockets ("normal" sockets), add the following rule:

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

And remove the other DROP rules.

Upvotes: 1

campescassiano
campescassiano

Reputation: 831

Did you try to filter the packets using iptables that you are interested in? I mean, I am not sure about this problem you are having so, maybe as a hint you could use iptables to filter the packets that has the SYN flag on it and see with the counters that the packets are dropped or not.

Since you are using the Server and Client in the same computer, the packets won't go out to your NIC, but however, the packet gonna be send to the virtual loopback interface (you can find on Google "loopback iptables").

This is not how to solve the problem but, maybe it could be useful to get some hints about how to fix it. I've never used raw socket, so all I can help is with this stuff. Another point is that the port number you are trying to connect must be set to accept new connections, that means, must be "binded".

Wish you good luck.

Upvotes: 1

Related Questions