赞
踩
环境: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,unsignedintnr_table_entries)
{
size_t lopt_size= sizeof(structlisten_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);elselopt=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=2
nr_table_entries = max_t(u32,8);计算nr_table_entries和8的最大值,此时得出nr_table_entries=8
nr_table_entries = roundup_pow_of_two(nr_table_entries + 1);计算(1UL << (ilog2((9) - 1) + 1)),即1<<3=16。这就是net.ipv4.tcp_max_syn_backlog的最小值
@H_502_127@
@H_502_127@
使用如下脚本模拟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/sh
initPort=10000
for ((i=1; i<=200; i ++))doinitPort=$[initPort+1]
sendip-v -p ipv4 -is 1.1.1.1 -p tcp -ts $initPort -td 19090 -tfs -tots 1.1.1.2sleep0.5done
总结
如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
小编个人微信号 jb51ccc
喜欢与人分享编程技术与工作经验,欢迎加入编程之家官方交流群!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。