第13章:TCP连接管理:TCP连接的建立与终止;TCP option;PMTU;TCP状态转换;RST位;TCP服务器选项;与TCP连接管理相关的攻击;TSO和GRO
TCP连接的建立与终止
一个TCP连接的4元组:源目IP+源目port
一个TCP连接的3个阶段:启动、数据传输、退出
TCP半关闭;半开连接(半打开);半连接;TCP同时打开与关闭; ------------------------------------------------------------------------------------------ TCP半关闭:仅关闭数据流的一个方向 close():全关闭,不再输出,也不能接收输入---通常一个关闭操作是由应用程序提出关闭连接的请求而引发的,例如系统调用close() P424-425 shutdown():半关闭-----当应用程序已经完成了数据的发送工作,并发送了一个FIN给对方,但仍然希望接收来自对方的数据,直接它发送一个FIN给我。伯克利套接字的API提供了半关闭操作,shutdown() 当半关闭输出时:对应TCP四次挥手的 FIN_WAIT_2状态 https://blog.csdn.net/qq_41754573/article/details/103440516 close 函数具体是如何关闭两个方向的数据流呢? 在输入方向,系统内核会将该套接字设置为不可读,任何读操作都会返回异常。 在输出方向,系统内核尝试将发送缓冲区的数据发送给对端,并最后向对端发送一个 FIN 报文,接下来如果再对该套接字进行写操作会返回异常。 如果对端没有检测到套接字已关闭,还继续发送报文,就会收到一个 RST 报文,告诉对端:“Hi, 我已经关闭了,别再给我发数据了。” 我们会发现,close 函数并不能帮助我们关闭连接的一个方向, shutdown 函数才可以。 使用 SHUT_RDWR 来调用 shutdown 不是和 close差别: close 会关闭连接,并释放所有连接对应的资源,而 shutdown 并不会释放掉套接字和所有的资源。 close 存在引用计数的概念,并不一定导致该套接字不可用;shutdown 则不管引用计数,直接使得该套接字不可用,如果有别的进程企图使用该套接字,将会受到影响。 close 的引用计数导致不一定会发出 FIN 结束报文,而 shutdown 则总是会发出 FIN 结束报文,这在我们打算关闭连接通知对端的时候,是非常重要的。 ------------------------------------------------------------------------------------------ 半开连接(半打开): 如果一方异常关闭(断网,断电),而另一方并不知情。处于半打开的状态,如果双方不进行数据通信,是无法发现问题的。可以引入心跳机制,以检测半打开状态,检测到了发送RST重新建立连接 ------------------------------------------------------------------------------------------ 半连接: 三次握手中,主动发起握手的一方不发最后一次ACK,使得服务器端阻塞在SYN_RECV状态 半连接攻击(SYN攻击):会耗尽服务器资源,使得真正的请求无法建立连接。 ------------------------------------------------------------------------------------------ TCP同时打开与关闭:P426 极端情况,不考虑
初始序列号ISN 序列号共占用32bit,RFC0793中,序列号可以被视为一个32位的计数器,每4微妙+1;(我的计算:32bit最大值4294967294,ISN一个循环需要约4.77小时) 但是在其他算法中,ISN使用算法来随机生成的。
TCP option
TCP option:NOP、MSS最大段大小、SACK和SACK-Permitted、WSopt窗口缩放因子、TSopt时间戳选项和PAWS防回绕序列号算法、UTO用户超时选项、TCP-AO TCP认证选项 ====================================================================================================== NOP:用于填充,因为TCP报头是以4字节为单位的,TCP报头长度取值范围20-60字节,且必须是4的整数倍 ------------------------------------------------------------------------------------------ MSS最大段大小 允许从对方接受到的最大报文段,即通信方发送数据时,一个报文中数据段的最大长度(字节)(MSS是不计算TCP报头和IP报头的,只计算数据) 在3次握手时,双方会进行MSS的通告,这不是协商值,而是一个限定值; MSS默认536字节,但是我观察的连接中,都是会进行MSS协商的; ipv4协商的MSS基本为1460字节,这是一个典型值,因为IP MTU = 1500字节,IP报头最小20字节,TCP报头最小20字节 ipv6协商的MSS典型值为1440字节,ipv6最小40字节 ------------------------------------------------------------------------------------------ SACK和SACK-Permitted 因为接收方可以通过ack告诉发送方目前已接收的有效的连续数据,但不能对乱序的数据进行有效的处理,进而造成了不必要的重传 例如发送方共要发送1/2/3/4/5号报文,若2包报文丢失,3/4/5正常到达,通过重复ack,发送方会对数据2进行重传,同时也会对3/4/5进行重传。(从上帝视角来看,3/4/5的重传是没有必要的,SACK就是为了解决这个问题) SACK-Permitted在3次握手阶段,协商是否支持SACK 协商允许SACK的双方,只能接受到乱序的数据时,ack报文才会携带SACK选项 ------------------------------------------------------------------------------------------ WSopt窗口缩放因子 因为tcp头部的window字段占用2字节,表示接收方的可用缓存窗口大小,2个字节所能表示的最大值为65535,即window字段所能表示的最大可用缓存窗口为64KB;而这64KB随着硬件的发展,显然是不够用的。 所以出现了WSopt,能够将window字节从16位扩展到30位。 具体实现:window字段无变化,根据WSopt将window字段值有效地左移,窗口数值扩大至原先的2的s次方倍(s为WSopt比例因子),所以tcp最大的缓存窗口为65535*2的14次方,数据差不多为1GB ------------------------------------------------------------------------------------------ TSopt时间戳选项和PAWS防回绕序列号算法 TSopt时间戳选项要求发送方在每一个报文段添加2个4字节的时间戳数值 [root@centos7 ~]# cat /proc/sys/net/ipv4/tcp_timestamps #1表示在tcp会话中使用timestamp 时间戳选项在tcp options中,类型8 TSopt time stamp option 需要两端的设备都支持,时间戳选项才会开启;若开启的tcp会话,传输数据的tcp报文也会携带时间戳选项 但是实际上在windows系统上抓到的包,都是没有时间戳选项的。。。那么又是使用什么样的方式来计算RTT/RTO呢? wireshark中在tcp数据报头里的时间戳看起来实际上是wireshark添加的效果而已,将会话的第一个报文作为0,以此来计算后续的报文 序列号回绕是TCP不能回避的问题:因为TCP报文序列号的增加意味着TCP发送方已发送数据量的增加(不准确,但是意思对了),tcp序列号占用32bit,也意味着一个tcp序列号的循环代表了2的32次方的数据量,相当于4GB;带宽越大的网络,序列号回绕的时间间隔可能越短,10Gb的接口发送4GB的数据量仅需要3.2秒。。。 PAWS防回绕序列号算法:根据上面的描述,当一个tcp连接发送的数据量超过4GB时,就会出现TCP序列号回绕;TSopt是单调递增的。 算法实现:PAWS则是根据TSopt的数值来进行判断,当出现序列号符合预期,但是时间戳却过时的报文,则判断为过时报文,将报文丢弃。 ------------------------------------------------------------------------------------------ UTO用户超时选项 这是一个相对较新的功能,指明了TCP发送者愿意等待ack的时间。 TCP-AO TCP认证选项
PMTU
路径MTU(PMTU)发现控制与IP报头DF位;PMTU实验 ------------------------------------------------------------------------------------------ 路径MTU(PMTU)发现控制与IP报头DF位 路径MTU发现是用来确定到达目的地的路径中最大传输单元(MTU)的大小。通过在IP报头中设置不分片DF(Don't Fragment)标志来探测路径中的MTU值, 如果路径中设备的MTU值小于此报文长度,并且发现DF标志,就会发回一个Internet控制消息协议(ICMP)(类型3、代码4需要分片的消息ICMP_FRAG_NEEDED),消息中包含它可接受的MTU值。 原理总结:在发送的数据包中,IP报头的DF位置位,表示不允许分片;当数据包大小大于中间设备的mtu时,中间设备会回复icmp 3类型,告知数据包过大 ------------------------------------------------------------------------------------------ PMTU实验 ip link set eth0 mtu 3000 ping -n -c 2 -s 2500 -M do www.baidu.com ping [选项与参数] IP 选项与参数: -c 数值:后面接的是执行 ping 的次数,例如 -c 5 ; -n :在输出数据时不进行 IP 与主机名的反查,直接使用 IP 输出(速度较快); -s 数值:发送出去的 ICMP 封包大小,预设为 56bytes,不过你可以放大此一数值; -t 数值:TTL 的数值,预设是 255,每经过一个节点就会少一; -W 数值:等待响应对方主机的秒数。 -M [do|dont] :主要在侦测网络的 MTU 数值大小,两个常见的项目是: do :代表传送一个 DF (Don't Fragment) 旗标,让封包不能重新拆包与打包; dont:代表不要传送 DF 旗标,表示封包可以在其他主机上拆包与打包
TCP状态转换
TIME_WAIT状态(2MSL等待状态);静默时间;FIN_WAIT_2状态 =========================================================================================== TIME_WAIT状态,也称为2MSL等待状态,在该状态下,TCP会等待2倍于最大段生存期MSL的时间。 RFC0793规定MSL为2分钟,2MSL为4分钟;但是实现中,该数据是可以修改的,常见的有30秒、1分钟、2分钟;例如linux系统,2MSL时间为1分钟 [root@centos7 ~]# cat /proc/sys/net/ipv4/tcp_fin_timeout #60,centos7的默认配置为60秒 客户端需要等待2MSL时间才完全结束TCP连接,原因有两个: 1、为了保证客户端发送的最后一个确认包能正确到达服务端。因为如果由于网络原因丢失的话,服务端会重新发送连接释放数据包,在等待过程中,如果真的发生这种情况就可以得到处理。 客户端每接收到一次服务端发送来的接释放数据包都会重新设置时间等待计时器,然后等待2MSL时间才完全结束TCP连接。 2、等待才2MSL时间完全结束TCP连接,可以避免再次开启TCP连接的时候收到上一次TCP连接存在网络中的数据包,显然这样的数据包不是属于本次连接的,是无效的数据包。 ------------------------------------------------------------------------------------------ 静默时间:假设主机建立了一条tcp连接,突然崩溃了,重启后,又建立了一条tcp连接,恰巧和上一个tcp连接使用了相同的ip和port。为了避免本次连接接收到上一次tcp连接的报文,RFC0793规定,主机在崩溃or重启后,创建新的TCP连接需要等待一个MSL时间,即静默时间。 但是在实现中,并没有遵循RFC规定,因为重启的时间本身已经超过了一个MSL时间。 ------------------------------------------------------------------------------------------ FIN_WAIT_2状态 在TCP半关闭的情况下,发出FIN报文的一端会处于FIN_WAIT_2状态,若对端一直不发FIN报文,则本端理论上是可以无限处于FIN_WAIT_2状态的。同时实际上对端若一直没有发送数据,那么无限处于FIN_WAIT_2状态是不合理的。 为了避免这种情况的发生,应用程序主动关闭的一方执行的是close()【完全关闭操作】,而不是shutdown()。 处于FIN_WAIT_2状态下,若一直没有接收到对方的数据,那么计时器超时,则转入CLOSE状态 net.ipv4.tcp_fin_timeout可以用来设置该计时器,默认为60s
TCP RST位 重置报文段
TCP RST位 重置报文段 一般来说,当发现一个到达的报文对于相关连接而言是不正确的,TCP就会发送一个重置报文段。 一般有以下场景: 1.针对不存在的端口的连接请求 假设主机B不存在监听port 8888的进程,主机A向主机B的8888 port发起连接请求 2.终止一条连接 特点:1.任何排队的数据都会被丢弃,重置报文被立即发送;2.RST报文的接收方会说明通信另一端采用了终止的方式,而不是一次正常关闭(不理解,可能会体现在应用程序吧,P448) 3.半开连接(这其实就是情况1的一种特殊场景吧。。) 某一方系统崩溃,导致另一端设备处于半开连接状态。处于半开连接状态的设备并不清楚对端已经发生了问题。半开连接设备正常发送报文,对端设备因为找不到连接信息,直接回复rst报文 4.时间等待错误 当系统处于time_wait状态下,只需要等待2msl时间,系统就会正常关闭;若系统处于time_wait状态收到了之前迷路的tcp报文,该系统仍然会回复ack报文,但是因为对端设备已经关闭了连接,当收到ack报文时,直接回复rst报文,这会是本端的time_wait状态提前结束,切换到closed状态 实际实现中,许多系统规定了处于time_wait状态时,不对rst报文做出反应,从而避免了上面的问题。
TCP服务器选项
TCP服务器选项 如果系统支持IPv4和IPv6双栈,那么在使用netstat命令进行查看时,端口号可能会出现混乱的情况。 如果服务器使用IPv6绑定了一个端口,那么这个端口也应用于IPv4;即IPv6监听某端口,那么IPv4也会监听这个端口。 [root@centos7 ~]# netstat -natp |grep "ESTABLISHED\|Proto" Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1154/sshd tcp 0 0 172.17.22.136:22 42.120.72.112:8916 ESTABLISHED 682/sshd: root@pts/ tcp 0 0 172.17.22.136:22 42.120.72.112:8948 ESTABLISHED 685/sshd: root@nott tcp 0 0 172.17.22.136:22 42.120.72.112:23455 ESTABLISHED 31036/sshd: root@no tcp 0 0 172.17.22.136:42884 100.100.30.25:80 ESTABLISHED 14308/AliYunDun tcp 0 0 172.17.22.136:22 42.120.72.112:23432 ESTABLISHED 31034/sshd: root@pt Recv-Q Send-Q是收发数据量,但是实测多次'netstat -natp |grep "ESTABLISHED\|Proto"',一直是0???? LISTEN状态 0.0.0.0:22 #表示不限制本地IP 10.0.0.1:22 #表示限制本地IP为10.0.0.1 对于建立一个TCP连接,TCP服务端对于该连接可能处于两种状态:SYS_RCVD、ESTABLISHED,操作系统通常会使用2个不同的连接队列处理这2种不同的情况 net.ipv4.tcp_max_syn_backlog限制SYS_RCVD状态的队列长度,默认为1000;即当SYS_RCVD状态的队列长度等于1000时,服务器会拒绝新连接 net.core.somaxconn限制"处于ESTABLISHED状态,但未被应用程序接受"的tcp连接,默认值为128
与TCP连接管理相关的攻击
P458
===============================================================================================================================
《网络排查案例课》08 | 分段:MTU引发的血案
案例:重传失败导致应用压测报错 根因:MTU问题导致server端回复的大包无法被传递到client端,原因系中间链路存在一段隧道 分析过程: 1.根据两组抓包数据分析,发现了过LB时,连接是client主动发起RST的 2.观察存在异常的TCP流,发现server侧进行了2次的数据包重传;client侧则有重复ACK,且ACK number为1 3.根据步骤2的client 重复ACK和server的数据包重传,可以判断server端的数据包没有被client接收 4.对比正常的数据流,发现回复POST请求的首包的大小不一样,异常会话的TCP包的TCP semgent len为1388;而正常的为1348 5.为什么会话中只存在了2次重传,会话就被RST了;重传数据包的间隔差不多为200ms和400ms,确实是指数退让; 6.观察到client侧的主动FIN报文和post请求相差1S,可以判断为client侧应用层设置了1S的超时规则 这种“整数值”,一般是跟某种特定的(有意的)配置有关,而不是偶然。 一般对策 ip link set enp0s3 mtu 1400 “暗箱操作” iptables。在中间环节(比如某个软件路由或者软件网关)上,在 iptabes 的 FORWARD 链这个位置,我们可以添加规则,修改报文的 MSS 值。 即通过iptables直接修改TCP3次握手时协商的MSS iptables -A FORWARD -p tcp --tcp-flags SYN SYN -j TCPMSS --set-mss 1400
TSO(TCP Segmentation Offload)和GRO(Generic Receive Offload);IP 分片对比TCP 分段(linux发出的IP报文默认都设置了DF位) ==================================================================================================================================== TSO(TCP Segmentation Offload)和GRO(Generic Receive Offload) 前面说的都是操作系统会做 TCP 分段的情况。但是,这个工作其实还是有一些 CPU 的开销的,毕竟需要把应用层消息切分为多个分段,然后给它们组装 TCP 头部等。 而为了提高性能,网卡厂商们提供了一个特性,就是让这个分段的工作从内核下沉到网卡上来完成,这个特性就是 TCP Segmentation Offload。(offload不能翻译为卸载,而应该是off + load) TSO 启用后,发送出去的报文可能会超过 MSS。同样的,在接收报文的方向,我们也可以启用 GRO(Generic Receive Offload)。 比如wireshark查看TCP 载荷有 2800 字节,这并不是说这些报文真的是以 2800 字节这个尺寸从网络上传输过来的,而是由于接收端启用了 GRO,由接收端的网卡负责把几个小报文“拼接”成了 2800 字节。 在 Wireshark 里看到这种超过 1460 字节的 TCP 段长度,不要觉得奇怪了,这只是因为你启用了 TSO(发送方向),或者是 GRO(接收方向),而不是 TCP 报文真的就有这么大! $ sudo ethtool -K enp0s3 tso off #启用或者关闭 TSO/GRO $ sudo ethtool -k enp0s3 | grep offload tcp-segmentation-offload: off $ ethtool -k enp0s3 | grep offload #确认你的网卡是否启用了这些特性 tcp-segmentation-offload: on generic-segmentation-offload: on generic-receive-offload: on large-receive-offload: off [fixed] rx-vlan-offload: on tx-vlan-offload: on [fixed] l2-fwd-offload: off [fixed] hw-tc-offload: off [fixed] esp-hw-offload: off [fixed] esp-tx-csum-hw-offload: off [fixed] rx-udp_tunnel-port-offload: off [fixed] tls-hw-tx-offload: off [fixed] tls-hw-rx-offload: off [fixed] --------------------------------------------------------------------------------------------------------------------------------------- IP 分片和 TCP 分段是两个在不同层面的分包机制,互不影响。 在 TCP 这一层,分段的对象是应用层发给 TCP 的消息体(message)。 比如应用给 TCP 协议栈发送了 3000 字节的消息,那么 TCP 发现这个消息超过了 MSS(常见值为 1460),就必须要进行分段,比如可能分成 1460,1460,80 这三个 TCP 段。 在 IP 这一层,分片的对象是 IP 包的载荷,它可以是 TCP 报文,也可以是 UDP 报文,还可以是 IP 层自己的报文比如 ICMP。 假设一个“奇葩”的场景,也就是 MSS 为 1460 字节,而 MTU 却只有 1000 字节 1460 字节的 TCP 分段由这台主机完成,1000 字节的 IP 分片由路径中某台 MTU 为 1000 的网络设备完成。 隐含的条件,就是主机发出的 1500 字节的报文,不能设置 DF(Don’t Fragment)位,否则它既超过了 1000 这个路径最小 MTU,又不允许分片,那么网络设备只能把它丢弃。 网络设备会把它切分为一个 1000(也就是 960+20+20)字节的报文和一个 520(也就是 500+20)字节的报文。1000 字节的 IP 报文的 MF 位(More Fragment)会设置为 1,表示后续还有更多分片,而 520 字节的 IP 报文的 MF 字段为 0。 在现实场景里,IP 分片是需要尽量避免的,原因有很多, 主要是因为互联网是一个松散的架构,这就导致路径中的各个环节未必会完全遵照所有的约定。 比如你发出了大于 PMTU 的报文,寄希望于 MTU 较小的那个网络环节为你做分片,但事实上它可能不做分片,而是直接丢弃,比如下面两种情况: 1.它考虑到开销等问题,未必做分片,所以直接丢弃。 2.如果你的报文有 DF 标志位,那么也是直接丢弃。 即使它帮你做了分片,但因为开销比较大,增加的时延对性能也是一个不利因素。 ***另外一个原因是,分片后,TCP 报文头部只在第一个 IP 分片中,后续分片不带 TCP 头部,那么防火墙就不知道后面这几个报文用的传输层协议是什么,可能判断为有害报文而丢弃。*** 为了避免这些麻烦,我们还是不要开启 IP 分片功能。事实上,Linux 默认的配置就是,发出的 IP 报文都设置了 DF 位 --------------------------------------------------------------------------------------------------------------------------------------- 小结: 在案例分析的过程中,我们解读了 Wireshark 里的信息,特别是两次 DupAck 和两次重传,推导出了问题的根因。这里,你需要了解 200ms 超时重传这个知识点 借助 Wireshark 的 Flow graph,我们可以更加清晰地看到两端报文的流动过程,这对我们推导问题提供了便利。 如果能稳定重现成功和失败这两种不同场景,那就对我们排查工作提供了极大的便利。我们通过对比成功和失败两种场景下的不同的抓包文件,能比较快地定位到问题根因。 如果排查中遇到有“整数值”出现,可以重点查一下,一般这跟人为的设置有关系,也有可能就是根因,或者与根因有关。 如果你对网络中间环节(包括 LB、网关、防火墙等)有权限,又不想改动两端机器的 MTU,那么可以选择在中间环节实施“暗箱操作”,也就是用 iptables 规则改动双方的 MSS,从而间接地达到“双方不发送超过 MTU 的报文”的目的。 我们也学习了如何用 ethtool 工具查看 offload 相关特性,包括 TSO、LRO、GRO 等等。同样通过 ethtool,我们还可以对这些特性进行启用或者禁用,这为我们的排查和调优工作提供了更大的余地。
===============================================================================================================================
《网络排查案例课》14 | 安全:用Wireshark把DDoS攻击照出原形
这一课其实主要讲UDP相关的DDoS攻击。。。
NTP 反射放大攻击;NTP 反射攻击案例 ================================================================================================== NTP 反射放大攻击 DDoS 攻击的一种类型,叫 NTP 反射放大攻击 NTP 全称是 Network Time Protocol,它的作用是通过网络服务来同步时间。其中有一项功能叫 Monlist,它在一些比较老的设备上是默认启用的,会返回与 NTP 服务器进行过时间同步的最后 600 个客户端的 IP。 UDP 的一个概念:UDP 报文的载荷最好不要大于 512 字节。 这个限制来自于 IPv4 协议。在 IPv4 的协议规范RFC791里建议,虽然 IP 报文的长度字段是 2 个字节,最大可以到 65535,但是由于网络不允许传输这么大的报文,所以 IPv4 规范建议,报文长度应该控制在相对小的范围内,这个范围是 576 字节,相应的 UDP 载荷在 512 字节以内: 它利用 IP 协议“不对源 IP 做验证”的不足,构造一个 IP 报文,其源 IP 为被攻击站点的 IP,使得 NTP 服务器回复的报文也被发往被攻击站点。 -------------------------------------------------------------------------------- NTP 反射攻击案例 如果我们面临这种攻击,该怎么办呢? 假如这些被利用的 NTP 服务器是我们的,那么需要升级版本,避免自己成为“帮凶”。 如果我们是单纯的被攻击者,那就需要上一些手段了,我会在这次课程的后半段讲到。这次的游戏客户,就是上了高防后,扛住了这次攻击。
SSDP 反射放大攻击;SSDP 反射型攻击案例 ================================================================================================== SSDP 反射放大攻击 借协议的“响应是请求的很多倍”这个力。显然,前面介绍的 NTP 反射攻击就是这样的。所以这种攻击,英文里叫 reflection attack with amplification。amplication 就是放大的意思。在这种模式下,只需要量很少的“肉机”,就可以发起巨大的攻击流量。 SSDP 反射放大攻击 SSDP 是在 UDP 这个传输层协议上,用 HTTP 协议格式传送信息。 2014 年,人们发现 SSDP 可以被攻击者利用。启用了 SSDP 协议的主要是一些家用路由器,在它们的 UPnP 软件中有一个漏洞,这个漏洞被攻击者利用后,这些路由器会从端口 1900 返回响应报文。 反射放大攻击的特点,它主要利用了以下三点: 1.IP 协议不对源 IP 进行校验,所以可以伪造源 IP,把它设定为被攻击站点的 IP,这样就可以把响应流量引向被攻击站点。 2.UDP 协议是无连接的,可以直接进行应用层的一问一答,这就使得 IP 欺骗可以奏效。 3.某些服务具有“响应报文的大小是请求报文的很多倍”的特点,使攻击行为达到了“四两拨千斤”的攻击效果。 -------------------------------------------------------------------------------------------------- SSDP 反射型攻击案例 当时的应对方法也是上了高防系统,顶住了这次攻击。
DDoS;反射型攻击基于UDP的原因 =================================================================================================== DDoS 跟 DOS 有着密切的联系。DOS(Denial of Service),就是服务拒绝,黑客通过各种手段,使得被攻击者无法正常提供服务。 DOS 这种攻击早已经存在了,而 DDoS(Distributed DOS)就是它的升级版,通过调动分布在各地的客户端发起攻击,使得被攻击站点无法正常服务。 DDoS 属于“攻击”,但不是“入侵”。两者的区别是,攻击是破坏服务,入侵可能不破坏,但会窃取资料、劫持勒索等等。 既然 DDoS 要破坏服务,那就需要破坏计算资源。 一般说的计算机资源还是 CPU、内存这些。旨在耗尽 CPU 和内存资源,这也是早期的攻击形式,也跟很多年前软件病毒肆虐的时候类似。 随着安全加固技术和意识的不断增强,攻破系统的成本越来越高,于是攻击者转换了方向。 其实他们不需要想办法攻入对端,只要在前面的网络环节上搞破坏,同样可以达到让对方服务瘫痪的目的。这时,服务瘫痪的原因已经不是之前的服务本身不可用,而是变成:网络通道不可用了! DDoS 的核心目标:耗尽网络带宽 如何产生巨大的流量呢? 一种常见的实现方式就是反射型攻击。它的核心方法论是:利用一些协议的“响应是请求的很多倍”这样的特点,同时也利用“IP 协议不验证源 IP”的不足,达到把流量引到被攻击站点上去的目的。 UDP 载荷最好不要超过 512 字节,这也是 IPv4 协议规范的建议,像 NTP 和 DNS 这些基于 UDP 的协议都实现了这个规范。 --------------------------------------------------------------------------------------------------------- TCP 当然也可能被 DDoS 所用,但是相对来说,如果用同样的成本,选择反射型攻击更加高效。而反射型攻击,主要基于 UDP,主要有两个原因: 1. UDP 报文头部如此简单,这就减少了攻击者做伪造的难度,只要做好这几件事就好了: 伪造一个源 IP; 找到 NTP 等有反射攻击漏洞的服务器; 向这些服务器发送构造好的虚假的 UDP 报文。 2.UDP 是无状态的 UDP 是无状态的,不需要握手。像 NTP 反射攻击、SSDP 反射攻击,都是只要“一问一答”即可,所以攻击者只需要伪造一个请求报文,那么后续的响应报文,自然就发送给了被攻击站点了。 TCP 需要三次握手,如果攻击者的 SYN 报文的源地址是伪造成被攻击站点的 IP,那么 SYN+ACK 报文就直接回复到那个站点的 IP 了,而不是攻击者。 被攻击站点收到一个莫名其妙的 SYN+ACK,就会被 RST 掉。这次 TCP 握手就这么结束了,攻击就没法继续了。 所以如果要用TCP发起DDOS攻击,那么攻击者就需要掌握大量肉机 不对,如果是这个IP没有被使用的话,那么还是会卡在syn_recive状态 所以,用 TCP 的话就是直接攻击,而不是反射攻击了。比如 SYN 攻击、半连接攻击、全连接攻击、CC 攻击等等。从“性价比”上看,反射攻击的优势更大些。
应付DDOS的方案:高防、云堤、anycast 和多 POP、CDN --------------------------------------------------- DDoS 的本质是挤占网络带宽,那么对付它的核心策略就是: 用更大的带宽来接纳,先解决正常流量被挤出网络的问题。 在接纳后进行清洗,把正常流量识别出来,发回给源站,让业务继续进行。 高防 一般来说,如果你的服务架设在公有云上,那么可以考虑使用云商或者其他专业安全服务商的高防产品。 高防是需要放置在源站前面的一类安全防护和清洗系统。 它利用了自身的足够大的带宽,以及强大的防护清洗集群,实现对流量清洗,最终把攻击流量拦截在外面,清洗过后的正常流量进入源站,得以被正常处理。 由于高防按时计费而且费用高昂,一般平时是不接入高防的。只有探测到被攻击时,才自动或者手动转入高防。 其实就是借助GSLB,将域名临时修改为CNAME,转入高防;然后经过高防清洗,流量才到达真正的服务器 如果是直接针对IP发起的攻击,那么只需要修改IP,让攻击流量进入路由黑洞;同时不暴露新的IP,接入到高防 云堤 云堤本身属于运营商自己的系统,而无论被攻击站点还是肉机,都依托于运营商的公网线路才能进入因特网,所以云堤具有“地理”上的天然优势。 anycast 和多 POP 这是一些自身规模比较大的网站会部署的架构 anycast 是网络术语,是指多个地点宣告同一个网段或者同一个 IP 地址的行为。 一旦有 DDoS 攻击,因为它的目标 IP 是属于 anycast 网段的,所以会被因特网的路由策略,相对均匀地分布到这些 POP。 anycast 一般是作用在网段级别。而在单个 IP 级别的 anycast 应用还较局限,目前主要还是主要应用在基于 UDP 的服务,比如 DNS 服务上。 基于 anycast 的 HTTP 是比较前沿的领域,目前有少数公司已经开始实践,相信在不久的将来,应该会看到越来越多的公司应用 HTTP over anycast。 CDN 与"anycast 和多 POP"相似 CDN 也是通过“多点分布”来达到防护或者缓解 DDoS 攻击的目的。而且 CDN 服务商一般也会采用 anycast 等策略混合使用,使得其防护 DDoS 的能力更加出色。 ------------------------------------------------------------------ 应对 DDoS 攻击的策略,包括: 1.使用高防产品,可以防护非常巨大的攻击流量。 2.如果对防护效果有更高的需求,可以使用运营商的云堤类的产品。 3.如果自身条件足够,可以部署多 POP 和 anycast,平均吸收攻击流量。 4.也可以上 CDN,让 CDN 天然的分布式布局减轻 DDoS 的影响。