zoukankan      html  css  js  c++  java
  • 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队列条目。
  • 相关阅读:
    你是否听说过 HashMap 在多线程环境下操作可能会导致程序死循环?
    深入浅出分析 PriorityQueue
    深入浅出分析 ArrayDeque
    深入浅出的分析 Set集合
    深入浅出的分析 Properties
    深入浅出分析 HashMap
    深入浅出的分析 Hashtable
    深入浅出的分析 WeakHashMap
    深入浅出的分析IdentityHashMap
    python 执行js PyExecJS
  • 原文地址:https://www.cnblogs.com/rookieDanny/p/13261315.html
Copyright © 2011-2022 走看看