将 tcp_tw_recycle/reuse 设置为 1 的后果是什么?

cod*_*ing 10 ubuntu tcp socket

我在配置文件中将 tcp_tw_recycle/reuse 都设置为 1。

这样做的后果是什么?

如果重复使用 tcp 套接字,是否会带来安全风险?即 2 个不同的连接都可能能够发送数据?

它适用于重新连接机会很小的短期连接吗?

jpe*_*zzo 24

默认情况下,当tcp_tw_reusetcp_tw_recycle都被禁用时,内核将确保处于TIME_WAIT状态的套接字将保持在该状态足够长的时间——足够长的时间以确保属于未来连接的数据包不会被误认为是旧连接的延迟数据包。

当您启用时tcp_tw_reuse,处于TIME_WAIT状态的套接字可以在它们到期之前使用,并且内核将尝试确保没有关于 TCP 序列号的冲突。如果您启用tcp_timestamps(又名 PAWS,用于防止包装序列号),它将确保不会发生这些冲突。然而,你需要TCP时间戳上启用两个端(至少,这是我的理解)。有关详细信息,请参阅tcp_twsk_unique定义

当您启用 时tcp_tw_recycle,内核会变得更加激进,并且会对远程主机使用的时间戳做出假设。它将跟踪每个具有连接TIME_WAIT状态的远程主机使用的最后一个时间戳),如果时间戳正确增加,则允许重新使用套接字。但是,如果主机使用的时间戳发生变化(即及时回溯),SYN数据包将被静默丢弃,并且连接将无法建立(您将看到类似于“连接超时”的错误)。如果您想深入了解内核代码,tcp_timewait_state_process定义可能是一个很好的起点。

现在,时间戳永远不应该回到过去;除非:

  • 主机重新启动(但是,当它恢复时,TIME_WAIT套接字可能已经过期,因此这将不是问题);
  • IP地址很快被其他东西重用(TIME_WAIT连接会保留一点,但其他连接可能会被攻击TCP RST,这会释放一些空间);
  • 网络地址转换(或 smarty-pants 防火墙)涉及连接中间。

在后一种情况下,您可以在同一个 IP 地址后面有多个主机,因此,不同的时间戳序列(或者,所述时间戳在每个连接上由防火墙随机化)。在这种情况下,一些主机将随机无法连接,因为它们被映射到TIME_WAIT服务器存储桶具有更新时间戳的端口。这就是为什么文档会告诉您“NAT 设备或负载平衡器可能会因为设置而开始丢帧”的原因。

有些人建议不要管tcp_tw_recycle,但启用tcp_tw_reuse并降低tcp_timewait_len. 我同意 :-)


小智 6

我刚被咬了一口,所以也许有人会从我的痛苦和苦难中受益。首先,包含大量信息的相关链接:http : //vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.html

特别是:

缺乏文档的唯一结果是我们发现许多调整指南建议将这两个设置都设置为 1,以减少 TIME-WAIT 状态中的条目数。然而,正如 tcp(7) 手册页所述,net.ipv4.tcp_tw_recycle 选项对于面向公众的服务器来说是相当有问题的,因为它不会处理来自同一 NAT 设备后面的两台不同计算机的连接,这是一个很难解决的问题检测并等待咬你:

我使用这些功能非常成功地提供了尽可能低的延迟,从客户端到 MySql NDB 集群的 haproxy 连接。这是在私有云中,从任何连接到任何连接都没有混合使用任何类型的 NAT。用例是有道理的,尽可能降低半径客户端通过 haproxy 访问 NDB 的延迟。它这样做了。

我在一个面向公众的 haproxy 系统上再次做了它,负载平衡网络流量,没有真正研究影响(愚蠢,对吧?!)并在多次故障排除和追逐鬼之后发现:

  • 它将为通过 NAT 连接的客户端造成混乱。
  • 几乎不可能识别,因为它是完全随机的、间歇性的,并且症状会在与客户 B 完全不同(或不完全不同)的时间袭击客户 A,等等。

在客户方面,他们会看到他们不再收到对 SYN 数据包的响应的时间段,有时是这里和那里,有时是很长一段时间。再次,随机。

在我最近的痛苦经历中,这里的简短故事是将这些单独/禁用在面向公众的服务器上,无论角色如何!


小智 4

从“man 7 tcp”你会看到:

   tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
          Enable fast recycling of TIME_WAIT sockets.  Enabling this option is not recommended since this causes problems when working with NAT
          (Network Address Translation).

   tcp_tw_reuse (Boolean; default: disabled; since Linux 2.4.19/2.6)
          Allow  to  reuse  TIME_WAIT  sockets  for  new connections when it is safe from protocol viewpoint.  It should not be changed without
          advice/request of technical experts.
Run Code Online (Sandbox Code Playgroud)

那里没有太多帮助。这个问题也有一些很好的见解:

/sf/ask/449837741/

但没有具体说明为什么重复使用比回收更安全。基本答案是 tcp_tw_reuse 将允许使用相同的套接字,如果 TIME_WAIT 中已经存在具有相同 TCP 参数的套接字,并且该套接字处于预计不再有流量的状态(我相信当 FIN 已发送时) )。另一方面,tcp_tw_recycle 只会重用处于 TIME_WAIT 中且具有相同参数的套接字,而不管状态如何,这可能会混淆可能期待不同数据包的状态防火墙。

tcp_tw_reuse 可以通过设置 SO_REUSEADDR 套接字选项在代码中有选择地完成,记录man 7 socket如下:

   SO_REUSEADDR
          Indicates that the rules used in validating addresses supplied in a bind(2) call should allow reuse of local addresses.  For  AF_INET
          sockets  this means that a socket may bind, except when there is an active listening socket bound to the address.  When the listening
          socket is bound to INADDR_ANY with a specific port then it is not possible to bind to this port for any local address.   Argument  is
          an integer boolean flag.
Run Code Online (Sandbox Code Playgroud)