TCP: SYN ACK FIN RST PSH URG 详解
三次握手Three-way Handshake
一个虚拟链接的创建是经过三次握手来实现的
1. (B) --> [SYN] --> (A)
假如服务器A和客户机B通信. 当A要和B通讯时,B首先向A发一个SYN (Synchronize) 标记的包,告诉A请求创建链接.
注意: 一个 SYN包就是仅SYN标记设为1的TCP包(参见TCP包头Resources). 认识到这点很重要,只有当A受到B发来的SYN包,才可创建链接,除此以外别无他法。所以,若是你的防火墙丢弃全部的发往外网接口的SYN包,那么你将不能让外部任何主机主动创建链接。
2. (B) <-- [SYN/ACK] <--(A)
接着,A收到后会发一个对SYN包的确认包(SYN/ACK)回去,表示对第一个SYN包的确认,并继续握手操做.
注意: SYN/ACK包是仅SYN 和 ACK 标记为1的包.
3. (B) --> [ACK] --> (A)
B收到SYN/ACK 包,B发一个确认包(ACK),通知A链接已创建。至此,三次握手完成,一个TCP链接完成
Note: ACK包就是仅ACK 标记设为1的TCP包. 须要注意的是当三此握手完成、链接创建之后,TCP链接的每一个包都会设置ACK位
这就是为什么链接跟踪很重要的缘由了. 没有链接跟踪,防火墙将没法判断收到的ACK包是否属于一个已经创建的链接.通常的包过滤(Ipchains)收到ACK包时,会让它经过(这绝对不是个好主意). 而当状态型防火墙收到此种包时,它会先在链接表中查找是否属于哪一个已建链接,不然丢弃该包
四次握手Four-way Handshake
四次握手用来关闭已创建的TCP链接
1. (B) --> ACK/FIN --> (A)
2. (B) <-- ACK <-- (A)
3. (B) <-- ACK/FIN <-- (A)
4. (B) --> ACK --> (A)
注意: 因为TCP链接是双向链接, 所以关闭链接须要在两个方向上作。ACK/FIN 包(ACK 和FIN 标记设为1)一般被认为是FIN(终结)包.然而, 因为链接尚未关闭, FIN包老是打上ACK标记. 没有ACK标记而仅有FIN标记的包不是合法的包,而且一般被认为是恶意的
链接复位Resetting a connection
四次握手不是关闭TCP链接的惟一方法. 有时,若是主机须要尽快关闭链接(或链接超时,端口或主机不可达),RST (Reset)包将被发送. 注意在,因为RST包不是TCP链接中的必须部分, 能够只发送RST包(即不带ACK标记). 但在正常的TCP链接中RST包能够带ACK确认标记
请注意RST包是能够不要收到方确认的?
无效的TCP标记Invalid TCP Flags
到目前为止,你已经看到了 SYN, ACK, FIN, 和RST 标记. 另外,还有PSH (Push) 和URG (Urgent)标记.
最多见的非法组合是SYN/FIN 包. 注意:因为 SYN包是用来初始化链接的, 它不可能和 FIN和RST标记一块儿出现. 这也是一个恶意***.
因为如今大多数防火墙已知 SYN/FIN 包, 别的一些组合,例如SYN/FIN/PSH, SYN/FIN/RST, SYN/FIN/RST/PSH。很明显,当网络中出现这种包时,很你的网络确定受到***了。
别的已知的非法包有FIN (无ACK标记)和"NULL"包。如同早先讨论的,因为ACK/FIN包的出现是为了关闭一个TCP链接,那么正常的FIN包老是带有 ACK 标记。"NULL"包就是没有任何TCP标记的包(URG,ACK,PSH,RST,SYN,FIN都为0)。
到目前为止,正常的网络活动下,TCP协议栈不可能产生带有上面提到的任何一种标记组合的TCP包。当你发现这些不正常的包时,确定有人对你的网络不怀好意。
UDP (用户数据包协议User Datagram Protocol)
TCP是面向链接的,而UDP是非链接的协议。UDP没有对接受进行确认的标记和确认机制。对丢包的处理是在应用层来完成的。(or accidental arrival).
此处须要重点注意的事情是:在正常状况下,当UDP包到达一个关闭的端口时,会返回一个UDP复位包。因为UDP是非面向链接的, 所以没有任何确认信息来确认包是否正确到达目的地。所以若是你的防火墙丢弃UDP包,它会开放全部的UDP端口(?)。
因为Internet上正常状况下一些包将被丢弃,甚至某些发往已关闭端口(非防火墙的)的UDP包将不会到达目的,它们将返回一个复位UDP包。
由于这个缘由,UDP端口扫描老是不精确、不可靠的。
ICMP (网间控制消息协议Internet Control Message Protocol)
如同名字同样, ICMP用来在主机/路由器之间传递控制信息的协议。 ICMP包能够包含诊断信息(ping, traceroute - 注意目前unix系统中的traceroute用UDP包而不是ICMP),错误信息(网络/主机/端口 不可达 network/host/port unreachable), 信息(时间戳timestamp, 地址掩码address mask request, etc.),或控制信息 (source quench, redirect, etc.) 。
尽管ICMP一般是无害的,仍是有些类型的ICMP信息须要丢弃。
Redirect (5), Alternate Host Address (6), Router Advertisement (9) 能用来转发通信。
Echo (8), Timestamp (13) and Address Mask Request (17) 能用来分别判断主机是否起来,本地时间 和地址掩码。注意它们是和返回的信息类别有关的。它们本身自己是不能被利用的,但它们泄露出的信息对***者是有用的。
ICMP消息有时也被用来做为DOS***的一部分(例如:洪水ping flood ping,死 ping ?呵呵,有趣 ping of death)?/p>
包碎片注意A Note About Packet Fragmentation
若是一个包的大小超过了TCP的最大段长度MSS (Maximum Segment Size) 或MTU (Maximum Transmission Unit),可以把此包发往目的的惟一方法是把此包分片。因为包分片是正常的,它能够被利用来作恶意的***。
由于分片的包的第一个分片包含一个包头,若没有包分片的重组功能,包过滤器不可能检测附加的包分片。典型的***Typical attacks involve in overlapping the packet data in which packet header is 典型的***Typical attacks involve in overlapping the packet data in which packet header isnormal until is it overwritten with different destination IP (or port) thereby bypassing firewall rules。包分片能做为 DOS ***的一部分,它能够crash older IP stacks 或涨死CPU链接能力。
Netfilter/Iptables中的链接跟踪代码能自动作分片重组。它仍有弱点,可能受到饱和链接***,能够把CPU资源耗光。
握手阶段:
序号 方向 seq ack
1 A->B 10000 0
2 B->A 20000 10000+1=10001
3 A->B 10001 20000+1=20001
解释:
1:A向B发起链接请求,以一个随机数初始化A的seq,这里假设为10000,此时ACK=0
2:B收到A的链接请求后,也以一个随机数初始化B的seq,这里假设为20000,意思是:你的请求我已收到,我这方的数据流就从这个数开始。B的ACK是A的seq加1,即10000+1=10001
3:A收到B的回复后,它的seq是它的上个请求的seq加1,即10000+1=10001,意思也是:你的回复我收到了,我这方的数据流就从这个数开始。A此时的ACK是B的seq加1,即20000+1=20001
数据传输阶段:
序号 方向 seq ack size
23 A->B 40000 70000 1514
24 B->A 70000 40000+1514-54=41460 54
25 A->B 41460 70000+54-54=70000 1514
26 B->A 70000 41460+1514-54=42920 54
解释:
23:B接收到A发来的seq=40000,ack=70000,size=1514的数据包
24:因而B向A也发一个数据包,告诉B,你的上个包我收到了。B的seq就以它收到的数据包的ACK填充,ACK是它收到的数据包的SEQ加上数据包的大小(不包括以太网协议头,IP头,TCP头),以证明B发过来的数据全收到了。
25:A在收到B发过来的ack为41460的数据包时,一看到41460,正好是它的上个数据包的seq加上包的大小,就明白,上次发送的数据包已安全到达。因而它再发一个数据包给B。这个正在发送的数据包的seq也以它收到的数据包的ACK填充,ACK就以它收到的数据包的seq(70000)加上包的size(54)填充,即ack=70000+54-54(全是头长,没数据项)。
其实在握手和结束时确认号应该是对方序列号加1,传输数据时则是对方序列号加上对方携带应用层数据的长度.若是从以太网包返回来计算所加的长度,就嫌走弯路了. 另外,若是对方没有数据过来,则本身的确认号不变,序列号为上次的序列号加上本次应用层数据发送长度.