linux 内核参数tcp_max_syn_backlog对应的队列最小长度

linux 内核参数tcp_max_syn_backlog对应的队列最小长度,第1张

概述环境:centos7.4 内核版本3.10 内核参数net.ipv4.tcp_max_syn_backlog定义了处于SYN_RECV的TCP最大连接数,当处于SYN_RECV状态的TCP连接数超过t

环境:centos7.4 内核版本3.10

内核参数net.ipv4.tcp_max_syn_backlog定义了处于SYN_RECV的TCP最大连接数,当处于SYN_RECV状态的TCP连接数超过tcp_max_syn_backlog后,会丢弃后续的SYN报文。

为了测试上述结论,首先将tcp_syncookies设置为0,并将net.ipv4.tcp_max_syn_backlog设置为2,测试拓扑为:1.1.1.1(clIEnt)------1.1.1.2:19090(server),在clIEnt端添加如下iptables规则,在发送完SYN报文后,底层丢弃接收到的SYN/ACK报文

iptables -t filter -I input -p tcp -m tcp --sport 19090  --tcp-flag SYN,ACK SYN,ACK -j DROP

但在实际测试中发现处于SYN_RECV状态的连接数可以大于设置的值2,且如果此时触发新的连接,该连接也能正常建链。难道tcp_max_syn_backlog没有生效?通过查找文档,发现在这篇文章中给出了原因。在内核net/core/request_sock.c中的实现如下,红色字体代码给出了计算tcp_max_syn_backlog的最小值。sysctl_max_syn_backlog的值对应手动设置的net.ipv4.tcp_max_syn_backlog的值。

int reqsk_queue_alloc(struct request_sock_queue *queue,unsigned int nr_table_entrIEs){    size_t lopt_size = sizeof(struct Listen_sock);    struct Listen_sock *lopt;    nr_table_entrIEs = min_t(u32,nr_table_entrIEs,sysctl_max_syn_backlog);    nr_table_entrIEs = max_t(u32,8);    nr_table_entrIEs = roundup_pow_of_two(nr_table_entrIEs + 1);    lopt_size += nr_table_entrIEs * struct request_sock *);    if (lopt_size > PAGE_SIZE)        lopt = vzalloc(lopt_size);    else        lopt = kzalloc(lopt_size,GFP_KERNEL);    if (lopt == NulL)        return -ENOMEM;    for (lopt->max_qlen_log = 3;         (1 << lopt->max_qlen_log) < nr_table_entrIEs;         lopt->max_qlen_log++);    get_random_bytes(&lopt->hash_rnd,sizeof(lopt->hash_rnd));    rwlock_init(&queue->syn_wait_lock);    queue->rskq_accept_head = NulL;    lopt->nr_table_entrIEs = nr_table_entrIEs;    write_lock_bh(&queue->syn_wait_lock);    queue->Listen_opt = lopt;    write_unlock_bh(&queue->syn_wait_lock);    return 0;}

可以看到当sysctl_max_syn_backlog=2时,计算过程如下:

nr_table_entrIEs = min_t(u32,sysctl_max_syn_backlog);nr_table_entrIEs为Listen backlog的值,即系统net.core.somaxconn的值,默认128。此处获取nr_table_entrIEs和sysctl_max_syn_backlog的最小值,得出nr_table_entrIEs=2nr_table_entrIEs = max_t(u32,8);计算nr_table_entrIEs和8的最大值,此时得出nr_table_entrIEs=8nr_table_entrIEs = roundup_pow_of_two(nr_table_entrIEs + 1);计算(1ul << (ilog2((9) - 1) + 1)),即1<<3=16。这就是net.ipv4.tcp_max_syn_backlog的最小值

使用如下脚本模拟syn flood攻击,当 watch 'netstat -antp|grep SYN_RECV|wc -l' 等于16时,换一台机器连接server发现连接超时;设置tcp_syncookies=1,重复上面测试,当 watch 'netstat -antp|grep SYN_RECV|wc -l' 等于16时,换一台机器连接server发现此时连接成功。

#!/bin/shinitPort=10000for ((i=1; i<=200; i ++))do    initPort=$[initPort+1]    sendip -v -p  ipv4 -is 1.1.1.1 -p tcp  -ts $initPort -td 19090 -tfs -tots 1.1.1.2    sleep 0.5done

 

总结

以上是内存溢出为你收集整理的linux 内核参数tcp_max_syn_backlog对应的队列最小长度全部内容,希望文章能够帮你解决linux 内核参数tcp_max_syn_backlog对应的队列最小长度所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/1015392.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存