Line # Revision Author
1 20 ahitrov@rambler.ru limit_ip.patch ��� apache_1.3.14
2
3 ��������� ��� ���������������� ���������:
4
5 MaxServersPerIP - ������������� ������������ ���������� ��������,
6 ������������� � ������ IP
7 MaxServersPerIPRead - ������������� ������������ ���������� ��������
8 � ������ IP, ������� ��������� � ��������� ������
9
10 ������������ �� ���� ������ ���������� ����
11 http_patch � http://www.shutoff.spb.ru/apache_patch.html
12 ��������� ������� ������ � ������������ �������� � apache_1.3.14
13
14 ����������� ���:
15 patch -d apache_1.3.14 -l -p1 < limit_ip.patch
16
17 diff -ur apache_1.3.9rusPL28.20/src/include/http_conf_globals.h apache_1.3.9rusPL28.20-patch/src/include/http_conf_globals.h
18 --- apache_1.3.9rusPL28.20/src/include/http_conf_globals.h Sat Aug 21 02:44:56 1999
19 +++ apache_1.3.9rusPL28.20-patch/src/include/http_conf_globals.h Tue Sep 21 17:34:52 1999
20 @@ -86,6 +86,8 @@
21 extern int ap_daemons_limit;
22 extern MODULE_VAR_EXPORT int ap_suexec_enabled;
23 extern int ap_listenbacklog;
24 +extern int ap_daemons_max_by_ip;
25 +extern int ap_daemons_max_by_ip_read;
26 extern int ap_dump_settings;
27 extern API_VAR_EXPORT int ap_extended_status;
28
29 diff -ur apache_1.3.9rusPL28.20/src/include/http_main.h apache_1.3.9rusPL28.20-patch/src/include/http_main.h
30 --- apache_1.3.9rusPL28.20/src/include/http_main.h Thu Jan 14 12:39:26 1999
31 +++ apache_1.3.9rusPL28.20-patch/src/include/http_main.h Tue Sep 21 17:34:53 1999
32 @@ -127,6 +127,9 @@
33 unsigned int ap_set_callback_and_alarm(void (*fn) (int), int x);
34 API_EXPORT(int) ap_check_alarm(void);
35
36 +void update_child_status_remote_ip (int, conn_rec *);
37 +int count_connections (conn_rec *, int);
38 +
39 #ifndef NO_OTHER_CHILD
40 /*
41 * register an other_child -- a child which the main loop keeps track of
42 diff -ur apache_1.3.9rusPL28.20/src/include/httpd.h apache_1.3.9rusPL28.20-patch/src/include/httpd.h
43 --- apache_1.3.9rusPL28.20/src/include/httpd.h Thu Sep 2 22:59:02 1999
44 +++ apache_1.3.9rusPL28.20-patch/src/include/httpd.h Tue Sep 21 17:34:53 1999
45 @@ -297,6 +297,12 @@
46 #define DEFAULT_MIN_FREE_DAEMON 5
47 #endif
48
49 +/* Define default limits for MaxDaemons serving a single address */
50 +
51 +#define DEFAULT_MAX_DAEMONS_BY_IP 150
52 +#define DEFAULT_MAX_DAEMONS_BY_IP_READ 75
53 +#define LIMIT_CONNECTIONS_BY_IP_ERROR HTTP_SERVICE_UNAVAILABLE
54 +
55 /* Limit on the total --- clients will be locked out if more servers than
56 * this are needed. It is intended solely to keep the server from crashing
57 * when things get out of hand.
58 diff -ur apache_1.3.9rusPL28.20/src/include/scoreboard.h apache_1.3.9rusPL28.20-patch/src/include/scoreboard.h
59 --- apache_1.3.9rusPL28.20/src/include/scoreboard.h Sat Aug 21 02:45:00 1999
60 +++ apache_1.3.9rusPL28.20-patch/src/include/scoreboard.h Tue Sep 21 17:34:53 1999
61 @@ -159,6 +159,7 @@
62 char request[64]; /* We just want an idea... */
63 server_rec *vhostrec; /* What virtual host is being accessed? */
64 /* SEE ABOVE FOR SAFE USAGE! */
65 + unsigned long remoteip;
66 } short_score;
67
68 typedef struct {
69 diff -ur apache_1.3.9rusPL28.20/src/main/http_config.c apache_1.3.9rusPL28.20-patch/src/main/http_config.c
70 --- apache_1.3.9rusPL28.20/src/main/http_config.c Sat Aug 21 02:45:03 1999
71 +++ apache_1.3.9rusPL28.20-patch/src/main/http_config.c Tue Sep 21 17:34:53 1999
72 @@ -1399,6 +1399,8 @@
73 ap_daemons_to_start = DEFAULT_START_DAEMON;
74 ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
75 ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
76 + ap_daemons_max_by_ip = DEFAULT_MAX_DAEMONS_BY_IP;
77 + ap_daemons_max_by_ip_read = DEFAULT_MAX_DAEMONS_BY_IP_READ;
78 ap_daemons_limit = HARD_SERVER_LIMIT;
79 ap_pid_fname = DEFAULT_PIDLOG;
80 ap_scoreboard_fname = DEFAULT_SCOREBOARD;
81 diff -ur apache_1.3.9rusPL28.20/src/main/http_core.c apache_1.3.9rusPL28.20-patch/src/main/http_core.c
82 --- apache_1.3.9rusPL28.20/src/main/http_core.c Sat Aug 21 02:45:03 1999
83 +++ apache_1.3.9rusPL28.20-patch/src/main/http_core.c Tue Sep 21 17:34:53 1999
84 @@ -2182,6 +2182,16 @@
85 return NULL;
86 }
87
88 +const char * set_max_servers_by_ip (cmd_parms *cmd, void *dummy, char *arg) {
89 + ap_daemons_max_by_ip = atoi (arg);
90 + return NULL;
91 +}
92 +
93 +const char * set_max_servers_by_ip_read (cmd_parms *cmd,void *dummy,char *arg) {
94 + ap_daemons_max_by_ip_read = atoi (arg);
95 + return NULL;
96 +}
97 +
98 static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, char *arg)
99 {
100 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
101 @@ -2852,6 +2862,10 @@
102 "Maximum number of idle children" },
103 { "MaxServers", set_max_free_servers, NULL, RSRC_CONF, TAKE1,
104 "Deprecated equivalent to MaxSpareServers" },
105 +{ "MaxServersPerIP", set_max_servers_by_ip, NULL, RSRC_CONF, TAKE1,
106 + "Maximum number of connections from a single IP address" },
107 +{ "MaxServersPerIPRead", set_max_servers_by_ip_read, NULL, RSRC_CONF, TAKE1,
108 + "Maximum number of connection from a single IP address in read state at any time." },
109 { "ServersSafetyLimit", set_server_limit, NULL, RSRC_CONF, TAKE1,
110 "Deprecated equivalent to MaxClients" },
111 { "MaxClients", set_server_limit, NULL, RSRC_CONF, TAKE1,
112 diff -ur apache_1.3.9rusPL28.20/src/main/http_main.c apache_1.3.9rusPL28.20-patch/src/main/http_main.c
113 --- apache_1.3.9rusPL28.20/src/main/http_main.c Sat Aug 21 02:45:05 1999
114 +++ apache_1.3.9rusPL28.20-patch/src/main/http_main.c Tue Sep 21 17:37:07 1999
115 @@ -249,6 +249,8 @@
116 API_VAR_EXPORT int ap_daemons_to_start=0;
117 API_VAR_EXPORT int ap_daemons_min_free=0;
118 API_VAR_EXPORT int ap_daemons_max_free=0;
119 +API_VAR_EXPORT int ap_daemons_max_by_ip;
120 +API_VAR_EXPORT int ap_daemons_max_by_ip_read;
121 API_VAR_EXPORT int ap_daemons_limit=0;
122 time_t ap_restart_time=0;
123 API_VAR_EXPORT int ap_suexec_enabled = 0;
124 @@ -2183,6 +2185,38 @@
125 return old_status;
126 }
127
128 +void update_child_status_remote_ip (int child_num, conn_rec * current_conn)
129 +{
130 + int slot_size;
131 + short_score new_score_rec;
132 +
133 + if (child_num < 0) { return; }
134 +
135 +printf("update ip %u\n", current_conn->remote_addr.sin_addr.s_addr);
136 +
137 + ap_sync_scoreboard_image();
138 + new_score_rec = ap_scoreboard_image->servers[child_num];
139 +
140 + slot_size = sizeof(new_score_rec.remoteip) - 1;
141 +
142 + if (current_conn)
143 + {
144 + new_score_rec.remoteip = current_conn->remote_addr.sin_addr.s_addr;
145 + }
146 + else
147 + {
148 + new_score_rec.remoteip = 0;
149 + }
150 +#if defined(HAVE_MMAP) || defined(HAVE_SHMGET)
151 + memcpy(&ap_scoreboard_image->servers[child_num], &new_score_rec, sizeof new_score_rec);
152 +#else
153 + lseek (scoreboard_fd, (long)child_num * sizeof(short_score), 0);
154 + force_write (scoreboard_fd, (char*)&new_score_rec, sizeof(short_score));
155 +#endif
156 +
157 + ap_sync_scoreboard_image();
158 +}
159 +
160 static void update_scoreboard_global(void)
161 {
162 #ifdef SCOREBOARD_FILE
163 @@ -2193,6 +2227,26 @@
164 #endif
165 }
166
167 +int count_connections (conn_rec * current_conn, int state)
168 +{
169 + unsigned long remote_ip = current_conn->remote_addr.sin_addr.s_addr;
170 + int res = 0, i;
171 +
172 + for (i = 0; i < HARD_SERVER_LIMIT; i++)
173 + {
174 + if ((ap_scoreboard_image->servers[i].status == SERVER_DEAD) ||
175 + (state > 0 && ap_scoreboard_image->servers[i].status != state))
176 + {
177 + continue;
178 + }
179 + if (ap_scoreboard_image->servers[i].remoteip == remote_ip)
180 + {
181 + res++;
182 + }
183 + }
184 + return res;
185 +}
186 +
187 void ap_time_process_request(int child_num, int status)
188 {
189 short_score *ss;
190 @@ -4021,12 +4075,15 @@
191 * until no requests are left or we decide to close.
192 */
193
194 - while ((r = ap_read_request(current_conn)) != NULL) {
195 + for (;;){
196 + if (ap_daemons_max_by_ip || ap_daemons_max_by_ip_read)
197 + update_child_status_remote_ip (my_child_num, (conn_rec *)current_conn);
198 +
199 + if ((r = ap_read_request(current_conn)) == NULL) break;
200
201 /* read_request_line has already done a
202 * signal (SIGUSR1, SIG_IGN);
203 */
204 -
205 (void) ap_update_child_status(my_child_num, SERVER_BUSY_WRITE, r);
206
207 /* process the request if it was read without error */
208 @@ -5248,6 +5305,9 @@
209 * until no requests are left or we decide to close.
210 */
211 - while ((r = ap_read_request(current_conn)) != NULL) {
212 + for (;;){
213 + if (daemons_max_by_ip || daemons_max_by_ip_read)
214 + update_child_status_remote_ip (child_num, (conn_rec *)current_conn);
215 + if ((r = ap_read_request(current_conn)) == NULL) break;
216 (void) ap_update_child_status(child_num, SERVER_BUSY_WRITE, r);
217
218 if (r->status == HTTP_OK)
219 @@ -5273,6 +5333,10 @@
220 * client has ACKed our FIN and/or has stopped sending us data.
221 */
222 ap_kill_cleanups_for_socket(ptrans, csd);
223 +
224 + if (daemons_max_by_ip || daemons_max_by_ip_read)
225 + update_child_status_remote_ip (child_num, (conn_rec *)NULL);
226 +
227
228 #ifdef NO_LINGCLOSE
229 ap_bclose(conn_io); /* just close it */
230 diff -ur apache_1.3.9rusPL28.20/src/main/http_protocol.c apache_1.3.9rusPL28.20-patch/src/main/http_protocol.c
231 --- apache_1.3.9rusPL28.20/src/main/http_protocol.c Thu Sep 2 22:59:02 1999
232 +++ apache_1.3.9rusPL28.20-patch/src/main/http_protocol.c Tue Sep 21 17:34:55 1999
233 @@ -73,6 +73,15 @@
234 #include "http_log.h" /* For errors detected in basic auth common
235 * support code... */
236 #include "util_date.h" /* For parseHTTPdate and BAD_DATE */
237 +
238 +#include "scoreboard.h" /* for limiting connections by IP */
239 +#ifndef LONG_STRING_LEN
240 +#define LONG_STRING_LEN 2048
241 +#endif /* LONG_STRING_LEN */
242 +extern int ap_daemons_max_by_ip;
243 +extern int ap_daemons_max_by_ip_read;
244 +extern void ap_die();
245 +
246 #include <stdarg.h>
247 #include "http_conf_globals.h"
248
249 @@ -935,6 +944,8 @@
250 pool *p;
251 const char *expect;
252 int access_status;
253 + int current_connections;
254 + char *reject_state = NULL;
255
256 p = ap_make_sub_pool(conn->pool);
257 r = ap_pcalloc(p, sizeof(request_rec));
258 @@ -966,6 +977,33 @@
259 r->read_length = 0;
260 r->read_body = REQUEST_NO_BODY;
261
262 + if (ap_daemons_max_by_ip && ((current_connections = count_connections(conn,0))
263 + > ap_daemons_max_by_ip))
264 + {
265 + r->request_time=time(NULL);
266 + reject_state = "total";
267 + }
268 + else if (ap_daemons_max_by_ip_read &&
269 + ((current_connections = count_connections(conn,SERVER_BUSY_READ))
270 + > ap_daemons_max_by_ip_read))
271 + {
272 + reject_state = "read state";
273 + }
274 + if (reject_state) {
275 + r->status = HTTP_OK;
276 + r->request_time = time(NULL);
277 + r->proto_num = 1000; /* or something */
278 + r->assbackwards = 0; /* who knows... */
279 + r->protocol = "HTTP/1.0"; /* just not empty */
280 + r->the_request = NULL;
281 + r->method = NULL;
282 + r->method_number = M_INVALID;
283 + ap_die(LIMIT_CONNECTIONS_BY_IP_ERROR, r);
284 + ap_log_transaction(r);
285 + ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, conn->server, "Client at %s for %s with %d %s current connections", conn->remote_ip, conn->server->server_hostname, current_connections, reject_state);
286 + return NULL;
287 + }
288 +
289 r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */
290 r->the_request = NULL;
291