TCP/UDP协议安全

端口

首先要理解端口(port)的概念。端口是一种抽象的软件结构,包括一些数据结构和I/O缓冲。
进程通过系统调用与端口建立连接(binding),之后传输层传给该端口的数据都被相应进程所接收,而相应进程发给传输层的数据也通过该端口。端口操作类似于一般的I/O操作,进程获取一个端口,相当于获取本地唯一的I/O文件,所以可以用一般的读写系统调用来操作。

类似于文件描述符,每个端口都拥有整数型标识符端口号,用于区分不同端口。由于TCP/IP传输层的TCP和UDP是完全独立的两个软件模块,因此各自的端口号也相互独立,两者都有多达65536个端口。

在所有的65536个端口中,数值为0~1023的端口也称为熟知端口,IANA把这些端口号指派给了TCP/IP最重要的一些应用进程。当一种新的应用程序出现后,IANA必须为它指派一个熟知端口号。常见的熟知端口包括20、21、22、23、53、80、443等。

TCP和UDP

特点

位于网络层
TCP特点:
使用三次握手建立连接,拥有确认、窗口、重传、拥塞控制等机制,传输完成后会断开连接节约资源
缺点:
速度慢、效率低、占用系统资源高、易被攻击
UDP特点:
快 但不可靠

结构


TCP

UDP

TCP的校验和计算和IP头部的校验和计算方法是一致的,但是覆盖的数据范围不一样。TCP校验和覆盖TCP首部和TCP数据,而IP首部中的校验和只覆盖IP的头部。TCP的校验和是必需的,而UDP的校验和是可选的。TCP和UDP计算校验和时,都要加上一个12字节的伪首部。

伪首部包含:源IP地址、目的IP地址、保留字节(置0)、传输层协议号(TCP是6)、TCP报文长度(报头+数据)。伪首部是为了增加TCP校验和的检错能力:如检查TCP的源和目的IP地址、传输层协议等。
【协议栈的处理数据报流程肯定是要先经过IP层的处理过滤掉不属于自己的IP数据报后才接着往上层处理的,为何到了上层(TCP、UDP)还需要校验数据报是否属于自己呢?主要是因为Internet中的数据报会在传输过程中经过多跳(hop)才会到达最终的目的地址,在中间的任何一跳都可能会存在软件/硬件的错误,导致本来应该到达X的数据报到达了Y(修改了数据报中的dst address和IP层的checksum),这样的数据报可以顺利的逃过IP层的校验到达上层TCP/UDP。这个时候pseudo header就发挥它的作用了,通过计算数据报的校验码就能发现这是一个错误的数据报。

不过另一方面,既然能修改IP层的数据那么同样可以修改TCP/UDP层的数据,如果把TCP/UDP中的校验码checksum重新计算修改成“正确“的值,这个数据报就可以逃过IP层、TCP层的校验了。pseudo header主要是为了修正中间网络设备的错误路由,因为中间路由设备一般都只会操作IP层不会操作TCP/UDP层,所以也就不会错误的修改TCP/UDP的checksum了。(即使错误路由,IP层的checksum应该也不会恰好对,所以....)】

在RFC 793中规定了TCP头部校验和的计算:

把伪首部、TCP报头、TCP数据分为16位的计算单位,如果总长度为奇数个字节,则在最后增添一个全为0的字节。计算式首先把TCP报头中的校验和字段置为0。然后使用反码相加法累加所有的16位字(进位也要累加)。最后,对计算结果取反,作为TCP的校验和。

攻击

TCP SYN Flooding

SYN flooding之前也讨论过,发生这种攻击的原因是因为TCP三次握手过程中的一个设计。当应用开放了一个TCP端口后,该端口就处于侦听状态,不停地监视发到该端口的Syn报文,一旦接收到Syn报文,就需要为即将建立的TCP连接分配TCB(Transmission Control Block),通常一个TCB至少需要280个字节,在某些操作系统中TCB甚至达到1300个字节;并且进入半开连接(half-opening)状态,也即收到SYN包而还未收到ACK包时的连接状态。操作系统实现的最多可开启的半开连接个数是一定的,譬如512,而受到内存的限制,可能还达不到这个数字。如果半开连接的个数过多,就会消耗掉可用的内存,使得新的正常的连接请求不能被处理。


防范:
系统中默认的tcp_syncookies的值是1,如果不做这个改动,syn_flood攻击没有效果。
syn cookie是现在防范TCP Syn Flood的业界标准做法之一,由Daniel J. Bernstein和Eric Schenk于 1996 年九月提出。Eric Schenk随后在 1997 年二月发布了Linux实现。

SYN Cache
因为我们常说的四元组主要是源IP、源端口、目的IP和目的端口,那么可以在接收到SYN包时,仅仅分配有限的空间,来维持其后可能需要的信息,而不是分配整个的TCP控制块。这种思路叫做SYNCache,每次来了SYN包,那么就在SYNCache队列中生成一个项,保持一些基本信息;然后在收到ACK时检查SYNCache队列,如果能找到合适的项,那么开始建立TCP连接,然后删除SYNcache中的项。使用TCPCache可以抵御DoS主要是通过保持有限的信息,节约资源;然后通过限制SynCache的大小。

SYN Cookie
SYN Cookie的原理即针对在ACK还未到达之前就需要分配大量资源的问题而提出的解决方案。思路是在ACK到达之前不分配任何资源。直观上来看,这样的问题是什么?如果不为SYN包分配任何资源,那么在收到ACK包的时候,怎么知道它前面发送了SYN包呢?特别是,如果实现的不好,那么防火墙上关于SYN所设置的过滤条件就可能失效。所以,SYN Cookie的关键在于如何在不分配资源的同时,能够识别是否是一个完整的TCP三次握手。

SYN Cookie的工作过程如下:在接收到客户端的TCP SYN数据包时,服务器构造TCP SYN + ACK数据包发送回客户端。根据TCP规范,端点发送的第一个序列号可以是由该端点决定的任何值。在该数据包中的序列号的值不再是随机值,或者是其他方法生成的值,而是,SYN cookie根据以下规则精心构建的初始序列号:

设t是一个缓慢递增的时间戳(通常是time()逻辑上右移6个位置,这给出了64秒的分辨率)令m为服务器可能在SYN队列条目中存储的最大段大小(MSS)值设s是通过服务器IP地址和端口号、客户端IP地址和端口号以及值t计算的加密哈希函数的结果。返回值s必须是24位值。

初始TCP序列号,即SYN cookie,计算如下:

前5位:t mod 32中3位:表示m的编码值最后24位:s

(注意:由于m必须使用3位进行编码,因此当使用SYN cookie时,服务器仅限于使用最多8个值;这时可以使用Mss Indicator,使用8个索引值来代表具体的值。)

当客户端响应服务器的SYN + ACK数据包向服务器发回TCP ACK数据包时,客户端必须(根据TCP规范)在数据包的确认号中使用n + 1,其中n是由服务器发送的初始序列号。然后,服务器从确认号中减去1,得到发送给客户端的SYN cookie。

然后,服务器执行以下操作。

检查值t与当前时间,以查看连接是否已过期。重新计算s以确定它是否确实是一个有效的SYN cookie。从SYN cookie中的3位编码解码值m,然后可以使用它来重建SYN队列条目。

tcp_syncookies 参数主要有以下三个值,可以在 /proc/sys/net/ipv4/tcp_syncookies 修改该值。

0 值,表示关闭该功能;
1 值,表示仅当 SYN 半连接队列放不下时,再启用它;
2 值,表示无条件开启功能;


SYN cookie的使用不会破坏任何TCP协议规范,因此应该与所有TCP实现兼容。但是,有两个问题。首先,服务器仅限于8个唯一的MSS值,因为它只能以3比特编码。其次,服务器必须拒绝所有TCP选项(例如大窗口或时间戳),因为服务器会丢弃SYN条目,而其他情况下会存储该信息。

虽然这些限制必然导致一些不好的体验,但客户很少注意到它们的影响,因为仅在受到攻击(队列溢出)时才应用SYN Cookie。在这种情况下,为了保护连接而丢失TCP选项通常被认为是一种合理的妥协。

另外一个方面是,当客户端发送的连接ACK数据包丢失,并且应用层协议要求服务器首先发包时(如SMTP和SSH),会出现问题。在这种情况下,客户端假定连接已成功建立,并等待服务器发送其协议标志,或重新发送SYN + ACK数据包;但是,服务器因为没有收到ACK包,将会认为是SYN Flooding攻击包,并且不会重新发送SYN + ACK。最终,客户端将因应用程序层超时而中止连接,但这可能需要相当长的时间。即使不要求服务器首先发包,那么客户发出的数据包也会被回复以RST而中断连接。

SYN Cookies 缺点

既然SYN Cookies可以减小资源分配环节,那为什么没有被纳入TCP标准呢?原因是SYN Cookies也是有代价的:

MSS的编码只有3位,因此最多只能使用 8 种MSS值
服务器必须拒绝客户端SYN报文中的其他只在SYN和SYN+ACK中协商的选项,原因是服务器没有地方可以保存这些选项,比如Wscale和SACK
增加了密码学运算

防御SYNFlood措施

方式一:增大半连接队列

在前面源码和实验中,得知要想增大半连接队列,我们得知不能只单纯增大 tcp_max_syn_backlog 的值,还需一同增大 somaxconn 和 backlog,也就是增大全连接队列。否则,只单纯增大 tcp_max_syn_backlog 是无效的。
方式二:开启 tcp_syncookies 功能

方式三:减少 SYN+ACK 重传次数
当服务端受到 SYN 攻击时,就会有大量处于 SYN_REVC 状态的 TCP 连接,处于这个状态的 TCP 会重传 SYN+ACK ,当重传超过次数达到上限后,就会断开连接。

那么针对 SYN 攻击的场景,我们可以减少 SYN+ACK 的重传次数,以加快处于 SYN_REVC 状态的 TCP 连接断开。

针对SYNCookie攻击

http://www.91ri.org/7075.html

posted @ 2020-07-07 15:55  歇马  阅读(529)  评论(0编辑  收藏  举报