5

I want to ask a classic question about raw socket programming and linux kernel TCP handling. I've done the research to some same threads like linux raw socket programming question, How to reproduce TCP protocol 3-way handshake with raw sockets correctly?, and TCP ACK spoofing, but still can't get the solution.

I try to make a server which don't listen to any port, but sniff SYN packets from remote hosts. After the server do some calculation, it will send back a SYN_ACK packet to corresponding SYN packet, so that I can create TCP Connection manually, without including kernel's operation. I've create raw socket and send the SYN_ACK over it, but the packet cannot get through to the remote host. When I tcpdump on the server (Ubuntu Server 10.04) and wireshark on client (windows 7), the server returns RST_ACK instead of my SYN_ACK packet. After doing some research, I got information that we cannot preempt kernel's TCP handling.

Is there still any other ways to hack or set the kernel not to responds RST_ACK to those packets? I've added a firewall to local ip of server to tell the kernel that maybe there's something behind the firewall which is waiting for the packet, but still no luck

Community
  • 1
  • 1
Xzorax
  • 71
  • 1
  • 7
  • Have you tried using iptables to block outgoing TCP packets? Hopefully, that can be done while still letting your raw packets through. – Dan Nov 16 '11 at 05:27
  • I am dying to know what application this has... you appear to be trying to hijack TCP connections. – Mike Pennington Dec 04 '11 at 00:20

2 Answers2

5

Did you try to drop RST using iptables?

iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP

should do the job for you.

patrickmdnet
  • 3,332
  • 1
  • 29
  • 34
Jekyll
  • 1,434
  • 11
  • 13
  • 1
    obviously you have to set this rule on the server on which you are using RAW sockets to avoid that your kernel send a RST because does not see for any TCP session open on your port – Jekyll Dec 20 '11 at 16:29
  • also see http://us.generation-nt.com/answer/can-iptables-block-tcp-rst-packets-only-help-173902771.html – patrickmdnet Dec 20 '11 at 17:25
2

I recommend using ip tables, but since you ask about hacking the kernel as well, here is an explanation of how you could do that (I'm using kernel 4.1.20 as reference):

When a packet is received (a sk_buff), the IP protocol handler will send it to the networking protocol registered:

static int ip_local_deliver_finish(struct sock *sk, struct sk_buff *skb)
{
        ...
        ipprot = rcu_dereference(inet_protos[protocol]);
        if (ipprot) {
           ...
           ret = ipprot->handler(skb);

Assuming the protocol is TCP, the handler is tcp_v4_rcv:

static const struct net_protocol tcp_protocol = {
    .early_demux    =   tcp_v4_early_demux,
    .handler    =  tcp_v4_rcv,
    .err_handler    =   tcp_v4_err,
    .no_policy  =   1,
    .netns_ok   =   1,
    .icmp_strict_tag_validation = 1,
};

So tcp_v4_cv is called. It will try to find the socket for the skb received, and if it doesn't, it will send reset:

int tcp_v4_rcv(struct sk_buff *skb)
{
    sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
    if (!sk)
        goto no_tcp_socket;

no_tcp_socket:
    if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
        goto discard_it;

    tcp_v4_send_reset(NULL, skb);
    ...

There are many different ways you can hack this. You could go to the xfrm4_policy_check function and hack/change the policy for AF_INET. Or you can just simply comment out the line that calls xfrm4_policy_check, so that the code will always go to discard_it, or you can just comment out the line that calls tcp_v4_send_reset (which will have more consequences, though).

Hope this helps.

Jay Medina
  • 544
  • 5
  • 12