【问题标题】:Is there a way for Linux to log the reason of sending out a TCP RST packet?Linux 有没有办法记录发送 TCP RST 数据包的原因?
【发布时间】:2018-01-20 19:21:53
【问题描述】:

运行这个版本的内核 4.11.8-1.el6.elrepo.x86_64 并想知道为什么 TCP 堆栈会发送一些 RST 数据包,即是否存在与 BSD net.inet.tcp.log_debug=1 对应的 Linux 版本?

以下是需要原因的情况之一。在握手的最终到达 ACK 之后立即发送 RST。可以看到SYN丢了好几次,最后一个ACK也超过1s没有到达。但仍不清楚为什么要发送 RST。禁用 syn cookie 没有帮助。

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

感谢您的帮助。

【问题讨论】:

  • 不是问题的答案,但在这种特定情况下,由于客户端在“15:27:46.547072”不正确的“ack 1”发送了 RST(应该是“确认 1773519352")
  • 谢谢,但是握手后的ack数1只是tcpdump调整的,方便阅读。
  • 你可以用iptables -I OUTPUT -p tcp -m tcp --tcp-flags SYN,ACK,FIN,RST RST -j LOG追踪他们,然后查看/var/log/kern.log

标签: linux tcp linux-kernel tcpdump


【解决方案1】:

这个确切的功能不可用,可以通过查看调用tcp_send_active_reset 的代码来查看。在code 喜欢:

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

显示的多个原因中的哪一个导致 RST 没有提供给任何调试宏,也没有提供给 tcp_send_active_reset。

Linux 4.15 添加了跟踪点,包括tcp:tcp_send_reset,如this blog entry 中所述。对于许多重置,可以将来自函数和跟踪点的动态探测的状态汇总在一起,以与内核相同的方式检查它并推断其选择的原因。这是不平凡的,因为在我的重置可能起源的示例中,套接字已经在使用tcp:tcp_send_reset 探针的函数之前更改了状态,因此必须在调用tcp_disconnect() 时结合检查 sk->sk_state 的动态探针或 tcp_set_state() 获取 old_state,并在 tcp_send_active_reset 中的跟踪点进行探测,以确认重置已在特定套接字上发送。

【讨论】:

    猜你喜欢
    • 2020-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 2020-03-13
    相关资源
    最近更新 更多