程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

Linux系统 TCP通信参数优化(linux tcp nodelay)

balukai 2025-02-03 11:21:05 文章精选 5 ℃

由于TCP通信的重要性和复杂性,对网络性能有直接的关系,linux系统内核关于TCP相关的参数配置非常之多,本文仅总结了一些工作中常用到的参数进行说明。

一、目录索引:

1. TCP帧格式详解和说明;

2. TCP的三个阶段的通信流程及原理;

3. TCP中半连接和全连接;

4. TCP窗口大小、MSS和MTU的区别;

5. 几种常见的重传机制:超时重传/快速重传/SACK/D-SACK;

6. TCP滑动窗口的理解;

7. TCP保活机制;

8. 什么是 SYN 攻击?如何避免TCP的SYN 攻击?

9.Linux 内核TCP其它参数设置方法

二、详细说明:

1.TCP帧格式说明:

下面是报文段首部各个字段的含义:

· 源端口号以及目的端口号:各占 2 个字节,端口是传输层和应用层的服务接口,用于寻找发送端和接收端的进程,一般来讲,通过端口号和IP地址,可以唯一确定一个 TCP 连接,在网络编程中,通常被称为一个 socket 接口。

· 序号:Seq 序号,占 4 个字节。用来标识从 TCP 发送端向 TCP 接收端发送的数据字节流序号,发起方发送数据时对此进行标记。

· 确认序号:Ack 序号,占 4 个字节,包含接收端所期望收到的下一个序号。只有 ACK 标记位为 1 时,确认序号字段才有效,因此,确认序号应该是上次已经成功收到数据字节序号加 1,即 Ack = Seq + 1。

· TCP头长度:占 4 个字节,用于指出 TCP 首部长度。

· 保留字段:占 6 位,暂时可忽略,值全为 0。

· 六位标志位:值内容含义如下

---URG(紧急):为1时表明紧急指针字段有效

---ACK(确认):为1时表明确认号字段有效

---PSH(推送):为1时接收方应尽快将这个报文段交给应用层

---RST(复位):为1时表明TCP连接出现故障必须重建连接

---SYN(同步):在连接建立时用来同步序号

---FIN(终止):为1时表明发送端数据发送完毕要求释放连接

· 窗口:占 2 个字节,用于流量控制和拥塞控制,表示当前接收缓冲区的大小。

· 校验和:占 2 个字节,范围包括首部和数据两部分

· 紧急指针:指出了紧急数据的末尾在报文段中的位置,和 URG 搭配使用

· 选项和填充:是可选的,默认情况是不选。


2. TCP的三个阶段的通信流程及原理:

TCP的三个阶段:创建连接(3次握手)、数据传送和释放连接(4次挥手)

1) 创建连接过程:

当两个设备之间准备传输数据之前,TCP 会建立连接,创建连接的阶段需要三次握手,过程如下:

详细过程如下:

a. 第一次握手:客户端向服务器端发出连接请求SYN,等待服务器确认;

b. 第二次握手:服务器端收到请求后,向客户端回送一个确认SYN+ACK,通知客户端收到了连接请求;

c. 第三次握手:客户端再次向服务器端发送确认ACK信息,确认连接;

完成以上 3 次握手之后,可靠性连接建立完成,就可以进行数据传输了。

相关的TCP系统设置参数见下面(TCP中半连接和全连接章节)

2) 数据传输过程:

通过序列号与确认应答机制,是 TCP 实现数据可靠传输的方式之一,也是最为重要的基石。但是在复杂的网络环境下,并不一定能如上图所描述的那样顺利的进行数据传输,例如数据包丢失,针对这种问题,TCP 使用了重传机制来解决。

相关的设置参数有:

(1). net.ipv4.tcp_retries1:默认是3次。当报文超时重传次数超过该值后,每次重传前,都会指示IP层进行MTU探测、刷新路由等,防止由于网络链路发生变化而导致TCP传输失败。对应
/proc/sys/net/ipv4/tcp_retries1;

(2). net.ipv4.tcp_retries2: 控制内核向已经建立连接的远程主机重新发送数据的次数,低值可以更早的检测到与远程主机失效的连接,因此服务器可以更快的释放该连接,可以修改为5,默认是15次,大约相当于13 ~ 30分钟;

(3). net.ipv4.tcp_max_orphans: 系统所能处理不属于任何进程的TCP sockets最大数量。假如超过这个数量,那么不属于任何进程的连接会被立即reset,并同时显示警告信息。对于net.ipv4.tcp_max_orphans = 65536,当orphans达到32768个时,会报Out of socket memory,此时占用内存 32K*64KB=2048MB=2GB(每个独立socket可占用多达64KB内存)

3) 释放连接过程:

· 第一次挥手:客户端向服务器端发出请求切断连接FIN,等待服务器确认;

· 第二次挥手:服务器端收到请求后,向客户端回送一个确认信息ACK,并同意关闭请求;

· 第三次挥手:服务器端再次向客户端发出请求切断连接FIN,等待客户端确认;

· 第四次挥手:客户端收到请求后,向服务器端回送一个确认信息ACK,并同意关闭请求.

完成以上 4 次挥手之后,连接释放完成。

相关的设置参数有:

(1)
net.ipv4.tcp_orphan_retries:
FIN报文重传次数最大值,默认值是0,特指8次。如果FIN报文重传次数达到该值且规定等待时间已结束,连接将直接关闭。如果是孤儿连接,重传次数虽未超过8次,但该连接自首次发出FIN报文开始,存活时间已超tcp_fin_timeout设定的时间,那么此时该连接也将会直接关闭。

(2) net.ipv4.tcp_fin_timeout:此字段用于控制TCP/IP协议栈中的FIN-WAIT-2状态的超时时间,默认值为 60 秒。在TCP协议中,当一端的连接主动关闭后,会进入FIN-WAIT-2状态,等待对方的确认,以确保双方都完成了连接关闭。当FIN-WAIT-2状态持续超过该参数值时,连接会被内核强制关闭,释放系统资源。较小的参数值可以更快地释放系统资源,但可能导致一些连接在网络不稳定的情况下被错误地关闭。

客户端收到FIN后,返回ack,接口状态为 TIME_WAIT; 客户端等待 FIN 的时间由 net.ipv4.tcp_fin_timeout 控制。

(3)
net.ipv4.tcp_max_tw_buckets:
接口进入 TIME_WAIT 状态后,可允许的最大连接数为
net.ipv4.tcp_max_tw_buckets,超过这个数量,连接会被摧毁。net.ipv4.tcp_tw_reuse 决定了是否对 TIME_WAIT 连接进行重用。net.ipv4.tcp_tw_recycle 决定是否对 TIME_WAIT 接口快速回收,这个参数在内核 4.12 版本后已废弃。

(4) net.ipv4.tcp_tw_reuse: 决定了是否对 TIME_WAIT 连接进行重用。表示是否允许重新应用处于TIME-WAIT状态的socket,用于新的TCP连接(这个对于快速重启动某些服务,而启动后提示端口已经被使用的情形非常有帮助)

(5) net.ipv4.tcp_tw_recycle: 决定是否对 TIME_WAIT 接口快速回收,默认值是0,打开快速 TIME-WAIT sockets 回收。除非得到技术专家的建议或要求﹐请不要随意修改这个值。(做NAT的时候,建议打开它)


3. TCP中半连接和全连接

在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是:

---半连接队列,也称 SYN 队列;

---全连接队列,也称 accept 队列;

1)正常流程如下:

a. 当服务端接收到客户端的 SYN 报文时,会将其加入到内核的「 SYN 队列」;

b. 接着发送 SYN + ACK 给客户端,等待客户端回应 ACK 报文;

c. 服务端接收到 ACK 报文后,从「 SYN 队列」移除放入到「 Accept 队列」;

d. 应用通过调用 accpet socket 接口,从「 Accept 队列」取出连接。


2) 相关的设置参数:

(1)net.ipv4. tcp_abort_on_overflow

(或cat
/proc/sys/net/ipv4/tcp_abort_on_overflow)

tcp_abort_on_overflow 共有两个值分别是 0 和 1,其分别表示:

0 :如果全连接队列满了,那么 server 扔掉 client 发过来的 ack ;

1 :如果全连接队列满了,server 发送一个 reset 包给 client,表示废掉这个握手过程和这个连接;

(2)net.ipv4.tcp_syn_retries:

作为发送syn来连接server的client端,要控制syn的重试次数,由net.ipv4.tcp_syn_retries 控制,或者
/proc/sys/net/ipv4/tcp_syn_retries。

默认值:5,建议值:2。如果SYN报文重传次数达到该值且规定等待时间已结束,连接将直接关闭。

(3) net.ipv4.tcp_max_syn_backlog

server收到client端的syn请求后,会返回syn+ack,状态为 SYN_RECEIVED,在整个 SYN_RECEIVED 状态下,server所能接收的最大连接的数量由这个字段来控制.

(4)net.ipv4.tcp_synack_retries:

server收到client端的syn请求后,会返回syn+ack,返回syn+ack 信息后,如果没有收到ack,会尝试再次发送syn+ack,尝试次数由
net.ipv4.tcp_synack_retries 控制。此值不应该大于255,默认值是5,对应于180秒左右 时间。如果SYN+ACK报文重传次数达到该值且规定等待时间已结束,连接将直接关闭;

(5) net.ipv4.tcp_syncookies:

只有在内核编译时选择了CONFIG_SYNCOOKIES时才会发生作用。当出现syn等候队列出现溢出时向对方发送syncookies。目的是为了防止syn flood攻击。syncookies 参数主要有以下三个值: 0 值,表示关闭该功能; 1 值,表示仅当 SYN 半连接队列放不下时,再启用它; 2 值,表示无条件开启功能

(6) net.core.somaxconn

参数定义了系统中每个端口的最大监听队列长度。增加此值可以提高高并发连接的处理能力;

三次握手即完成,产生了一个全连接,它会被添加到accept queue中。Server就可以调用accept来完成TCP连接的建立。但是就如syn queue一样,accept queue的长度也是有限的,全连接的长度是由,listen(socket,backlog)中的backlog控制的,该backlog的最大值是由somaxconn控制的。

net.core.somaxconn = 65535


4. TCP窗口大小、MSS和MTU的区别?

1)解释如下:

---MTU:Maximum Transmission Unit. MTU是指在数据传输过程中,数据链路层所能传输的最大数据单元的大小。如果发送的数据包超过了这个大小,就需要将数据包分割成多个较小的数据包进行传输。?

---MSS:Maxitum Segment Size. MSS是TCP报文段中数据部分的最大长度。

TCP提交给IP层最大分段大小,不包含TCP Header和 TCP Option,只包含TCP Payload ,MSS是TCP用来限制application层最大的发送字节数,是tcp能发送的分组的最大长度。 如果上层交付下来的数据超过MSS就要对交付下来的数据进行分段。在TCP连接的第一次、第二次握手中会分别告知对方MSS,从而起到通信双方协商MSS的效果。

---Window Size: TCP窗口大小。TCP报文段首部中,“窗口大小”字段通常用于告知对方自己的能够接受的数据量大小。窗口本质就是一个缓冲区buffer,该字段的值用于告知对方自己剩余的可用缓冲区大小。在每一个TCP报文段中都会通过“窗口”字段告知对方自己的所能接收数据的大小。窗口大小通常用滑动窗口流量控制。

2)举例说明:

如果底层物理接口MTU= 1500 byte,则 MSS = 1500- 20(IP Header) -20 (TCP Header) = 1460 byte,假设应用层有2000 byte发送,需要两个segment才可以完成发送,第一个TCP segment = 1460,第二个TCP segment = 540。

TCP Window Size: 如果A发送给B window size = 8192,意思是:B最多可以连续发送8192 byte 给A, 一般来说,8192byte就是A的接收缓区,A_Receive_Buffer= 8192,如果B不小心发送超过8192 byte,并且A的应用层没有及时取走,则超过8192 byte 数据可能会因为A_Receive_Buffer满而被丢弃,所以B会严格遵守A的 advertised window size;另外,如果A通告的window size= 0,则B一定不会发送数据。

Window Size 占两个byte,最大值为65535,这个字段会对对方发送速率影响比较大。如果window size 是高速网络带宽的瓶颈,可以通过设置net.ipv4. tcp_window_scaling这个参数来调整window size大小。


5. 几种常见的重传机制;超时重传/快速重传/SACK/D-SACK

当网络不稳定的时候,很容易出现数据包丢失,常见的重传方式有以下几种:

超时重传 、快速重传、SACK、D-SACK。

1) 超时重传

超时重传,顾名思义,就是在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的 ACK 确认应答报文,就会重发数据。

TCP 会在以下两种情况发生超时重传:

a · 发送的数据包丢失

b· 确认应答丢失

其中比较关键的就是超时重传时间如何来设定的问题。

其中 RTT 指的是数据从网络一端传送到另一端所需的时间,也就是数据包发送出去的往返时间。超时重传时间,我们以 RTO (Retransmission Timeout 超时重传时间)来表示。

超时重发时间既不能设置过大,也不能设置过小,需要精准的计算。

a· 当超时重发时间 RTO 设置较大时,会出现数据传输效率差的现象,比如数据包丢失之后,需要等很长时间才重发,性能差;

b· 当超时重发时间 RTO 设置较小时,可能会出现并没有丢失包就重发,多次重发会造成网络拥堵,导致出现更多的超时,更多的超时意味着更多的重发;

TCP为了保证无论在任何环境下都能比较高性能的通信, 因此会动态计算建立连接后的数据通信重传最大超时时间。Linux中(BSD Unix和Windows也是如此), 超时以500ms为一个单位进行控制, 每次判定超时重发的超时时间都是500ms的整数倍.

a. 如果重发一次之后, 仍然得不到应答, 等待 2*500ms 后再进行重传.

b. 如果仍然得不到应答, 等待 4*500ms 进行重传. 依次类推, 以指数形式递增.

c. 累计到一定的重传次数, TCP认为网络或者对端主机出现异常, 强制关闭连接.

2) 快速重传

快速重传就是来补充超时重传机制中时间过长的问题。简单的说,快速重传不像超时重传那样通过时间来驱动重发,而是通过次数来驱动重发。

当收到报文重复的 ACK 数量,到达一定的阀值(一般为3),TCP 会在定时器过期之前,检查丢失的报文段并重传丢失的报文段。

在上图,发送方向接受方发出了 1、2、3、4、5 份数据,大致执行的过程如下:

· 第一份 Seq1 先送到了,主机B方就 Ack 回序号 2,表示 seq 1 已经收到,准备接受下一个序列号为 2 的包;

· Seq2 因为某些原因没收到,Seq3 到达了,因为 Seq2 缺失,还是回Ack序号为 2;

· 后面的 Seq4 和 Seq5 都到了,因为 Seq2 没有收到,还是回Ack序号为 2;

· 发送端连续收到了3个 Ack = 2 的确认,知道了 Seq2 还没有收到,就会在定时器过期之前,重传丢失的 Seq2;

· 最后接收方收到了 Seq2,此时因为 Seq3,Seq4,Seq5 都收到了,于是 Ack 回 6 。

因此,快速重传的工作方式是当收到相同的 ACK 报文数量到达一个阀值,默认是 3,会在定时器过期之前,重传丢失的报文段。

快速重传机制弥补了超时重传机制中时间过长的问题,但是它依然面临着另外一个问题,那就是重传的时候,是重传之前的一个还是重传所有的包?例如上面的例子,是重传 Seq2 呢?还是重传 Seq2、Seq3、Seq4、Seq5 呢?根据 TCP 不同的实现,以上两种情况都有可能。

3) SACK 方法

标准的TCP确认机制中,如果发送方发送了0-800序号之间的数据,接收方收到了0-100、300-800,那么接收方只能向发送方确认101,这时发送方会重传所有101-800之间的数据,实际上这是不必要的,因为有可能仅仅是丢了一小段而已,但是在标准的TCP确认机制中,发送方无法感知这一事情,只能重传从101开始的所有数据。

为了优化这种情况,必须让发送方知道更多的接收信息,所以发展出了SACK选项,关于SACK的标准见RFC 2018。英文全称:Selective Acknowledgment,也被称为选择性确认。

SACK实现的需要发送方和接收方协作。为此,TCP首部实际上定义了两种选项:SACK允许选项 + SACK选项。

a. SACK允许选项

SACK特性是TCP的一个可选特性,是否启用需要收发双发进行协商,通信双发在SYN段或SYN+ACK段中添加SACK允许选项通知对端本端是否支持SACK,如果双发都支持,那么后续连接态通信过程中就可以使用SACK选项了。所以SACK允许选项只能出现在SYN段中。SACK允许选项格式如下图:

b. SACK选项

连接建立后,如果出现开头所述的情况,接收方就可以通过SACK选项告诉发送方字节的实际接收情况。SACK选项格式如下:

由于整个TCP首部的选项部分不能超过40字节,所以一个ACK段中最多可以容纳4组SACK信息。

Left Edge表示已收到的不连续块的第一个序号,Right Edge表示已收到的不连续块的最后一个序号+1,即左闭右开区间。通过ACK和SACK信息,发送方就可以确定接收方具体没有收到的数据就是从ACK到最大SACK信息之间的那些空洞的序号。

需要主要的是,如果要支持 SACK 机制,必须发送方和接受方都要支持。在 Linux 操作系统中,开发者可以通过net.ipv4.tcp_sack参数打开这个功能(Linux 2.4 后默认打开)。

4) Duplicate SACK 方法

为了更好的反应网络情况,RFC 2883在SACK选项的基础上提出了D-SACK(即Duplicate SACK)。接收方收到的乱序报文中同样有可能是会出现重复段,在SACK选项的第一个块中携带该重复段的序号,该序号可能是已经确认过的(小于ACK序号),或者大于其后面其它SACK的序号,发送方可以根据第一个块更加精细的判断网络状况:如数据段被复制、错误重传等。

过程分析:

· 主机A向主机B成功的发送了两个数据包,但是主机B发给主机A两个 ACK 确认应答都丢失了,主机A检查超时后,重传第一个数据包(100 ~ 199)

· 主机B发现数据是重复收到的,于是回了一个ACK 300和 SACK 100~299,告诉主机A 100~299的数据早已被接收了,因为 ACK 都到300了,因此这个 SACK 可以称为D-SACK。

· 当主机A知道数据没有丢,是主机B的 ACK 确认报文丢了,就不会继续重发数据包了

使用D-SACK方法的好处,可以让发送方知道,是发出去的包丢了还是接收方回应的 ACK 包丢了,然后来决定是否需要继续重发包。在 Linux 操作系统下,可以通过net.ipv4.tcp_dsack参数来开启/关闭这个功能(Linux 2.4 后默认打开)。


6. TCP滑动窗口的理解

1)概述:

a. 为解决TCP通信时每一个包都必须要数据接收方返回对应的ACK这个效率低下的问题,TCP 引入了滑动窗口这个概念。即使在往返时间较长的情况下,它也不会降低网络通信的效率。那么有了窗口,就可以指定窗口大小,窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值

b. 窗口的实现实际上是操作系统开辟的一个缓存空间,发送方主机在等到确认应答返回之前,必须在缓冲区中保留已发送的数据。

c. 如果按期收到确认应答,此时数据就可以从缓存区清除。假设窗口大小为 3 个 TCP 段,那么发送方就可以「连续发送」 3 个 TCP 段,并且中途若有 ACK 丢失,可以通过「下一个确认应答进行确认」

图中的 ACK 600 确认应答报文丢失,也没关系,因为可以通过下一个确认应答进行确认,只要发送方收到了 ACK 700 确认应答,就意味着 700 之前的所有数据「接收方」都收到了。这个模式就叫累计确认或者累计应答。

2)原理:

TCP窗口机制是用来控制数据流量的一个关键机制,确保发送方和接收方在数据传输过程中不会因为缓冲区溢出或网络拥堵而丢失数据。TCP窗口机制包括两个主要部分:滑动窗口和窗口大小。

TCP刚发明的时候,全世界的网络带宽都很小,所以最大的接受窗口被定义成65535字节,随着硬件的革命性进步,65535已经成为性能瓶颈,而TCP头只给接收窗口值留了16bit,解决方案就是在三次握手时是,把自己的Window Scale告知对方。Window Scale放在TCP头之外的Options中,向对方声明一个Shilt count,把它作为2的指数,再剩以TCP头中定义的接收窗口,就得到真正的TCP接收窗口了。

窗口缩放在RFC 1072中引入并在RFC 1323中进行了改进。实际上,窗口缩放只是将16位窗口字段扩展为32位长度。解决方案是定义TCP选项以指定计数,通过该计数,TCP标头字段应按位移位以产生更大的值。

3 ) 重要参数:

TCP 头里有一个字段叫 Window,也就是窗口大小。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。

a. Window size value:窗口的大小;(TCP头部)

b.Calculated Window size:放大后窗口的大小,也就是实际可用的大小

c. Window scale:窗口可以放大的倍数,也就是Calculated Window size最大等于Window size value 乘以 2 的 Window scale 次方(TCP options中)

如:Window size value如果等于1024,Window scale等于7,那么Calculated Window size最大可以等于1024*128=131072

4)窗口滑动:

a.发送方窗口滑动

发送方的发送数据如下图所示被分为四类:

(1).已经成功发送,并且收到确认

(2).已经发送成功尚未确认

(3).未发送,准备发送

(4).未发送,不允许发送

其中第二类数据和第三类数据处于TCP发送端的滑动窗口中,发送窗口只有收到发送窗口内字节的ACK确认,才会移动发送窗口的左边界; 发送方只能发送第三类数据,如果窗口很小,那么每一批发送的数据也就很少,如果ACK返回很慢,那么数据传输速度会非常慢;

b. 接收方窗口滑动

接收方的缓存数据分为三类:

(1). 已接收并已确认

(2). 未接受但准备好接收(接收窗口)

(3). 尚未接收并尚未准备好接收

接收方窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认。以此确保发送方会对这些数据重传。

5)窗口参数设置:

(1) net.ipv4. tcp_window_scaling: 启用或禁用TCP窗口缩放。默认值通常是1,表示启用。需要建立tcp连接的双方都开启才有效;

(2) net.core.rmem_max: 为所有类型的连接设置最大OS接收缓冲区大小

(3) net.core.wmem_max: 为所有类型的连接设置最大OS发数缓冲区大小

(4) net.ipv4.tcp_rmem : 三个值:

#可以为TCP套接字分配的最小接收缓冲区大小

#默认接收缓冲区大小

#可以为TCP套接字分配的最大接收缓冲区大小

(5) net.ipv4.tcp_wmem 三个值:

#单个TCP套接字分配的最小发送缓冲区大小

#单个TCP套接字默认发送缓冲区大小

#可以为TCP套接字分配的最大发送缓冲区大小

前两个参数会影响直接控制TCP窗口大小的应用的最大TCP窗口大小,方法是将应用的请求限制为不超过这些值; 后两个参数会影响linux自动调整运行的应用的TCP窗口大小。


7. TCP保活机制:

-----起源:

TCP协议中有长连接和短连接之分。 1)短连接环境下,数据交互完毕后,主动释放连接; 2)长连接环境下,进行一次数据交互后,很长一段时间内无数据交互时,客户端可能意外断电、死机、崩溃、重启,还是中间路由网络无故断开,这些TCP连接并未来得及正常释放,那么,连接的另一方并不知道对端的情况,所以服务器端要做到快速感知失败,减少无效链接操作,这就有了TCP的Keepalive(保活探测)机制,可以避免系统资源无效的消耗和浪费;

-----原理:

当一个 TCP 连接建立之后,启用 TCP Keepalive 的一端便会启动一个计时器,当这个计时器数值到达 0 之后(也就是经过tcp_keep-alive_time时间后),一个 TCP 探测包便会被发出。这个 TCP 探测包是一个纯 ACK 包(规范建议,不应该包含任何数据,但也可以包含1个无意义的字节,比如0x0。),其 Seq号 与上一个包是重复的,所以其实探测包报文不在窗口控制范围内。如果一个给定的连接在两小时内(默认时长)没有任何的动作,则服务器就向客户发一个探测报文段;

-----三个重要参数设置:

1)
net.ipv4.tcp_keepalive_time:
在TCP保活打开的情况下,最后一次数据交换到TCP发送第一个保活探测包的间隔,即允许的持续空闲时长,或者说每次正常发送心跳的周期,默认值为7200s(2h)。

2)
net.ipv4.tcp_keepalive_probes:
在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包次数,默认值为9(次)

3)
net.ipv4.tcp_keepalive_intvl :
在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包的发送频率,默认值为75s;


8. 什么是 SYN 攻击?如何避免TCP的SYN 攻击?

1)SYN Flood原理:

a. SYN攻击利用TCP的三次握手机制,攻击者通过大量伪造源IP地址和伪造的SYN请求,向目标服务器发送大量的TCP连接请求。由于被攻击端发出的响应报文将永远发送不到目的地,因此被攻击端在等待关闭这些连接的过程中会消耗大量资源。如果有成千上万的这种连接,主机的资源将被耗尽,从而无法正常响应合法用户的请求,达到拒绝服务的目的。

b. SYN攻击发生在TCP三次握手的第一个阶段。攻击者会发送大量的数据包,但并不向服务器发送“ACK”确认信息,被攻击端发出的响应报文永远发送不到目的地,这样TCP连接就处于挂起状态,即所谓的半连接状态。

2) 避免TCP的SYN 攻击措施:

(1) 监视SYN包

对于直接的Syn Flood攻击,一种简单的防范方法是监视SYN包。如果发现某个IP发送了大量的报文,直接将这个IP列入黑名单即可。然而,这种方法对于源地址不断变化的攻击则效果不佳。

(2) 延缓TCB分配

另一种方法是延缓TCB的分配。Syn Flood攻击消耗服务器资源的主要原因是系统一接收到SYN数据报文就立即分配TCB。因此,延缓TCB的分配可以有效地减轻服务器资源的消耗。

(3) 监视并释放无效连接

这种方法通过不断监视系统的半开连接和不活动连接,当达到一定阈值时拆除这些连接,从而释放系统资源。然而,这种方法可能会对所有连接一视同仁,可能会误释放正常连接请求,因此这种方法只适合应对少许简单的Syn Flood攻击。

(4) 使用SYN Cookie技术

SYN Cookie是一种用于防范SYN攻击的技术。当服务器收到SYN包时,不立即分配资源,而是根据源IP地址、端口和初始序号等信息生成一个加密的cookie并发送给客户端。当客户端发送ACK包时,服务器根据cookie解密还原出连接请求信息,并建立连接。这种方法可以有效防止服务器资源被大量半连接请求耗尽。

(5) 调整TCP/IP协议栈参数:

通过调整TCP/IP协议栈的参数,可以减少SYN攻击的影响。例如,可以减少SYN包的重试次数,限制同时处理的半连接数量,缩短SYN包超时时间等。

(6) 增加连接队列大小:服务器在处理连接请求时,会将请求放入一个队列中进行处理。增加连接队列大小可以增加服务器同时处理连接的能力,从而一定程度上减轻SYN攻击带来的负担。


9. Linux 内核TCP其它参数设置方法

1)TCP缓冲区的设置(与TCP窗口大小设置类似):

如下:

a. net.core.rmem_max: 最大的TCP数据接收缓冲(字节), 默认值:129024,建议值:873200;

b. net.core.wmem_max: 最大的TCP数据发送缓冲(字节), 默认值:129024,建议值:873200;

c. net.core.rmem_default: 默认的接收窗口大小(字节), 默认值:129024

d. net.core.wmem_default: 默认的发送窗口大小(字节),默认值:129024,

以上几条单位为字节,以下几点关于TCP单位为页(4K);:

e. net.ipv4.tcp_mem: [low-middle-high] 该内核参数也是包括三个值,用来定义内存管理的范围,page是 以页面为单位的,为系统中socket全局分配的内存容量。

---low: 是当page数低于该值时,无内存压力;

---middle:是进入内存的压力区域时所达到的页数;

---high: 表示内存吃紧,超过该值后,会丢弃后续报文。

f. net.ipv4.tcp_rmem: 接收缓存设置;

g. net.ipv4.tcp_wmem:发送缓存设置

每一项里面都有三个值,第一个值是缓冲区最小值,中间值是缓冲区的默认值,最后一个是缓冲区的最大值,虽然缓冲区的值不受core缓冲区的值的限制,但是缓冲区的最大值仍旧受限于core的最大值;

注:

1) net.core.wmem_max和net.core.wmem_default优先级高于net.ipv4.tcp_wmem,会覆盖其中的第2,3项值;

2) net.core.rmem_max和net.core.rmem_default优先级高于net.ipv4.tcp_rmem, 会覆盖其中的第2,3项值;

2)TCP其它内核参数:

(1) net.ipv4. tcp_app_win

---默认值:31,建议值:31;

---描述:保留max(window/2^tcp_app_win, mss)数量的字节数应用于TCP窗口缓冲。当为0时表示不需要缓冲。

(2) net.ipv4. tcp_adv_win_scale

---默认值:1,建议值:2;

---描述:这个变量用于告诉内核,对于TCP窗口大小,应该使用多少套接字缓冲区空间,以及要为应用程序缓冲区保存多少;

(3) net.ipv4. tcp_stdurg

---默认值:0,建议值:0

---描述:使用 TCP urg pointer 字段中的主机请求解释功能。大部份的主机都使用老旧的 BSD解释,因此如果您在 Linux 打开它,或会导致不能和它们正确沟通。

(4) net.ipv4. tcp_window_scaling

---默认值:1,-建议值:1;

---描述:该文件表示设置tcp/ip会话的滑动窗口大小是否可变。参数值为布尔值,为1时表示可变,为0时表示不可变。tcp/ip通常使用的窗口最大可达到65535字节,对于高速网络,该值可能太小,这时候如果启用了该功能,可以使tcp/ip滑动窗口大小增大数个数量级,从而提高数据传输的能力(RFC 1323)。

(5) net.ipv4. tcp_low_latency

---默认值:0,建议值:0;

---描述:允许 TCP/IP 栈适应在高吞吐量情况下低延时的情况;这个选项一般情形是的禁用。

(6) net.ipv4. ip_forward:

---默认值:0,建议值:1;

---描述:NAT必须开启IP转发支持,把该值写1

(7) net.ipv4.ip_local_port_range:

---默认: 32768---60999, 建议值:1024---65000

---描述:表示用于向外连接的端口范围,默认比较小,这个范围同样会间接用于NAT表规模。

3) 查看Linux系统的统计信息


/sys/class/net/eth0/statistics/rx_packets: 收到的数据包数量


/sys/class/net/eth0/statistics/tx_packets: 传输的数据包数量


/sys/class/net/eth0/statistics/rx_bytes: 接收的字节数


/sys/class/net/eth0/statistics/tx_bytes: 传输的字节数


/sys/class/net/eth0/statistics/rx_dropped: 收包时丢弃的数据包


/sys/class/net/eth0/statistics/tx_dropped: 发包时丢弃的数据包

4) 修改内核参数的方法:

(1).使用 echo value方式直接追加到文件中。 如 echo "1" >
/proc/sys/net/ipv4/tcp_syn_retries ,但是这种方式设备重启后,会恢复成默认值。

(2)把参数添加到 /etc/sysctl.conf 中,然后执行 sysctl -p 使参数生效。这种方式是永久有效的。

(3)使用systcl命令进行修改,例如修改SYN重传次数sysctl net.ipv4.tcp_syn_retries=n

使用 sysctl -w 命令配置为临时生效,写入 /etc/sysctl.conf 配置永久生效。

(4)/proc/sys/和/etc/sysctl.conf都支持在实例运行时修改内核参数,不同之处如下:

a. /proc/sys/是一个虚拟文件系统,提供了访问内核参数的方法,该目录下的net中存放了当前系统中已开启的所有网络内核参数, 可以在系统运行时进行修改,但重启实例后就会失效,一般用于临时性验证修改的效果。

b. /etc/sysctl.conf是一个配置文件,您可以通过修改/etc/sysctl.conf文件来修改内核参数的默认值,实例重启后不会失效.


(后续补充......)

Tags:

最近发表
标签列表