5

Running this version of kernel 4.11.8-1.el6.elrepo.x86_64 and want to know why the TCP stack sends some RST packets, i.e. is there a Linux counterpart of the BSD net.inet.tcp.log_debug=1?

Following is one of the cases where the reason is wanted. A RST is sent immediately after the finally arrived ACK of the handshake. It can be seen that SYN got lost for several times and the last ACK did not arrive in more that 1s. But it is still not clear why the RST is sent. Disabling syn cookie does not help.

15:27:41.166799 IP CLIENT.16537 > SERVER.80: Flags [S], seq 1397492268, win 29200, options [mss 1440,sackOK,TS val 1230199 ecr 0,nop,wscale 6], length 0
15:27:41.166820 IP SERVER.80 > CLIENT.16537: Flags [S.], seq 1773519351, ack 1397492269, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0
15:27:42.069572 IP CLIENT.16537 > SERVER.80: Flags [S], seq 1397492268, win 29200, options [mss 1460,sackOK,TS val 1230299 ecr 0,nop,wscale 6], length 0
15:27:42.069590 IP SERVER.80 > CLIENT.16537: Flags [S.], seq 1773519351, ack 1397492269, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0
15:27:43.123141 IP SERVER.80 > CLIENT.16537: Flags [S.], seq 1773519351, ack 1397492269, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0
15:27:44.067228 IP CLIENT.16537 > SERVER.80: Flags [S], seq 1397492268, win 29200, options [mss 1460,sackOK,TS val 1230499 ecr 0,nop,wscale
 6], length 0
15:27:44.067240 IP SERVER.80 > CLIENT.16537: Flags [S.], seq 1773519351, ack 1397492269, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 9], length 0
15:27:46.547072 IP CLIENT.16537 > SERVER.80: Flags [.], ack 1, win 457, length 0
15:27:46.547094 IP SERVER.80 > CLIENT.16537: Flags [R], seq 1773519352, win 0, length 0
15:27:46.548177 IP CLIENT.16537 > SERVER.80: Flags [.], ack 1, win 457, options [nop,nop,sack 1 {0:1}], length 0
15:27:46.548186 IP SERVER.80 > ClIENT.16537: Flags [R], seq 1773519352, win 0, length 0

Thanks for helping.

Utoah
  • 1,052
  • 1
  • 12
  • 18
  • 1
    Not an answer to the question, but in this specific case the RST was probably sent due to the incorrect "ack 1" by the client at "15:27:46.547072" (it should have been "ack 1773519352") – user3151902 Aug 12 '17 at 11:00
  • Thanks, but the ack number of 1 after handshaking was just an adjustment by tcpdump for easy of read. – Utoah Aug 12 '17 at 11:38
  • U could track them, with `iptables -I OUTPUT -p tcp -m tcp --tcp-flags SYN,ACK,FIN,RST RST -j LOG` then look in `/var/log/kern.log` – F. Hauri - Give Up GitHub Sep 26 '19 at 15:48

1 Answers1

3

This exact functionality is not available, that can be seen by looking at the code for calls to tcp_send_active_reset. In code like:

int tcp_disconnect(struct sock *sk, int flags)
{
    ...
    int old_state = sk->sk_state;

    if (old_state != TCP_CLOSE)
        tcp_set_state(sk, TCP_CLOSE);

    if ...
    } else if (tcp_need_reset(old_state) ||
           (tp->snd_nxt != tp->write_seq &&
            (1 << old_state) & (TCPF_CLOSING | TCPF_LAST_ACK))) {
        /* The last check adjusts for discrepancy of Linux wrt. RFC
         * states
         */
        tcp_send_active_reset(sk, gfp_any());

which of the multiple reason shown caused the RST is not being provided to any debug macro, and is not provided to tcp_send_active_reset.

Linux 4.15 added tracepoints including tcp:tcp_send_reset as documented in this blog entry. For many resets it would be possible to pull together the state from dynamic probes on functions and tracepoints to examine it the same way your kernel did and infer the reason for its choice. This is non-trivial since in my example of where the reset could originate, the socket has already changed state before the function with the tcp:tcp_send_reset probe, so one must combine a dynamic probe examining sk->sk_state either on calling tcp_disconnect() or tcp_set_state() to get old_state, together with a probe at the tracepoint in tcp_send_active_reset to confirm the reset was sent on the particular socket.

lossleader
  • 13,182
  • 2
  • 31
  • 45