Chinaunix首页 | 论坛 | 博客
  • 博客访问: 633890
  • 博文数量: 356
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2287
  • 用 户 组: 普通用户
  • 注册时间: 2013-04-08 17:08
文章分类

全部博文(356)

文章存档

2023年(3)

2022年(7)

2021年(33)

2020年(47)

2019年(36)

2018年(221)

2017年(1)

2015年(1)

2013年(7)

我的朋友

分类: LINUX

2018-12-06 14:49:45

原文地址:深入浅出TCP之listen 作者:weizhulinux

int listen(int fd, int backlog);  


有几个概念需要在开头澄清一下

TCP socket分两种,监听socket和传输socket两种

监听socket:负责处理网络上来的连接请求(客户端的syn包到达便是连接请求来了,如果不知道syn包,请参看一下TCP三次握手);

传输socket:负责在网络上的两个端点之间传输TCP数据。


未决socket:pending socket,就是某客户端的syn包到达,内核为这个syn包对应的tcp请求生成一个socket,但是此时三次握手并没有完成,这样的socket就是pending socket,是未决连接,没有经过三次握手认证的tcp连接。

已建立连接的socket:established socket,tcp服务器利用三次握手完成对客户端的简单认证之后,未决socket就变成已连接socket,后续可以用这个socket传输数据。

内核为每个tcp服务器维护两个socket队列:未决socket队列和已建立连接的socket队列

图 1


现在进入主题:)

在TCP服务器端创建socket完毕,调用listen函数的时候,系统下层发生了以下动作:

1. 将刚才创建的(fd所标示的)socket转换为此tcp服务器的监听socket,让此socket进入监听请求模式,此socket的tcp状态由CLOSE转至LISTEN.

2.内核为此监听socket所对应的tcp服务器建立一个未决socket队列和一个已建立连接socket队列

backlog这个参数用来决定未决socket队列的长度,有个映射关系,0表示长度可以无限大。


现在来串一串整个过程

监听socket收到某客户端的syn包,第一次握手完成;

然后内核为此syn请求生成一个pending socket,例如图1中的socket5,标记状态为SYN_RECV,并且将socket5加入相应的pending socket队列,并且服务器发出ack和syn,第二次握手完成。

后续针对此socket5有两种可能

1可能

过会儿客户端响应了服务器的syn(第三个ack到达),第三次握手结束。内核触发accept函数执行,将socket5状态标记为ESTABLISHED,并且将此socket5由pending socket queue移至established socket queue,如图2

             图2


2可能

客户端的最后一个ack并未来到,过很久,图1中的socket5超时了,被移除,如图3

            图3


到这儿,listen的作用应该清楚了


另外针对此listen,有两个极限情况导致的拒绝服务情况需要考虑

backlog设置过小,pending socket队列已满,此时客户端调用connect发送syn分节给服务器端请求连接,服务端会忽略此syn包,客户端收不到syn的ack,会触发syn超时,这个超时时间比较长,重发syn,导致客户端长时间连接不上。

backlog设置为0或者过大,只要收到syn包,就会在pending socket队列中增加节点,这个容易导致队列变满。

Syn flood就是攻击pending socket队列的


linux 内核可以全局设置此pending socket队列大小

/proc/sys/net/ipv4/tcp_max_syn_backlog
还可以启用tcp_syncookies,来缓解pending socket队列的压力
echo "1" > / proc/sys/net/ipv4/tcp_syncookies
但是,这两个调整,对于巨量的synflood攻击来说,都是治标不治本。

阅读(1077) | 评论(0) | 转发(0) |
0

上一篇:TCP选项之SO_REUSEADDR

下一篇:trie树

给主人留下些什么吧!~~