下面是我的理解,可能有误,仅供参考。

要调优,三次/四次握手必须烂熟于心。

client                  server
(SYN_SENT)      —>  (SYN_RECV)
(ESTABLISHED)   <—
—>  (ESTABLISHED)

client(主动)            server
(FIN_WAIT_1)    —>    (CLOSE_WAIT)
(FIN_WAIT_2)    <—
(TIME_WAIT)     <—    (LAST_ACK)
—>    (CLOSED)

大家熟知的 SYN flooding/SYN spoofing 就是在 SYN_RECV 的状态下发起的进攻。这种由于 TCP/IP 协议引起的缺陷只能防治而不好根治,除非换了 TCP/IP。通过下面的方式,可以在一定程度上缓解 DDOS 攻击。

  • 增大半连接的队列,即 backlog queue
  • 人工干预以减少 SYS_RECV 的时间,可以降低第一个重传包的时间或者减少重传的次数

检测 SYN 攻击,可以使用 netstat 命令查看当前的连接类型以及连接数目,如果发现有大量的 SYN_RECV,就值得怀疑了:
$ netstat -tuna | grep :80 | awk '{print $6}' | sort | uniq -c

或者可以通过 wget/curl 从远端实际来测试一下访问的速度:
$ time wget -O /dev/null www.example.com
正常情况下,其 real time 在个位数(s)左右,如果出现长达数十秒乃至几百秒的情况,有可能是此类情况。

最简单的方式是通过 syncookie 实现,Linux 还实现了一种称作 SYN cookie 的机制,开启:
# echo 1 > /proc/sys/net/ipv4/tcp_syncookies

该机制会在服务器收到 SYN 请求后,构造一个带有 ISN(initial sequence number)的 SYN/ACK 包,该 ISN 称为 cookie,其实就是一个哈希。通过此就可以验证客户端的真实性了
注意:SYN cookie 机制不会使用到 backlog queue,因此不必担心 queue 被填满然后服务器主动放弃连接。

使用了 SYN cookie 之后,在 /var/log/kern.log 会发现不少如下的 log,起作用了 
possible SYN flooding on port 80. Sending cookies

除了使用 syncookie,还可以修改 backlog queue 来达到目的。backlog queue 是一个用来处理在三次握手过程中带有 SYN 标志的包的数据结构,可以用来控制系统同时处理的最大连接,当达到该阈值后,接下来的请求会被系统丢弃。这需要系统开辟额外的内存来处理进来的包。如果处理的不好会导致系统内存耗尽,导致严重的性能问题。

tcp_max_syn_backlog 定义了 backlog queue 的半连接数量:
# echo 90000 > /proc/sys/net/ipv4/tcp_max_syn_backlog

当客户端发起 SYN 请求后,服务端会立刻发送 SYN+ACK 的回应,该次半连接会到 backlog queue 中,服务器会等待客户返回 ACK,如果在一段时间内没有应答,服务器会重新发送刚刚的 SYN+ACK,经历了几次还是没有回应后,服务器会主动断开此次半连接。
我们就可以修改重发的次数来减少整个半连接的时间:
# echo 3 > /proc/sys/net/ipv4/tcp_synack_retries

——————————————————————————-
|Value|    Time of retransmission      |         Total time         |
——————————————————————————-
|1       | in 3rd second                          |            9 seconds      |
——————————————————————————-
|2       | in 3rd and 9th second            |            21 seconds   |
——————————————————————————-
|3       | in 3rd, 9th and 21st second  |            45 seconds    |
——————————————————————————-
这张表格显示了不同重传次数消耗的总时间

上面属于 passive 连接,也就是客户端连接服务端,还有个相反的 active TCP connection 参数:
# echo 3 > /proc/sys/net/ipv4/tcp_syn_retries

tcp_fin_timeout 参数会通知 kernel 在 FIN_WAIT_2 状态 sockets 的存活时间,根据理解应该是 server 主动终止,像下面这样。

server                        client
(FIN_WAIT_1)    —>    (CLOSE_WAIT)
(FIN_WAIT_2)    <—
(TIME_WAIT)     <—    (LAST_ACK)
—>    (CLOSED)

当处于 CLOST_WAIT 的 client 有意(攻击)/无意(client 突然崩溃等)不发 fin 来继续时,server 会一直停留在 FIN_WAIT_2 状态,造成资源的浪费。
可以适当的减小该时间:
# echo 15 > /proc/sys/net/ipv4/tcp_fin_timeout

跟 tcp_fin_timeout 相关的有 tcp_max_orphans 参数,表示没有跟任何用户文件相关联的 socket 最大个数,超出的将被内核丢弃。
建议该参数只增加不减小,但增加也意味着内存的消耗增加:
# echo 327680 > /proc/sys/net/ipv4/tcp_max_orphans

相关的 tcp_orphans_retries 关闭本端 TCP 连接前的重试次数,默认 7,高负载的 webserver 建议可以减小。这里解释了设置为 0 的情况。

下面这三个参数一起解释:
tcp_tw_recycle
tcp_tw_reuse
tcp_timestamps

其中 tcp_tw_recycle/tcp_tw_reuse 这两个官方的建议保持默认为 0,而 tcp_timestamps 这个参数在特定的情况开启会引起很严重的问题(via 12)。

基本的情况就是,你的客户或者你的服务器在一个 NAT 后面,如果开启这个参数,会导致服务器能收到三次握手的 SYN 但是不会返回任何的 SYN+ACK,其结果是客户无法访问你的网站。可以通过 tcpdump 或者下面的这个查看:
# netstat -s | grep timestamp

tcp_timestamps 是 tcp 协议中的一个扩展项,通过时间戳的方式来检测过来的包以防止 PAWS(Protect Against Wrapped  Sequence numbers),可以提高 tcp 的性能,2.6 的内核默认是打开的。只要 client/server/nat/loadbalancer 不同时打开该选项就不会出现上面的问题。与之相关的包括 tcp_tw_recycle,如果 tcp_timestamps 和 tcp_tw_recycle 同时开启,就会开启时间戳选项,导致上面的问题。如果有上述的网络结构,比较合理的方式是禁用 tcp_tw_recyle 而开启 tcp_timestamps。禁用了 tcp_tw_recycle 其 TIME_OUT sockets 回收功能就没了,可以配合 tcp_tw_reuse 让 TIME_WAIT 降下来。

netdev_max_backlog 这个参数跟 TCP 的传输队列有关,发送队列长度是 txqueuelen ,netdev_backlog 则决定接收队列的长度。
前者通过 ifconfig 命令改变:
# ifconfig eth0 txqueuelen 10000
对于高吞吐的网络而言,默认的 100 肯定是不够的,一个 rrt 为 120ms 的千兆以太网络,可以设置成 10000 以上的值。

对于接受端而言,需要修改的话就涉及到了 /proc/sys/net/core/netdev_max_backlog 了,如果接收包的速度大于内核能处理的速度,则需要队列来维持,此数值表示最大队列值。默认为 1000,如果超过该数值,会引起丢包,根据实际情况增大。

对于网络不是很好的情况,可以开启 tcp_sack 参数。该实现是 TCP 的一个选项,称为 Selective Acknowlegement(SACK),默认开启,对于千兆网络可以关闭,能提高一定的性能。

keepalive 的情况,Linux 内置支持,只需要开启相应的内核参数就可以了,主要是下面三个:
tcp_keepalive_time 表示 TCP 发出第一个 keepalive 信息之前等待的时间,默认为 7200
tcp_keepalive_intvl keepalive 的时间间隔,默认是 75
tcp_keepalive_probes 触发的次数,默认是 9

ip_local_port_range 128M 内存以上的机器默认是 32768 61000,可以进一步扩大 10240 65535,尽量不要使用 1024 周围的,避免冲突。

以上只是网络内核参数的一小小部分,有待继续补充。

ref:

http://www.frozentux.net/ipsysctl-tutorial/chunkyhtml/tcpvariables.html

http://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt

http://www.symantec.com/connect/articles/hardening-tcpip-stack-syn-attacks

http://www.saview.net/archives/201

sysctl.conf网络内核参数说明(转)的更多相关文章

  1. /etc/sysctl.conf 控制内核相关配置文件

    /etc/sysctl.conf 用于控制内核相关的配置参数,而且它的内容全部是对应于 /proc/sys/ 这个目录的子目录及文件 [root@MongoDB ~]# ll /proc/sys to ...

  2. /etc/sysctl.conf 调优 & 优化Linux内核参数

    from: http://apps.hi.baidu.com/share/detail/15652067 http://keyknight.blog.163.com/blog/static/36637 ...

  3. (转)/etc/sysctl.conf 调优 & 优化Linux内核参数

    /etc/sysctl.conf 调优 & 优化Linux内核参数 from: http://apps.hi.baidu.com/share/detail/15652067 http://ke ...

  4. [Kernel参数]----/etc/sysctl.conf

    修改sysctl方法 方法一:修改/proc下内核参数文件内容 直接修改内核参数ip_forward对应在/proc下的文件/proc/sys/net/ipv4/ip_forward.用下面命令查看i ...

  5. linux内核参数sysctl.conf,TCP握手ack,洪水攻击syn,超时关闭wait

    题记:优化Linux内核sysctl.conf参数来提高服务器并发处理能力 PS:在服务器硬件资源额定有限的情况下,最大的压榨服务器的性能,提高服务器的并发处理能力,是很多运维技术人员思考的问题.要提 ...

  6. linux内核参数sysctl.conf,TCP握手ack,洪水攻击syn,超时关闭wait(转)

    http://www.xshell.net/linux/Linux_sysctl_conf.html 优化Linux内核sysctl.conf参数来提高服务器并发处理能力 Posted by 破冰 o ...

  7. 内核参数优化/etc/sysctl.conf

    net.nf_conntrack_max = 65536000net.netfilter.nf_conntrack_tcp_timeout_established = 1200net.ipv4.tcp ...

  8. linux 作为web应用服务器内核参数/etc/sysctl.conf

    # Kernel sysctl configuration file for Red Hat Linux## For binary values, 0 is disabled, 1 is enable ...

  9. linux 部署nginx作为反向代理入口的内核参数/etc/sysctl.conf

    # Kernel sysctl configuration file for Red Hat Linux## For binary values, 0 is disabled, 1 is enable ...

随机推荐

  1. Unity3d外包(北京)公司(长年承接U3D外包)

    我们制作各类型严肃游戏,虚拟现实,增强现实项目! 品质保证,售后完备. 联系请加QQ:372900288  电话:13911652504 我们团队成立于2011年10月,是一个专业从事严肃游戏研发的团 ...

  2. 个人博客作业Week2

    一.是否需要有代码规范 这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 我反驳这个观点,这些规范是成千上万的程序员在开发程序中总结出来的代码规范,他有助于我们的开 ...

  3. [地图SkyLine二次开发]框架(3)

    上节将显示我们地图的OBJECT控件,布了一下局,但地图没有进行加载. 这是因为我们要在另一个页面,对OBJECT控件进行地图加载,并且得到该控件的sgworld,以便对其进行我们想要的开发. 这里, ...

  4. PHP获取当前时间戳,当前时间、及解决时区问题

    一.获取当前时间戳 方法1:通过time函数 time(); 方法2:通过$_SERVER中的REQUEST_TIME元素 $_SERVER['REQUEST_TIME']; 方法3:通过strtot ...

  5. hibernate一级缓存的源码初窥

    hibernate的一级缓存的存在使得hibernate可以在操作实体化对象的时候减少对于数据库的访问.hibernate的一级缓存实际上就是指的session缓存,它的生命周期和session相同. ...

  6. Webpack、Browserify和Gulp

    https://www.zhihu.com/question/37020798 https://www.zhihu.com/question/35479764

  7. python实现查看目录下重复的文件

    该python 脚本有以下三个功能: 1. 实现查看目录下重复的文件,输出文件按修改时间升序排列 2. 将按修改时间排列比较旧的.可删除的文件列出来 3. 按目录对重复文件进行统计,比如,目录/tmp ...

  8. EasyUI的combobox控件使用onchange 问题

    在项目中几次都遇到了同样的问题,现在都不知道怎样解决了! 路过的朋友们帮我看看嘛!谢谢了! 最后我想要实现的效果是这样的.   在下拉列表中不存在值.(这里的是下拉列表中存在值的!)  但是在我输入值 ...

  9. Android 开发如何选择轮子(转)

    一个项目的开发,我们不可能一切从0做起,如果真是这样,那同样要哭瞎.因此,善于借用已经做好的 "车轮" 非常重要,如: 网络访问框架:OKHttp.retrofit.android ...

  10. ExtJS获取父子、兄弟容器元素方法

    http://www.cnblogs.com/CoolHu/archive/2012/12/08/2808433.html 1.当前对象的父对象(上级对象) this.ownerCt: 2.当前对象的 ...