我在配置文件中将tcp_tw_recycle / reuse都设置为1。
这样做的后果是什么?
如果重新使用TCP套接字,是否会带来安全风险?即2个不同的连接都可能能够发送数据?
它是否适用于寿命短的连接,并且有重新连接的机会?
我在配置文件中将tcp_tw_recycle / reuse都设置为1。
这样做的后果是什么?
如果重新使用TCP套接字,是否会带来安全风险?即2个不同的连接都可能能够发送数据?
它是否适用于寿命短的连接,并且有重新连接的机会?
Answers:
默认情况下,当同时禁用tcp_tw_reuse
和时tcp_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
套接字可能已经过期,因此这将不是问题);TIME_WAIT
连接会保留一些,但是其他连接可能会被删除TCP RST
,从而释放一些空间);在后一种情况下,您可以在同一IP地址后面有多个主机,因此,时间戳的序列不同(或者说,在每个连接处,防火墙都会随机分配这些时间戳)。在这种情况下,某些主机将随机无法连接,因为它们被映射到TIME_WAIT
服务器的存储桶具有较新时间戳的端口。这就是为什么文档告诉您“由于设置,NAT设备或负载平衡器可能会开始丢帧”的原因。
有人建议让tcp_tw_recycle
独自一人,但能tcp_tw_reuse
和降低tcp_timewait_len
。我同意 :-)
我只是被我咬了一口,所以也许有人可能会从我的痛苦和磨难中受益。首先,一个包含大量信息的链接:http : //vincent.bernat.im/zh/blog/2014-tcp-time-wait-state-linux.html
特别是:
缺乏文档的唯一结果是,我们找到了许多调优指南,建议将这两个设置都设置为1,以减少TIME-WAIT状态下的条目数。但是,如tcp(7)手册所述,net.ipv4.tcp_tw_recycle选项对于面向公众的服务器来说是个问题,因为它无法处理来自同一NAT设备后面的两台不同计算机的连接,这是一个很难解决的问题发现并等待咬你:
我曾经成功地启用了这些功能,以提供尽可能低的延迟,从客户端到MySql NDB群集的haproxy连接。这是在私有云中,任何连接到任何连接都没有任何类型的NAT。用例很有道理,可以尽可能地减少通过haproxy攻击Radius客户端到NDB的延迟。它是这样做的。
我在面向公众的haproxy系统上再次进行了此操作,平衡了网络流量,却没有真正研究其影响(愚蠢,对吗?!),并经过大量的故障排除和追捕后发现:
在客户方面,他们将看到一段时间不再获得对SYN数据包的响应,有时会在这里和那里,有时会很长一段时间。再次,随机。
根据我最近的经历(痛苦的经历),这里的简短故事是,不管角色如何,在面向公众的服务器上都将这些设置单独/禁用!
从“ 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.
那里没有太多帮助。此举也有一些很好的见解:
/programming/6426253/tcp-tw-reuse-vs-tcp-tw-recycle-which-to-use-or-both
但是没有关于为什么重用比回收更安全的具体信息。基本的答案是,如果TIME_WAIT中已经有一个套接字具有相同的TCP参数,并且处于没有预期进一步通信的状态(我相信在发送FIN后,它将可以使用一个套接字)使用tcp_tw_reuse )。另一方面,tcp_tw_recycle只会使用相同的参数重用TIME_WAIT中的套接字,而不管其状态如何,这可能会使有状态的防火墙(可能期望使用不同的数据包)感到困惑。
通过设置SO_REUSEADDR套接字选项,可以有选择地在代码中完成tcp_tw_reuse,其记录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.
SO_REUSEADDR
与链接tcp_tw_reuse
吗?据我所知,SO_REUSEADDR
仅在需要时才适用bind()
,而如果需要创建新的传出连接,tcp_tw_reuse
它将指示内核重用处于TIME_WAIT
状态的本地套接字的端口。