Linux TCP socket 开发中 listen backlog 的含义

TCP socket 服务开发的4个步骤 socket->bind->listen->accept
调用listen函数时,有一个backlog参数.html

int listen(int sockfd, int backlog);linux

FreeBSD 和 Linux的实现有些不一样, 本文讨论Linux.
在Linux中backlog表示已完成(ESTABLISHED)且未accept的队列大小.git

TCP链接建立过程
服务器收到客户端SYN包,发送SYN+ACK包后,在内存建立一个状态为SYN_RCVD 的链接,放入未完成队列,这个队列的大小可经过/proc/sys/net/ipv4/tcp_max_syn_backlog设置.github

服务器收到客户端的ACK包后,该链接的状态由SYN_RCVD改成ESTABLISHED,并移到已完成队列.
服务器程序调用accept后,该链接移除已完成队列, 由内核交给程序控制.服务器

TCP 三次握手在应用程序accept以前由内核完成. 应用程序调用accept只是获取已经完成的链接.cookie

已完成队列满后
一般未完成队列的长度大于已完成队列.
已完成队列满后, 当服务器收到来自客户端的ACK包时
若是 /proc/sys/net/ipv4/tcp_abort_on_overflow 设为 1, 直接回RST包,结束链接.
不然忽视ACK包.
内核有定时器管理未完成队列,对于因为网络缘由没收到ACK包或是收到ACK包后被忽视的SYN_RCVD链接重发SYN+ACK包, 最多重发次数由/proc/sys/net/ipv4/tcp_synack_retries 设定.网络

backlog 即上述已完成队列的大小, 这个设置是个参考值,不是精确值. 内核会作些调整, 大于/proc/sys/net/core/somaxconn, 则取somaxconn的值socket

未完成队列满后
若是启用syncookies (net.ipv4.tcp_syncookies = 1),新的链接不进入未完成队列,不受影响.
不然,服务器不在接受新的链接.tcp

SYN 洪水攻击(syn flood attack)
经过伪造IP向服务器发送SYN包,塞满服务器的未完成队列,服务器发送SYN+ACK包 没回复,反复SYN+ACK包,使服务器不可用.函数

启用syncookies 是简单有效的抵御措施.
启用syncookies,仅未完成队列满后才生效.

参考:
http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
http://blog.dubbelboer.com/2012/04/09/syn-cookies.html
http://blog.csdn.net/justlinux2010/article/details/8604676

相关文章
相关标签/搜索