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,9 +159,11 @@
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 #ifdef MOD_DEFLATE_IDLE
66 int deflate;
67 #endif
68 +
69 + unsigned long remoteip;
70 } short_score;
71
72 typedef struct {
73 diff -ur apache_1.3.9rusPL28.20/src/main/http_config.c apache_1.3.9rusPL28.20-patch/src/main/http_config.c
74 --- apache_1.3.9rusPL28.20/src/main/http_config.c Sat Aug 21 02:45:03 1999
75 +++ apache_1.3.9rusPL28.20-patch/src/main/http_config.c Tue Sep 21 17:34:53 1999
76 @@ -1399,6 +1399,8 @@
77 ap_daemons_to_start = DEFAULT_START_DAEMON;
78 ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
79 ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
80 + ap_daemons_max_by_ip = DEFAULT_MAX_DAEMONS_BY_IP;
81 + ap_daemons_max_by_ip_read = DEFAULT_MAX_DAEMONS_BY_IP_READ;
82 ap_daemons_limit = HARD_SERVER_LIMIT;
83 ap_pid_fname = DEFAULT_PIDLOG;
84 ap_scoreboard_fname = DEFAULT_SCOREBOARD;
85 diff -ur apache_1.3.9rusPL28.20/src/main/http_core.c apache_1.3.9rusPL28.20-patch/src/main/http_core.c
86 --- apache_1.3.9rusPL28.20/src/main/http_core.c Sat Aug 21 02:45:03 1999
87 +++ apache_1.3.9rusPL28.20-patch/src/main/http_core.c Tue Sep 21 17:34:53 1999
88 @@ -2182,6 +2182,16 @@
89 return NULL;
90 }
91
92 +const char * set_max_servers_by_ip (cmd_parms *cmd, void *dummy, char *arg) {
93 + ap_daemons_max_by_ip = atoi (arg);
94 + return NULL;
95 +}
96 +
97 +const char * set_max_servers_by_ip_read (cmd_parms *cmd,void *dummy,char *arg) {
98 + ap_daemons_max_by_ip_read = atoi (arg);
99 + return NULL;
100 +}
101 +
102 static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, char *arg)
103 {
104 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
105 @@ -2852,6 +2862,10 @@
106 "Maximum number of idle children" },
107 { "MaxServers", set_max_free_servers, NULL, RSRC_CONF, TAKE1,
108 "Deprecated equivalent to MaxSpareServers" },
109 +{ "MaxServersPerIP", set_max_servers_by_ip, NULL, RSRC_CONF, TAKE1,
110 + "Maximum number of connections from a single IP address" },
111 +{ "MaxServersPerIPRead", set_max_servers_by_ip_read, NULL, RSRC_CONF, TAKE1,
112 + "Maximum number of connection from a single IP address in read state at any time." },
113 { "ServersSafetyLimit", set_server_limit, NULL, RSRC_CONF, TAKE1,
114 "Deprecated equivalent to MaxClients" },
115 { "MaxClients", set_server_limit, NULL, RSRC_CONF, TAKE1,
116 diff -ur apache_1.3.9rusPL28.20/src/main/http_main.c apache_1.3.9rusPL28.20-patch/src/main/http_main.c
117 --- apache_1.3.9rusPL28.20/src/main/http_main.c Sat Aug 21 02:45:05 1999
118 +++ apache_1.3.9rusPL28.20-patch/src/main/http_main.c Tue Sep 21 17:37:07 1999
119 @@ -249,6 +249,8 @@
120 API_VAR_EXPORT int ap_daemons_to_start=0;
121 API_VAR_EXPORT int ap_daemons_min_free=0;
122 API_VAR_EXPORT int ap_daemons_max_free=0;
123 +API_VAR_EXPORT int ap_daemons_max_by_ip;
124 +API_VAR_EXPORT int ap_daemons_max_by_ip_read;
125 API_VAR_EXPORT int ap_daemons_limit=0;
126 time_t ap_restart_time=0;
127 API_VAR_EXPORT int ap_suexec_enabled = 0;
128 @@ -2183,6 +2185,38 @@
129 return old_status;
130 }
131
132 +void update_child_status_remote_ip (int child_num, conn_rec * current_conn)
133 +{
134 + int slot_size;
135 + short_score new_score_rec;
136 +
137 + if (child_num < 0) { return; }
138 +
139 +printf("update ip %u\n", current_conn->remote_addr.sin_addr.s_addr);
140 +
141 + ap_sync_scoreboard_image();
142 + new_score_rec = ap_scoreboard_image->servers[child_num];
143 +
144 + slot_size = sizeof(new_score_rec.remoteip) - 1;
145 +
146 + if (current_conn)
147 + {
148 + new_score_rec.remoteip = current_conn->remote_addr.sin_addr.s_addr;
149 + }
150 + else
151 + {
152 + new_score_rec.remoteip = 0;
153 + }
154 +#if defined(HAVE_MMAP) || defined(HAVE_SHMGET)
155 + memcpy(&ap_scoreboard_image->servers[child_num], &new_score_rec, sizeof new_score_rec);
156 +#else
157 + lseek (scoreboard_fd, (long)child_num * sizeof(short_score), 0);
158 + force_write (scoreboard_fd, (char*)&new_score_rec, sizeof(short_score));
159 +#endif
160 +
161 + ap_sync_scoreboard_image();
162 +}
163 +
164 static void update_scoreboard_global(void)
165 {
166 #ifdef SCOREBOARD_FILE
167 @@ -2193,6 +2227,26 @@
168 #endif
169 }
170
171 +int count_connections (conn_rec * current_conn, int state)
172 +{
173 + unsigned long remote_ip = current_conn->remote_addr.sin_addr.s_addr;
174 + int res = 0, i;
175 +
176 + for (i = 0; i < HARD_SERVER_LIMIT; i++)
177 + {
178 + if ((ap_scoreboard_image->servers[i].status == SERVER_DEAD) ||
179 + (state > 0 && ap_scoreboard_image->servers[i].status != state))
180 + {
181 + continue;
182 + }
183 + if (ap_scoreboard_image->servers[i].remoteip == remote_ip)
184 + {
185 + res++;
186 + }
187 + }
188 + return res;
189 +}
190 +
191 void ap_time_process_request(int child_num, int status)
192 {
193 short_score *ss;
194 @@ -4021,12 +4075,15 @@
195 * until no requests are left or we decide to close.
196 */
197
198 - while ((r = ap_read_request(current_conn)) != NULL) {
199 + for (;;){
200 + if (ap_daemons_max_by_ip || ap_daemons_max_by_ip_read)
201 + update_child_status_remote_ip (my_child_num, (conn_rec *)current_conn);
202 +
203 + if ((r = ap_read_request(current_conn)) == NULL) break;
204
205 /* read_request_line has already done a
206 * signal (SIGUSR1, SIG_IGN);
207 */
208 -
209 (void) ap_update_child_status(my_child_num, SERVER_BUSY_WRITE, r);
210
211 /* process the request if it was read without error */
212 @@ -5248,6 +5305,9 @@
213 * until no requests are left or we decide to close.
214 */
215 - while ((r = ap_read_request(current_conn)) != NULL) {
216 + for (;;){
217 + if (daemons_max_by_ip || daemons_max_by_ip_read)
218 + update_child_status_remote_ip (child_num, (conn_rec *)current_conn);
219 + if ((r = ap_read_request(current_conn)) == NULL) break;
220 (void) ap_update_child_status(child_num, SERVER_BUSY_WRITE, r);
221
222 if (r->status == HTTP_OK)
223 @@ -5273,6 +5333,10 @@
224 * client has ACKed our FIN and/or has stopped sending us data.
225 */
226 ap_kill_cleanups_for_socket(ptrans, csd);
227 +
228 + if (daemons_max_by_ip || daemons_max_by_ip_read)
229 + update_child_status_remote_ip (child_num, (conn_rec *)NULL);
230 +
231
232 #ifdef NO_LINGCLOSE
233 ap_bclose(conn_io); /* just close it */
234 diff -ur apache_1.3.9rusPL28.20/src/main/http_protocol.c apache_1.3.9rusPL28.20-patch/src/main/http_protocol.c
235 --- apache_1.3.9rusPL28.20/src/main/http_protocol.c Thu Sep 2 22:59:02 1999
236 +++ apache_1.3.9rusPL28.20-patch/src/main/http_protocol.c Tue Sep 21 17:34:55 1999
237 @@ -73,6 +73,15 @@
238 #include "http_log.h" /* For errors detected in basic auth common
239 * support code... */
240 #include "util_date.h" /* For parseHTTPdate and BAD_DATE */
241 +
242 +#include "scoreboard.h" /* for limiting connections by IP */
243 +#ifndef LONG_STRING_LEN
244 +#define LONG_STRING_LEN 2048
245 +#endif /* LONG_STRING_LEN */
246 +extern int ap_daemons_max_by_ip;
247 +extern int ap_daemons_max_by_ip_read;
248 +extern void ap_die();
249 +
250 #include <stdarg.h>
251 #include "http_conf_globals.h"
252
253 @@ -935,6 +944,8 @@
254 pool *p;
255 const char *expect;
256 int access_status;
257 + int current_connections;
258 + char *reject_state = NULL;
259
260 p = ap_make_sub_pool(conn->pool);
261 r = ap_pcalloc(p, sizeof(request_rec));
262 @@ -966,6 +977,33 @@
263 r->read_length = 0;
264 r->read_body = REQUEST_NO_BODY;
265
266 + if (ap_daemons_max_by_ip && ((current_connections = count_connections(conn,0))
267 + > ap_daemons_max_by_ip))
268 + {
269 + r->request_time=time(NULL);
270 + reject_state = "total";
271 + }
272 + else if (ap_daemons_max_by_ip_read &&
273 + ((current_connections = count_connections(conn,SERVER_BUSY_READ))
274 + > ap_daemons_max_by_ip_read))
275 + {
276 + reject_state = "read state";
277 + }
278 + if (reject_state) {
279 + r->status = HTTP_OK;
280 + r->request_time = time(NULL);
281 + r->proto_num = 1000; /* or something */
282 + r->assbackwards = 0; /* who knows... */
283 + r->protocol = "HTTP/1.0"; /* just not empty */
284 + r->the_request = NULL;
285 + r->method = NULL;
286 + r->method_number = M_INVALID;
287 + ap_die(LIMIT_CONNECTIONS_BY_IP_ERROR, r);
288 + ap_log_transaction(r);
289 + 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);
290 + return NULL;
291 + }
292 +
293 r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */
294 r->the_request = NULL;
295