How to set linux kernel not to send RST_ACK, so that I can give SYN_ACK within raw socket

时光怂恿深爱的人放手 提交于 2021-01-27 06:21:33

问题


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


回答1:


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.




回答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.



来源:https://stackoverflow.com/questions/8047728/how-to-set-linux-kernel-not-to-send-rst-ack-so-that-i-can-give-syn-ack-within-r

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!