Mercurial > hg > nginx-quic
comparison src/http/modules/ngx_http_geo_module.c @ 3242:f678ea405737 stable-0.7
merge r2993:
geo module supports trusted proxies
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 26 Oct 2009 16:42:19 +0000 |
parents | 415400fa0f10 |
children | 24e7bf1abbe5 |
comparison
equal
deleted
inserted
replaced
3241:0ecc8d7c77b1 | 3242:f678ea405737 |
---|---|
33 ngx_str_t *net; | 33 ngx_str_t *net; |
34 ngx_http_geo_high_ranges_t *high; | 34 ngx_http_geo_high_ranges_t *high; |
35 ngx_radix_tree_t *tree; | 35 ngx_radix_tree_t *tree; |
36 ngx_rbtree_t rbtree; | 36 ngx_rbtree_t rbtree; |
37 ngx_rbtree_node_t sentinel; | 37 ngx_rbtree_node_t sentinel; |
38 ngx_array_t *proxies; | |
38 ngx_pool_t *pool; | 39 ngx_pool_t *pool; |
39 ngx_pool_t *temp_pool; | 40 ngx_pool_t *temp_pool; |
40 } ngx_http_geo_conf_ctx_t; | 41 } ngx_http_geo_conf_ctx_t; |
41 | 42 |
42 | 43 |
44 union { | 45 union { |
45 ngx_radix_tree_t *tree; | 46 ngx_radix_tree_t *tree; |
46 ngx_http_geo_high_ranges_t *high; | 47 ngx_http_geo_high_ranges_t *high; |
47 } u; | 48 } u; |
48 | 49 |
50 ngx_array_t *proxies; | |
51 | |
49 ngx_int_t index; | 52 ngx_int_t index; |
50 } ngx_http_geo_ctx_t; | 53 } ngx_http_geo_ctx_t; |
51 | 54 |
52 | 55 |
53 static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r, | 56 static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r, |
57 ngx_http_geo_ctx_t *ctx); | |
58 static in_addr_t ngx_http_geo_real_addr(ngx_http_request_t *r, | |
54 ngx_http_geo_ctx_t *ctx); | 59 ngx_http_geo_ctx_t *ctx); |
55 static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 60 static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
56 static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); | 61 static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); |
57 static char *ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, | 62 static char *ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, |
58 ngx_str_t *value); | 63 ngx_str_t *value); |
62 ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end); | 67 ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end); |
63 static char *ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, | 68 static char *ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, |
64 ngx_str_t *value); | 69 ngx_str_t *value); |
65 static ngx_http_variable_value_t *ngx_http_geo_value(ngx_conf_t *cf, | 70 static ngx_http_variable_value_t *ngx_http_geo_value(ngx_conf_t *cf, |
66 ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *value); | 71 ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *value); |
72 static char *ngx_http_geo_add_proxy(ngx_conf_t *cf, | |
73 ngx_http_geo_conf_ctx_t *ctx, ngx_cidr_t *cidr); | |
74 static ngx_int_t ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net, | |
75 ngx_cidr_t *cidr); | |
67 | 76 |
68 | 77 |
69 static ngx_command_t ngx_http_geo_commands[] = { | 78 static ngx_command_t ngx_http_geo_commands[] = { |
70 | 79 |
71 { ngx_string("geo"), | 80 { ngx_string("geo"), |
166 | 175 |
167 | 176 |
168 static in_addr_t | 177 static in_addr_t |
169 ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx) | 178 ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx) |
170 { | 179 { |
180 u_char *p, *ip; | |
181 size_t len; | |
182 in_addr_t addr; | |
183 ngx_uint_t i, n; | |
184 ngx_in_cidr_t *proxies; | |
185 ngx_table_elt_t *xfwd; | |
186 | |
187 addr = ngx_http_geo_real_addr(r, ctx); | |
188 | |
189 xfwd = r->headers_in.x_forwarded_for; | |
190 | |
191 if (xfwd == NULL || ctx->proxies == NULL) { | |
192 return addr; | |
193 } | |
194 | |
195 proxies = ctx->proxies->elts; | |
196 n = ctx->proxies->nelts; | |
197 | |
198 for (i = 0; i < n; i++) { | |
199 if ((addr & proxies[i].mask) == proxies[i].addr) { | |
200 | |
201 len = xfwd->value.len; | |
202 ip = xfwd->value.data; | |
203 | |
204 for (p = ip + len - 1; p > ip; p--) { | |
205 if (*p == ' ' || *p == ',') { | |
206 p++; | |
207 len -= p - ip; | |
208 ip = p; | |
209 break; | |
210 } | |
211 } | |
212 | |
213 return ntohl(ngx_inet_addr(ip, len)); | |
214 } | |
215 } | |
216 | |
217 return addr; | |
218 } | |
219 | |
220 | |
221 static in_addr_t | |
222 ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx) | |
223 { | |
171 struct sockaddr_in *sin; | 224 struct sockaddr_in *sin; |
172 ngx_http_variable_value_t *v; | 225 ngx_http_variable_value_t *v; |
173 | 226 |
174 if (ctx->index == -1) { | 227 if (ctx->index == -1) { |
175 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 228 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
257 ngx_rbtree_init(&ctx.rbtree, &ctx.sentinel, | 310 ngx_rbtree_init(&ctx.rbtree, &ctx.sentinel, |
258 ngx_http_variable_value_rbtree_insert); | 311 ngx_http_variable_value_rbtree_insert); |
259 | 312 |
260 ctx.high = NULL; | 313 ctx.high = NULL; |
261 ctx.tree = NULL; | 314 ctx.tree = NULL; |
315 ctx.proxies = NULL; | |
262 ctx.pool = cf->pool; | 316 ctx.pool = cf->pool; |
263 | 317 |
264 save = *cf; | 318 save = *cf; |
265 cf->pool = pool; | 319 cf->pool = pool; |
266 cf->ctx = &ctx; | 320 cf->ctx = &ctx; |
269 | 323 |
270 rv = ngx_conf_parse(cf, NULL); | 324 rv = ngx_conf_parse(cf, NULL); |
271 | 325 |
272 *cf = save; | 326 *cf = save; |
273 | 327 |
328 geo->proxies = ctx.proxies; | |
329 | |
274 if (ctx.high) { | 330 if (ctx.high) { |
275 | 331 |
276 for (i = 0; i < 0x10000; i++) { | 332 for (i = 0; i < 0x10000; i++) { |
277 a = (ngx_array_t *) ctx.high->low[i].ranges; | 333 a = (ngx_array_t *) ctx.high->low[i].ranges; |
278 | 334 |
339 static char * | 395 static char * |
340 ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) | 396 ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) |
341 { | 397 { |
342 char *rv; | 398 char *rv; |
343 ngx_str_t *value, file; | 399 ngx_str_t *value, file; |
400 ngx_cidr_t cidr; | |
344 ngx_http_geo_conf_ctx_t *ctx; | 401 ngx_http_geo_conf_ctx_t *ctx; |
345 | 402 |
346 ctx = cf->ctx; | 403 ctx = cf->ctx; |
347 | 404 |
348 value = cf->args->elts; | 405 value = cf->args->elts; |
390 } | 447 } |
391 | 448 |
392 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); | 449 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); |
393 | 450 |
394 rv = ngx_conf_parse(cf, &file); | 451 rv = ngx_conf_parse(cf, &file); |
452 | |
453 goto done; | |
454 | |
455 } else if (ngx_strcmp(value[0].data, "proxy") == 0) { | |
456 | |
457 if (ngx_http_geo_cidr_value(cf, &value[1], &cidr) != NGX_OK) { | |
458 goto failed; | |
459 } | |
460 | |
461 rv = ngx_http_geo_add_proxy(cf, ctx, &cidr); | |
395 | 462 |
396 goto done; | 463 goto done; |
397 } | 464 } |
398 | 465 |
399 if (ctx->high) { | 466 if (ctx->high) { |
801 } else { | 868 } else { |
802 net = &value[0]; | 869 net = &value[0]; |
803 del = 0; | 870 del = 0; |
804 } | 871 } |
805 | 872 |
806 if (ngx_strcmp(net->data, "255.255.255.255") == 0) { | 873 if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) { |
807 cidr.u.in.addr = 0xffffffff; | 874 return NGX_CONF_ERROR; |
808 cidr.u.in.mask = 0xffffffff; | |
809 | |
810 } else { | |
811 rc = ngx_ptocidr(net, &cidr); | |
812 | |
813 if (rc == NGX_ERROR) { | |
814 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
815 "invalid network \"%V\"", net); | |
816 return NGX_CONF_ERROR; | |
817 } | |
818 | |
819 if (cidr.family != AF_INET) { | |
820 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
821 "\"geo\" supports IPv4 only"); | |
822 return NGX_CONF_ERROR; | |
823 } | |
824 | |
825 if (rc == NGX_DONE) { | |
826 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
827 "low address bits of %V are meaningless", | |
828 net); | |
829 } | |
830 | |
831 cidr.u.in.addr = ntohl(cidr.u.in.addr); | |
832 cidr.u.in.mask = ntohl(cidr.u.in.mask); | |
833 } | 875 } |
834 | 876 |
835 if (del) { | 877 if (del) { |
836 if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, | 878 if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, |
837 cidr.u.in.mask) | 879 cidr.u.in.mask) |
925 | 967 |
926 ngx_rbtree_insert(&ctx->rbtree, &vvn->node); | 968 ngx_rbtree_insert(&ctx->rbtree, &vvn->node); |
927 | 969 |
928 return val; | 970 return val; |
929 } | 971 } |
972 | |
973 | |
974 static char * | |
975 ngx_http_geo_add_proxy(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, | |
976 ngx_cidr_t *cidr) | |
977 { | |
978 ngx_in_cidr_t *c; | |
979 | |
980 if (ctx->proxies == NULL) { | |
981 ctx->proxies = ngx_array_create(ctx->pool, 4, sizeof(ngx_in_cidr_t)); | |
982 if (ctx->proxies == NULL) { | |
983 return NGX_CONF_ERROR; | |
984 } | |
985 } | |
986 | |
987 c = ngx_array_push(ctx->proxies); | |
988 if (c == NULL) { | |
989 return NGX_CONF_ERROR; | |
990 } | |
991 | |
992 c->addr = cidr->u.in.addr; | |
993 c->mask = cidr->u.in.mask; | |
994 | |
995 return NGX_CONF_OK; | |
996 } | |
997 | |
998 | |
999 static ngx_int_t | |
1000 ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr) | |
1001 { | |
1002 ngx_int_t rc; | |
1003 | |
1004 if (ngx_strcmp(net->data, "255.255.255.255") == 0) { | |
1005 cidr->u.in.addr = 0xffffffff; | |
1006 cidr->u.in.mask = 0xffffffff; | |
1007 | |
1008 return NGX_OK; | |
1009 } | |
1010 | |
1011 rc = ngx_ptocidr(net, cidr); | |
1012 | |
1013 if (rc == NGX_ERROR) { | |
1014 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid network \"%V\"", net); | |
1015 return NGX_ERROR; | |
1016 } | |
1017 | |
1018 if (cidr->family != AF_INET) { | |
1019 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"geo\" supports IPv4 only"); | |
1020 return NGX_ERROR; | |
1021 } | |
1022 | |
1023 if (rc == NGX_DONE) { | |
1024 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
1025 "low address bits of %V are meaningless", net); | |
1026 } | |
1027 | |
1028 cidr->u.in.addr = ntohl(cidr->u.in.addr); | |
1029 cidr->u.in.mask = ntohl(cidr->u.in.mask); | |
1030 | |
1031 return NGX_OK; | |
1032 } |