调用tcp_send_active_reset发送RESET报文:
- 当TCP调用tcp_close时,如果socket的sk_receive_queue中skb还有数据的话,则调用tcp_send_active_reset,向对端发送RESET报文。
- 当TCP调用tcp_out_of_resource时,当orphan(孤儿)socket过多,或者TCP内存高度紧张的时候,向对端发送RESET报文。
- tcp_out_of_resource会在写超时tcp_write_timeout和零窗口探测tcp_probe_timer的时候调用。
- 当关闭监听socket的时候,该监听socket及其生成的子socket通过调用sock_orphan()函数,sock_set_flag(sk, SOCK_DEAD),变成orphan socket。
- 当TCP调用tcp_disconnect时,如果当前socket状态为:TCPF_ESTABLISHED、TCPF_CLOSE_WAIT、TCPF_FIN_WAIT1、TCPF_FIN_WAIT2 或 TCPF_SYN_RECV时;则向对端发送RESET报文;或者如果当前socket状态为TCPF_CLOSING 或 TCPF_LAST_ACK,且tp->snd_nxt != tp->write_seq(当前socket有数据未发送完毕),则也向对端发送RESET报文。
- 当TCP调用tcp_close时,如果当前状态为LISTEN,则会调用inet_csk_listen_stop,其中调用tcp_disconnect;
- 当TCP调用tcp_close时,如果socket设置LINGER,并且lingertime不为0,则调用tcp_disconnect;
调用tcp_v4_send_reset发送RESET报文:
- TCP接收报文:在tcp_v4_rcv,如果校验和有问题,则发送RESET;
- TCP接收报文:在tcp_v4_rcv,如果 __inet_lookup_skb 函数找不到报文所请求的socket,则发送RESET;
- TCP收到SYN,发送SYN-ACK,并开始等待连接最后的ACK:在tcp_v4_do_rcv - tcp_v4_hnd_req - tcp_check_req,如果TCP报文头部包含RST,或者包含序列不合法的SYN,则发送RESET;
- TCP收到连接建立最后的ACK,并建立child套接字后:tcp_v4_do_rcv - tcp_child_process - tcp_rcv_state_process - tcp_ack 函数中,如果发现连接等待的最后ACK序列号有问题: before(ack, prior_snd_una),则发送RESET;
- TCP在ESTABLISH状态收到报文,在tcp_v4_do_rcv - tcp_rcv_established - tcp_validate_incoming 函数中,如果发现有SYN报文出现在当前的接收窗口中: th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt),则发送RESET;
- TCP在进行状态迁移时:tcp_rcv_state_process -
- 如果此时socket处于LISTEN状态,且报文中含有ACK,则发送RESET;
- 如果此时socket处于FIN_WAIT_1或者FIN_WAIT_2;当接收已经shutdown,并且报文中有新的数据时,发送RESET;
- 如果测试socket处于FIN_WAIT_1;=待续=
在iptables规则中数据包被拒:
- send_reset:在iptables规则中,可以指定 -j RESET。如果符合iptables规则并丢弃数据包,并向对端发送RESET报文;