Changeset 2061
- Timestamp:
- 01/21/2008 08:21:20 AM (4 months ago)
- Files:
-
- branches/lighttpd-1.4.x/NEWS (modified) (1 diff)
- branches/lighttpd-1.4.x/src/mod_extforward.c (modified) (11 diffs)
- branches/lighttpd-1.4.x/tests/docroot/www/ip.pl (modified) (1 diff)
- branches/lighttpd-1.4.x/tests/mod-extforward.conf (modified) (2 diffs)
- branches/lighttpd-1.4.x/tests/mod-extforward.t (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/lighttpd-1.4.x/NEWS
r2058 r2061 21 21 * generate ETag and Last-Modified headers for mod_ssi based on newest modified include (#1491) 22 22 * support letterhomes in mod_userdir (#1473) 23 * support chained proxies in mod_extforward (#1528) 23 24 24 25 - 1.4.18 - 2007-09-09 branches/lighttpd-1.4.x/src/mod_extforward.c
r2052 r2061 21 21 * mod_extforward.c for lighttpd, by comman.kang <at> gmail <dot> com 22 22 * extended, modified by Lionel Elie Mamane (LEM), lionel <at> mamane <dot> lu 23 * support chained proxies by glen@delfi.ee, #1528 23 24 * 24 25 * Config example: … … 33 34 * Note that "all" has precedence over specific entries, 34 35 * so "all except" setups will not work. 36 * 37 * In case you have chained proxies, you can add all their IP's to the 38 * config. However "all" has effect only on connecting IP, as the 39 * X-Forwarded-For header can not be trusted. 35 40 * 36 41 * Note: The effect of this module is variable on $HTTP["remotip"] directives and … … 226 231 /* state variable, 0 means not in string, 1 means in string */ 227 232 int in_str = 0; 228 for (base = pbuffer->ptr, curr = pbuffer->ptr; *curr; curr++) 229 { 233 for (base = pbuffer->ptr, curr = pbuffer->ptr; *curr; curr++) { 230 234 if (in_str) { 231 if ( (*curr > '9' || *curr < '0') && *curr != '.' && *curr != ':') {235 if ((*curr > '9' || *curr < '0') && *curr != '.' && *curr != ':') { 232 236 /* found an separator , insert value into result array */ 233 put_string_into_array_len(result, base, curr -base);237 put_string_into_array_len(result, base, curr - base); 234 238 /* change state to not in string */ 235 239 in_str = 0; 236 240 } 237 241 } else { 238 if (*curr >= '0' && *curr <= '9') 239 { 242 if (*curr >= '0' && *curr <= '9') { 240 243 /* found leading char of an IP address, move base pointer and change state */ 241 244 base = curr; … … 245 248 } 246 249 /* if breaking out while in str, we got to the end of string, so add it */ 247 if (in_str) 248 { 249 put_string_into_array_len(result, base, curr-base); 250 if (in_str) { 251 put_string_into_array_len(result, base, curr - base); 250 252 } 251 253 } … … 256 258 #define IP_UNTRUSTED 0 257 259 /* 258 check whether ip is trusted, return 1 for trusted , 0 for untrusted259 */260 * check whether ip is trusted, return 1 for trusted , 0 for untrusted 261 */ 260 262 static int is_proxy_trusted(const char *ipstr, plugin_data *p) 261 263 { 262 data_string* allds = (data_string *) array_get_element(p->conf.forwarder,"all"); 264 data_string* allds = (data_string *)array_get_element(p->conf.forwarder, "all"); 265 263 266 if (allds) { 264 if (strcasecmp(allds->value->ptr, "trust") == 0)267 if (strcasecmp(allds->value->ptr, "trust") == 0) { 265 268 return IP_TRUSTED; 266 else269 } else { 267 270 return IP_UNTRUSTED; 268 } 269 return (data_string *)array_get_element(p->conf.forwarder,ipstr) ? IP_TRUSTED : IP_UNTRUSTED ; 271 } 272 } 273 274 return (data_string *)array_get_element(p->conf.forwarder, ipstr) ? IP_TRUSTED : IP_UNTRUSTED; 275 } 276 277 /* 278 * Return char *ip of last address of proxy that is not trusted. 279 * Do not accept "all" keyword here. 280 */ 281 static const char *last_not_in_array(array *a, plugin_data *p) 282 { 283 array *forwarder = p->conf.forwarder; 284 285 for (int i = a->used - 1; i >= 0; i--) { 286 data_string *ds = (data_string *)a->data[i]; 287 const char *ip = ds->value->ptr; 288 289 if (!array_get_element(forwarder, ip)) { 290 return ip; 291 } 292 } 293 return NULL; 270 294 } 271 295 … … 317 341 #endif 318 342 const char *dst_addr_str = NULL; 319 int i;320 343 array *forward_array = NULL; 321 c har *real_remote_addr = NULL;344 const char *real_remote_addr = NULL; 322 345 #ifdef HAVE_IPV6 323 346 #endif … … 343 366 } 344 367 345 /* if the remote ip itself is not trusted , then do nothing */346 368 #ifdef HAVE_IPV6 347 369 dst_addr_str = inet_ntop(con->dst_addr.plain.sa_family, … … 354 376 dst_addr_str = inet_ntoa(con->dst_addr.ipv4.sin_addr); 355 377 #endif 356 if (IP_UNTRUSTED == is_proxy_trusted (dst_addr_str, p) ) { 378 379 /* if the remote ip itself is not trusted, then do nothing */ 380 if (IP_UNTRUSTED == is_proxy_trusted(dst_addr_str, p)) { 357 381 if (con->conf.log_request_handling) { 358 382 log_error_write(srv, __FILE__, __LINE__, "s", … … 363 387 } 364 388 389 /* build forward_array from forwarded data_string */ 365 390 forward_array = extract_forward_array(forwarded->value); 366 367 /* Testing shows that multiple headers and multiple values in one header 368 come in _reverse_ order. So the first one we get is the last one in the request. */ 369 for (i = forward_array->used - 1; i >= 0; i--) { 370 data_string *ds = (data_string *) forward_array->data[i]; 371 if (ds) { 372 real_remote_addr = ds->value->ptr; 373 break; 374 } else { 375 /* bug ? bailing out here */ 376 break; 377 } 378 } 391 real_remote_addr = last_not_in_array(forward_array, p); 379 392 380 393 if (real_remote_addr != NULL) { /* parsed */ … … 382 395 struct addrinfo *addrs_left; 383 396 server_socket *srv_sock = con->srv_socket; 384 data_string *forwarded_proto = (data_string *) array_get_element(con->request.headers,"X-Forwarded-Proto");385 386 if (forwarded_proto && !strcmp(forwarded_proto->value->ptr, "https")) 397 data_string *forwarded_proto = (data_string *)array_get_element(con->request.headers, "X-Forwarded-Proto"); 398 399 if (forwarded_proto && !strcmp(forwarded_proto->value->ptr, "https")) { 387 400 srv_sock->is_proxy_ssl = 1; 388 else401 } else { 389 402 srv_sock->is_proxy_ssl = 0; 403 } 390 404 391 405 if (con->conf.log_request_handling) { 392 log_error_write(srv, __FILE__, __LINE__, "ss", 393 "using address:", real_remote_addr); 406 log_error_write(srv, __FILE__, __LINE__, "ss", "using address:", real_remote_addr); 394 407 } 395 408 #ifdef HAVE_IPV6 396 409 addrlist = ipstr_to_sockaddr(real_remote_addr); 397 410 sock.plain.sa_family = AF_UNSPEC; 398 for (addrs_left = addrlist; addrs_left != NULL; 399 addrs_left = addrs_left -> ai_next) { 411 for (addrs_left = addrlist; addrs_left != NULL; addrs_left = addrs_left -> ai_next) { 400 412 sock.plain.sa_family = addrs_left->ai_family; 401 if ( sock.plain.sa_family == AF_INET) {413 if (sock.plain.sa_family == AF_INET) { 402 414 sock.ipv4.sin_addr = ((struct sockaddr_in*)addrs_left->ai_addr)->sin_addr; 403 415 break; 404 } else if ( sock.plain.sa_family == AF_INET6) {416 } else if (sock.plain.sa_family == AF_INET6) { 405 417 sock.ipv6.sin6_addr = ((struct sockaddr_in6*)addrs_left->ai_addr)->sin6_addr; 406 418 break; … … 437 449 #endif 438 450 } 439 array_free(forward_array);451 array_free(forward_array); 440 452 441 453 /* not found */ branches/lighttpd-1.4.x/tests/docroot/www/ip.pl
r2044 r2061 3 3 print $ENV{'REMOTE_ADDR'}; 4 4 5 if ($ENV{'QUERY_STRING'} eq 'info') { 6 print "\nF:",$ENV{'HTTP_X_FORWARDED_FOR'},"\n"; 7 8 while (my($key, $value) = each %ENV) { 9 printf "%s => %s\n", $key, $value; 10 } 11 } 12 5 13 0; branches/lighttpd-1.4.x/tests/mod-extforward.conf
r2044 r2061 1 1 debug.log-request-handling = "enable" 2 debug.log-response-header = " enable"3 debug.log-request-header = " enable"2 debug.log-response-header = "disable" 3 debug.log-request-header = "disable" 4 4 5 5 server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/" … … 28 28 extforward.forwarder = ( 29 29 "127.0.0.1" => "trust", 30 "127.0.30.1" => "trust", 30 31 ) branches/lighttpd-1.4.x/tests/mod-extforward.t
r2044 r2061 9 9 use strict; 10 10 use IO::Socket; 11 use Test::More tests => 2;11 use Test::More tests => 5; 12 12 use LightyTest; 13 13 … … 19 19 ok($tf->start_proc == 0, "Starting lighttpd") or die(); 20 20 21 ## check if If-Modified-Since, If-None-Match works22 23 21 $t->{REQUEST} = ( <<EOF 24 22 GET /ip.pl HTTP/1.0 … … 28 26 ); 29 27 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '127.0.10.1' } ]; 30 ok($tf->handle_http($t) == 0, 'expect 127.0.10.1 ');28 ok($tf->handle_http($t) == 0, 'expect 127.0.10.1, from single ip'); 31 29 32 30 $t->{REQUEST} = ( <<EOF … … 37 35 ); 38 36 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '127.0.20.1' } ]; 39 ok($tf->handle_http($t) == 0, 'expect 127.0.20.1'); 37 ok($tf->handle_http($t) == 0, 'expect 127.0.20.1, from two ips'); 38 39 $t->{REQUEST} = ( <<EOF 40 GET /ip.pl HTTP/1.0 41 Host: www.example.org 42 X-Forwarded-For: 127.0.10.1, 127.0.20.1, 127.0.30.1 43 EOF 44 ); 45 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '127.0.20.1' } ]; 46 ok($tf->handle_http($t) == 0, 'expect 127.0.20.1, from chained proxies'); 40 47 41 48 ok($tf->stop_proc == 0, "Stopping lighttpd");

