1,查看tcp状态工具服务器
工欲善其事必先利其器,先了解下查看tcp状态的工具cookie
1),netstat 网络
Netstat 命令用于显示各类网络相关信息,如网络链接,路由表,接口状态 (Interface Statistics),masquerade 链接,多播成员 (Multicast Memberships) 等等。并发
-a (all)显示全部选项,默认不显示LISTEN相关
-t (tcp)仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-n 拒绝显示别名,能显示数字的所有转化成数字。
-l 仅列出有在 Listen (监听) 的服務状态socket
-p 显示创建相关连接的程序名
-r 显示路由信息,路由表
-e 显示扩展信息,例如uid等
-s 按各个协议进行统计
-c 每隔一个固定时间,执行该netstat命令。tcp
2)、lsof -i:port 能够检测到打开套接字的情况函数
lsof(list open files)是一个列出当前系统打开文件的工具工具
3)、 sar -n SOCK 查看tcp建立的链接数 (System Activity Reporter)测试
4)、tcpdump -iany tcp port 9000 对tcp端口为9000的进行抓包ui
5)traceroute:raceroute 跟踪数据包到达网络主机所通过的路由工具
2 tcp状态
LISTENING:侦听来自远方的TCP端口的链接请求
Server端调用bind操做,将监听套接字与指定的地址和端口关联,而后又调用listen函数,系统会为其分配未完成队列和完成队列,此时的监听套接字能够接受Client的链接,监听套接字状态处于LISTEN状态。
SYN_SEND:客户端经过应用程序调用connect进行active open.因而客户端tcp发送一个SYN以请求创建一个链接.以后状态置为SYN_SENT
SYN_RCVD: 服务端收到SYN,将标志位SYN和ACK置1,发送给客户端, 此时为SYN_RCVD状态。
SYN Flood的攻击原理是:
在进行三次握手时,攻击软件向被攻击的服务器发送SYN链接请求(握手的第一步),可是这个地址是伪造的,如攻击软件随机伪造了51.133.163.10四、65.158.99.152等等地址。服务器在收到链接请求时将标志位ACK和SYN置1发送给客户端(握手的第二步),可是这些客户端的IP地址都是伪造的,服务器根本找不到客户机,也就是说握手的第三步不可能完成。
ESTABLISHED:表明一个打开的链接。
netstat -nat |grep 9502或者使用lsof -i:9502能够检测到。
当客户端未主动close的时候就断开链接:即客户端发送的FIN丢失或未发送。
这时候若客户端断开的时候发送了FIN包,则服务端将会处于CLOSE_WAIT状态;
这时候若客户端断开的时候未发送FIN包,则服务端处仍是显示ESTABLISHED状态;
结果客户端从新链接服务器。
而新链接上来的客户端(也就是刚才断掉的从新连上来了)在服务端确定是ESTABLISHED; 若是客户端重复的上演这种状况,那么服务端将会出现大量的假的ESTABLISHED链接和CLOSE_WAIT链接。
最终结果就是新的其余客户端没法链接上来,可是利用netstat仍是能看到一条链接已经创建,并显示ESTABLISHED,但始终没法进入程序代码。
关闭(四次挥手)
FIN_WAIT1:
主动关闭(active close)端应用程序调用close,因而其TCP发出FIN请求主动关闭链接,以后进入FIN_WAIT1状态./* The socket is closed, and the connection is shutting down. 等待远程TCP的链接中断请求,或先前的链接中断请求的确认 */
若是服务器出现shutdown再重启,使用netstat -nat查看,就会看到不少FIN-WAIT-1的状态。就是由于服务器当前有不少客户端链接,直接关闭服务器后,没法接收到客户端的ACK。
CLOSE-WAIT:等待从本地用户发来的链接中断请求
被动关闭(passive close)端TCP接到FIN后,就发出ACK以回应FIN请求(它的接收也做为文件结束符传递给上层应用程序),并进入CLOSE_WAIT. /* The remote end has shut down, waiting for the socket to close. 等待从本地用户发来的链接中断请求 */
FIN-WAIT-2:从远程TCP等待链接中断请求
主动关闭端接到ACK后,就进入了FIN-WAIT-2 ./* Connection is closed, and the socket is waiting for a shutdown from the remote end. 从远程TCP等待链接中断请求 */
这就是著名的半关闭的状态了,这是在关闭链接时,客户端和服务器两次握手以后的状态。在这个状态下,应用程序还有接受数据的能力,可是已经没法发送数据,可是也有一种多是,客户端一直处于FIN_WAIT_2状态,而服务器则一直处于WAIT_CLOSE状态,而直到应用层来决定关闭这个状态
LAST-ACK:等待原来的发向远程TCP的链接中断请求的确认
被动关闭端一段时间后,接收到文件结束符的应用程序将调用CLOSE关闭链接。这致使它的TCP也发送一个 FIN,等待对方的ACK.就进入了LAST-ACK . /* The remote end has shut down, and the socket is closed. Waiting for acknowledgement. 等待原来发向远程TCP的链接中断请求的确认 */
使用并发压力测试的时候,忽然断开压力测试客户端,服务器会看到不少LAST-ACK。
TIME-WAIT:等待足够的时间以确保远程TCP接收到链接中断请求的确认
在主动关闭端接收到FIN后,TCP就发送ACK包,并进入TIME-WAIT状态。/* The socket is waiting after close to handle packets still in the network.等待足够的时间以确保远程TCP接收到链接中断请求的确认 */
TIME_WAIT等待状态,这个状态又叫作2MSL状态,说的是在TIME_WAIT2发送了最后一个ACK数据报之后,要进入TIME_WAIT状态,这个状态是防止最后一次握手的数据报没有传送到对方那里而准备的(注意这不是四次握手,这是第四次握手的保险状态)。这个状态在很大程度上保证了双方均可以正常结束,可是,问题也来了。
因为插口的2MSL状态(插口是IP和端口对的意思,socket),使得应用程序在2MSL时间内是没法再次使用同一个插口的,对于客户程序还好一些,可是对于服务程序,例如httpd,它老是要使用同一个端口来进行服务,而在2MSL时间内,启动httpd就会出现错误(插口被使用)。为了不这个错误,服务器给出了一个平静时间的概念,这是说在2MSL时间内,虽然能够从新启动服务器,可是这个服务器仍是要平静的等待2MSL时间的过去才能进行下一次链接。
client/server两条路线讲述TCP状态迁移路线图:
1.为何创建链接协议是三次握手,而关闭链接倒是四次握手呢?
这是由于服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它能够把ACK和SYN(ACK起应答做用,而SYN起同步做用)放在一个报文里来发送。但关闭链接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你全部的数据都所有发送给对方了,因此你能够未必会立刻会关闭SOCKET,也即你可能还须要发送一些数据给对方以后,再发送FIN报文给对方来表示你赞成如今能够关闭链接了,因此它这里的ACK报文和FIN报文多数状况下都是分开发送的。
2.为何TIME_WAIT状态还须要等2MSL后才能返回到CLOSED状态?
这是由于虽然双方都赞成关闭链接了,并且握手的4个报文也都协调和发送完毕,按理能够直接回到CLOSED状态(就比如从SYN_SEND状态到ESTABLISH状态那样):
一方面是可靠的实现TCP全双工链接的终止,也就是当最后的ACK丢失后,被动关闭端会重发FIN,所以主动关闭端须要维持状态信息,以容许它从新发送最终的ACK。
另外一方面,可是由于咱们必需要假想网络是不可靠的,你没法保证你最后发送的ACK报文会必定被对方收到,所以对方处于LAST_ACK状态下的SOCKET可能会由于超时未收到ACK报文,而重发FIN报文,因此这个TIME_WAIT状态的做用就是用来重发可能丢失的ACK报文。
TCP在2MSL等待期间,定义这个链接(4元组)不能再使用,任何迟到的报文都会丢弃。设想若是没有2MSL的限制,刚好新到的链接正好知足原先的4元组,这时候链接就可能接收到网络上的延迟报文就可能干扰最新创建的链接。
三、发现系统存在大量TIME_WAIT状态的链接,能够经过调整内核参数解决:vi /etc/sysctl.conf 加入如下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
而后执行 /sbin/sysctl -p 让参数生效。
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少许SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。容许将TIME-WAIT sockets从新用于新的TCP链接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP链接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间
服务器端主动关闭:
1)当服务器的服务由于某种缘由,进程提早终止时会向客户 TCP 发送 FIN 分节,服务器端处于FIN_WAIT1状态。
2)客户TCP回应ACK后,服务TCP将转入FIN_WAIT2状态。
3)此时若是客户进程没有处理该 FIN (如阻塞在其它调用上而没有关闭 Socket 时),则客户TCP将处于CLOSE_WAIT状态。
4)当客户进程再次向 FIN_WAIT2 状态的服务 TCP 发送数据时,则服务 TCP 将马上响应 RST。
TIME_WAIT状态存在的理由:
1)可靠地实现TCP全双工链接的终止:(即在TIME_WAIT下等待2MSL,只是为了尽最大努力保证四次握手正常关闭)。
TCP协议规定,对于已经创建的链接,网络双方要进行四次握手才能成功断开链接,若是缺乏了其中某个步骤,将会使链接处于假死状态,链接自己占用的资源不会被释放。
在进行关闭链接四路握手协议时,最后的ACK是由主动关闭端发出的,若是这个最终的ACK丢失,服务器将重发最终的FIN,所以客户端必须维护状态信息容许它重发最终的ACK。若是不维持这个状态信息,那么客户端将响应RST分节,于是,要实现TCP全双工链接的正常终止,必须处理终止序列四个分节中任何一个分节的丢失状况,主动关闭的客户端必须维持状态信息进入TIME_WAIT状态。
咱们看客户端主动关闭服务器被动关闭四次握手的流程:
一、 客户端发送FIN报文段,进入FIN_WAIT_1状态。
二、 服务器端收到FIN报文段,发送ACK表示确认,进入CLOSE_WAIT状态。
三、 客户端收到FIN的确认报文段,进入FIN_WAIT_2状态。
四、 服务器端发送FIN报文端,进入LAST_ACK状态。
五、 客户端收到FIN报文端,发送FIN的ACK,同时进入TIME_WAIT状态,启动TIME_WAIT定时器,超时时间设为2MSL。
六、 服务器端收到FIN的ACK,进入CLOSED状态。
七、 客户端在2MSL时间内没收到对端的任何响应,TIME_WAIT超时,进入CLOSED状态。
若是不考虑报文延迟、丢失,确认延迟、丢失等状况,TIME_WAIT的确没有存在的必要。当网络在不理想的状况下一般会有报文的丢失延迟发生,让咱们看下面的一个特例:
客户端进入发送收到四次握手关闭的最后一个ACK后,进入TIME_WAIT同时发送ACK,若是其不停留2MSL时间,而是立刻关闭链接,销毁链接上的资源,当发送以下状况时,将不能正常的完成四次握手关闭:
客户端发送的ACK在网路上丢失,这样服务器端收不到最后的ACK,重传定时器超时,将重传FIN到客户端,因为客户端关于该链接的全部资源都释放,收到重传的FIN后,它没有关于这个FIN的任何信息,因此向服务器端发送一个RST报文端,服务器端收到RST后,认为搞链接出现了异常(而非正常关闭)。
因此,在TIME_WAIT状态下等待2MSL时间端,是为了可以正确处理第一个ACK(最长生存时间为MSL)丢失的状况下,可以收到对端重传的FIN(最长生存时间为MSL),而后重传ACK。
是否只要主动关闭方在TIME_WAIT状态下停留2MSL,四次握手关闭就必定正常完成呢?
答案是否认的?能够考虑以下的状况,
TIME_WAIT状态下发送的ACK丢失,LAST_ACK时刻设定的重传定时器超时,发送重传的FIN,很不幸,这个FIN也丢失,主动关闭方在TIME_WAIT状态等待2MSL没收到任何报文段,进入CLOSED状态,当此时被动关闭方并无收到最后的ACK。因此即便要主动关闭方在TIME_WAIT状态下停留2MSL,也不必定表示四次握手关闭就必定正常完成。
2)确保老的报文段在网络中消失,不会影响新创建的链接
考虑以下的状况,主动关闭方在TIME_WAIT状态下发送的ACK因为网络延迟的缘由没有按时到底(但并无超过MSL的时间),致使被动关闭方重传FIN,在FIN重传后,延迟的ACK到达,被动关闭方进入CLOSED状态,若是主动关闭方在TIME_WAIT状态下发送ACK后立刻进入CLOSED状态(也就是没有等待)2MSL时间,则上述的链接已不存在:
如今考虑下面的状况,假设客户端(192.186.0.1:23) 到服务器192.168.1.1:6380)的TCP链接, 因为链接已关闭,咱们能够立刻创建一个相同的IP地址和端口之间的TCP链接,而且这个链接也是客户端(192.186.0.1:23) 到服务器192.168.1.1:6380),那么当上一个链接的重传FIN到达主动关闭方时,被新的链接所接受,这将致使新的链接被复位,很显然,这不是咱们但愿看到的事情。
引用:https://blog.csdn.net/hguisu/article/details/38700899