转自:http://www.blogjava.net/jasmine214--love/archive/2010/12/15/340680.html?opt=admin
TCP是一个面向连接的协议。在传输数据前必须要建立连接,在停止传输数据后要终止连接释放资源。
TCP连接是在IP网络中两个进程间(应用层协议)的双向、全双工的逻辑回路。由节点的IP地址和端口将连接双方对应起来。
1.TCP连接特点:
为了建立连接TCP连接双方必须从对方了解下面的信息:
通 过3个TCP段的交换来了解这些信息,就是常说的TCP 握手的3个包。一般在客户端访问TCP服务器的时候,在客户端初始化一个TCP连接,服务器端打开一个特殊端口等待传入的请求。客户端主动发起第一个 SYN置位的包开始协商TCP连接。服务器接收后向客户端回ACK,最后客户端在向服务器回复ACK后连接建立。
下面我们用TCP连接的两个对等端A和B来详细介绍握手过程,其中发起方是A。
两个应用程序同时执行主动建立TCP的连接的可能性是存在的,此时发送到SYN建立需要交换4个包,如图所示:
需要注意的是,即使同时打开仍然只建立一条连接。(但其他的协议不一定)
TcpMaxConnectRetransmissions
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~255
Default value:2
Present by default:No
设定当试图建立一个TCP连接时,会重传多少次SYN。每次间隔时间加倍。初始的RTO为3秒,并且默认值为2,这样第一次SYN等待3秒后重传第一次,在等待6秒后重传第二次,在等待12秒没有SYN+ACK就超时了。
TcpNumConnections
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~0xFFFFFF
Default value:0xFFFFFF
Present by default:No
设定能打开的TCP最大数。默认能打开16777214(0xFFFFFF)个连接。
TCP 半开连接是未完成的连接建立的进程的一个TCP连接,收到一个SYN包,并且一个SYN-ACK已经发送,但是最后的ACK没有收到。前面知道XP默认设 置情况下在发送2个重传SYN-ACK后等待12秒后放弃连接,并释放内存和连接的内部表项,从收到SYN到释放总共会花费21秒。
SYN-ACK重传输的一个半开连接
SYN攻击就是利用这种方法,使用伪装的IP地址和TCP端口,在短时间内制造大量的半开连接来耗尽资源,造成拒绝服务攻击。大量的半开连接能做如下事情:
1.使用所有可用的内存,
2.使用在TCP传输控制模块(TCB)中所有可能的项,这是一个用来跟踪TCP连接的内部表,一旦半开连接使用完所有的项,就用一个TCP连接复位来响应下一个连接企图。
3.使用所有可能的半开连接,此后用一个TCP连接复位响应下一个连接企图。
可以使用netstat -n -p tcp 查看TCP连接状态,包括半开连接。如果state出现大量的SYN-RECEIVED就该受到SYN攻击了。
Windows xp和2003 在检测和防护SYN攻击方面的注册表:
TcpMaxConnectResponseRetransmissions
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~255
Default value:2
Present by default:No
设定针对半开连接的一个AYN-ACK的重传数目,对于大于1的值使用SYN攻击防护机制。
SynAttackProtect
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~1
Default value:0
Present by default:No
设置为0禁用SYN攻击防护,1启用SYN攻击防护。被启用时,检测到SYN攻击,则半开连接的超时会更快些。
TcpMaxHalfOpen
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:100~65535
Default value:100 for windows xp 和Windows 2003 web版及标准版,500 for Windows 2003 企业版和数据中心版
Present by default:No
在SYN攻击防护起作用前,此键值设定了在SYN-RECEIVED状态中的TCP链接最大数。
TcpMaxHalfOpenRetried
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:80~65535
Default value:80 for windows xp 和Windows 2003 web版及标准版,400 for Windows 2003 企业版和数据中心版
Present by default:No
在SYN-RECEIVED状态中设定TCP连接的最大数并且在SYN攻击防护起作用前至少发送过一个重传。
在 建立TCP连接后,必须有一些机制维持TCP连接。如果TCP建立连接后不传输任何数据也没有应用级别的保活机制时,那么TCP连接一直存在,数天,数月 会一直存在。中间的路由器可能重启,崩溃,TCP连接的双方无从知道,许多时候一个服务器希望知道客户主机是否崩溃并关机或者崩溃又重新启动。许多实现提 供的保活定时器可以提供这种能力。但这个规范并不推荐,理由如下:
TCP保活定时器(keepalive)
Windows 中TCP通过一个TCP keepalive的周期性交换,能维持一个TCP连接。在keepalive的TCP头部序列号字段被设为比当前出站数据流的序列号小1的值。如果一个 TCP对等端的下一个数据的字节序列号是N,那么keepalive的序列号是N-1.
在接收到keepalive包后,对等端回送一个ACK字段,并将确认号置为下一个期望收到的字节N,这个交换证实了两个对等端仍然处于TCP连接状态中。
Windows 2003 和 XP的TCP/IP在默认情况下禁用TCP的keepalive.启用情况下每2个小时发送一次keepalive。如果其他上层协议的保活机制时间小于keepalive,tcp的keepalive将不会发送。
相关注册表
KeepAliveTime
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~0xFFFFFFFF
Default value:0x6DDD00 (2小时)
Present by default:No
如果连接上没有没有数据,并且启用keepalive,此键值在每一个TCP保持活跃包之间设置了毫秒数,默认是2小时。
KeepAliveInterval
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~0xFFFFFFFF
Default value:0x3E8 (1000毫秒)
Present by default:No
在没有接收到对初始的保持活跃的响应时,此键值设置了重传时间默认是1秒。重传数目受TcpMaxDataRetransmission键值控制,默认是5.此时的重传不会有指数级的回退行为。
如果都启用且是默认,无数据传输的TCP连接在keepalive包发出后2小时6秒收不到ACK就放弃连接。
举例:
另一端崩溃
keepalive机制在重复发送探测包到一定次数后报错,由TCP转换为“连接超时”
另一端崩溃而重启
客户端telnet到服务器后,我们拔掉服务器网线重启服务器,服务器重启好后我们在telnet客户端上输入命令。服务器重启后丢失了以前连接的所有信息,此时服务器收到来着telnet客户端的命令,不知道此连接的信息,于是TCP就以复位作为应答来结束TCP连接。
另外一端不可达
拔掉网线,模拟中间路由器崩溃,keepalive探测的时候会引起ICMP差错“不可达--没有到达主机的路由”反馈给主机。
TCP的连接终止需要4个包交换来完成。在两个逻辑管道上每个逻辑管道上发送方发送FIN置位的终止包,然后收到ACK后关闭该逻辑管道的连接。
TCP连接终止的4个TCP段交换过程
一个期望终止出站数据流的TCP对等端(A)发送一个不包含任何数据的TCP段,他具有如下特点:
与SYN类似,FIN包也会占用一个字节的序列空间,并且必须把它当作是一个字节数据来确认。所以B接收到FIN-ACK后必须发送一个ACK,具有如下特点:
一旦FIN-ACK被确认,发送初始FIN-ACK端A就不能再发送数据了,这仅终止了一个逻辑管道的连接,TCP对等端B发送数据到A的逻辑管道仍然开放,B仍然可以发数据给A。
前面对等端A向B发送数据的逻辑管道被关闭后,如果B向A发送数据的逻辑管道仍然有数据发送,且被对等端A确认,这就是TCP半关闭。TCP对等端B向A发送数据的逻辑管道没有数据发送后,也要B向A发送FIN-ACK来关闭。
特点:
同样段三的FIN-ACK包也按占用了一个字节算,并且必须作为一个字节的数据被确认。因此收到FIN-ACK的A必须发送一个ACK。
具有如下特点:
当来自A的ACK被B接收后,TCP连接上的B向A发送数据的逻辑管道就会被关闭,此时经过四次握手后,整个TCP连接才会被完整关闭。
但在有些实现中段二和段段三被合并。其过程就是FIN-ACK/FIN-ACK/ACK,此时中间的FIN-ACK中的ACK是对第一个FIN-ACK的确认。
双方都执行主动关闭也是可能的,TCP协议也允许这样的同时关闭(simultaneous close)。双方各发送一个FIN,两个FIN经过网络传送后分别到达另一端。收到FIN后,两端发送最后的ACK。当收到最后的A C K时,关闭TCP连接.
同时关闭的报文段交换
TCP连接终止进程适用于一个TCP连接的两个管道在互相同意的情况下正常关闭。另外一种终止TCP连接的方式是通过TCP连接复位—一个具有RST(Reset)标志的TCP段来完成。
当一个不可调和的入站TCP段的TCP头中存在参数问题时,一个TCP连接复位就会被发送。例如,不恰当的源IP地址、目的IP地址或者TCP端口号都能中断一个建立了的连接。中断的TCP连接将丢失所有的TCP数据,包括正在传送中或者在等待被发送的缓冲区中。
TCP也用来拒绝一个TCP连接企图,以响应对SYN段的接收。最常见的是,SYN段中目的端口与运行在SYN段接收者上的应用层进程相对应。当达到被允许的最大值时,连接企图就会被拒绝。下图显示了TCP连接复位
一个显示SYN和RST段的TCP连接的复位
注意:当UDP到达一个与应用层进程不对应的目的端口时,会产生一个ICMP,目的不可达-端口不可达的报错发送给UDP数据发送方。
抓包截图显示了在一台运行FTP客户端和一台非FTP服务器主机之间的包交换。帧一是一个到FTP控制端口的SYN段,帧二是连接复位。
在连接复位段中:
1.设置了RST和ACK标志
2.序列号为0
3.确认号比SYN段的序列号多1
4.窗口大小是0.
TCP连接状态和说明:
状态 | 说明 |
CLOSED | 不存在TCP连接 |
LISTEN | 一个应用层协议已经发布了一个被动打开,并且有意接收TCP连接企图 |
SYN SENT | 一个应用层协议已经发布一个主动打开,并且发送一个SYN段 |
SYN RCVD | 一个SYN段被接收,并且一个SYN-ACK被发送 |
ESTABLISHED | 建立TCP连接的3此握手完成。现在数据能双向传输 |
FIN WAIT-1 | 初始的关闭连接段的FIN-ACK被发送 |
FIN WAIT-2 | 响应初始的FIN-ACK的ACK被接收 |
CLOSING | 一个FIN-ACK被接收但ACK不是针对已发送的FIN-ACK的。收到的FIN-ACK中的是针对已发送的FINA-ACK被称为同时关闭,这时两个TCP对等端在相同时刻发送FIN-ACK。 |
TIME WAIT | FIN- ACK已被发送并得到两个对等端的确认,并且TCP连接终止进程完成。一旦到达TIME WAIT状态,在连接的TCP端口能被重新使用前,TCP必须等待的时间是最大生存时间(MSL)的两倍。MSL是在互联网中一个TCP段能存在时间的最 大值,推荐是240秒。这个延迟防止一个使用相同端口的连接的TCP段与旧连接的TCP段的副本相混淆 |
CLOSE WAIT | 一个FIN-ACK被接收,并且一个FIN-ACK被发送 |
LAST ACK | 响应FIN-ACK的ACK已被接收 |
TCP状态变迁图
一个TCP对等端经过的连接状态依赖于TCP对等端是TCP连接建立的初始化方还是TCP连接终止的初始化方。
TCP连接图和终止图