Annotation of embedaddon/nginx/src/http/modules/ngx_http_realip_module.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (C) Igor Sysoev
4: * Copyright (C) Nginx, Inc.
5: */
6:
7:
8: #include <ngx_config.h>
9: #include <ngx_core.h>
10: #include <ngx_http.h>
11:
12:
13: #define NGX_HTTP_REALIP_XREALIP 0
14: #define NGX_HTTP_REALIP_XFWD 1
15: #define NGX_HTTP_REALIP_HEADER 2
16:
17:
18: typedef struct {
19: ngx_array_t *from; /* array of ngx_cidr_t */
20: ngx_uint_t type;
21: ngx_uint_t hash;
22: ngx_str_t header;
23: ngx_flag_t recursive;
24: } ngx_http_realip_loc_conf_t;
25:
26:
27: typedef struct {
28: ngx_connection_t *connection;
29: struct sockaddr *sockaddr;
30: socklen_t socklen;
31: ngx_str_t addr_text;
32: } ngx_http_realip_ctx_t;
33:
34:
35: static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r);
36: static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r,
37: ngx_addr_t *addr);
38: static void ngx_http_realip_cleanup(void *data);
39: static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
40: void *conf);
41: static char *ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
42: static void *ngx_http_realip_create_loc_conf(ngx_conf_t *cf);
43: static char *ngx_http_realip_merge_loc_conf(ngx_conf_t *cf,
44: void *parent, void *child);
45: static ngx_int_t ngx_http_realip_init(ngx_conf_t *cf);
46:
47:
48: static ngx_command_t ngx_http_realip_commands[] = {
49:
50: { ngx_string("set_real_ip_from"),
51: NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
52: ngx_http_realip_from,
53: NGX_HTTP_LOC_CONF_OFFSET,
54: 0,
55: NULL },
56:
57: { ngx_string("real_ip_header"),
58: NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
59: ngx_http_realip,
60: NGX_HTTP_LOC_CONF_OFFSET,
61: 0,
62: NULL },
63:
64: { ngx_string("real_ip_recursive"),
65: NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
66: ngx_conf_set_flag_slot,
67: NGX_HTTP_LOC_CONF_OFFSET,
68: offsetof(ngx_http_realip_loc_conf_t, recursive),
69: NULL },
70:
71: ngx_null_command
72: };
73:
74:
75:
76: static ngx_http_module_t ngx_http_realip_module_ctx = {
77: NULL, /* preconfiguration */
78: ngx_http_realip_init, /* postconfiguration */
79:
80: NULL, /* create main configuration */
81: NULL, /* init main configuration */
82:
83: NULL, /* create server configuration */
84: NULL, /* merge server configuration */
85:
86: ngx_http_realip_create_loc_conf, /* create location configuration */
87: ngx_http_realip_merge_loc_conf /* merge location configuration */
88: };
89:
90:
91: ngx_module_t ngx_http_realip_module = {
92: NGX_MODULE_V1,
93: &ngx_http_realip_module_ctx, /* module context */
94: ngx_http_realip_commands, /* module directives */
95: NGX_HTTP_MODULE, /* module type */
96: NULL, /* init master */
97: NULL, /* init module */
98: NULL, /* init process */
99: NULL, /* init thread */
100: NULL, /* exit thread */
101: NULL, /* exit process */
102: NULL, /* exit master */
103: NGX_MODULE_V1_PADDING
104: };
105:
106:
107: static ngx_int_t
108: ngx_http_realip_handler(ngx_http_request_t *r)
109: {
110: u_char *p;
111: size_t len;
112: ngx_str_t *value;
113: ngx_uint_t i, hash;
114: ngx_addr_t addr;
115: ngx_array_t *xfwd;
116: ngx_list_part_t *part;
117: ngx_table_elt_t *header;
118: ngx_connection_t *c;
119: ngx_http_realip_ctx_t *ctx;
120: ngx_http_realip_loc_conf_t *rlcf;
121:
122: ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module);
123:
124: if (ctx) {
125: return NGX_DECLINED;
126: }
127:
128: rlcf = ngx_http_get_module_loc_conf(r, ngx_http_realip_module);
129:
130: if (rlcf->from == NULL) {
131: return NGX_DECLINED;
132: }
133:
134: switch (rlcf->type) {
135:
136: case NGX_HTTP_REALIP_XREALIP:
137:
138: if (r->headers_in.x_real_ip == NULL) {
139: return NGX_DECLINED;
140: }
141:
142: value = &r->headers_in.x_real_ip->value;
143: xfwd = NULL;
144:
145: break;
146:
147: case NGX_HTTP_REALIP_XFWD:
148:
149: xfwd = &r->headers_in.x_forwarded_for;
150:
151: if (xfwd->elts == NULL) {
152: return NGX_DECLINED;
153: }
154:
155: value = NULL;
156:
157: break;
158:
159: default: /* NGX_HTTP_REALIP_HEADER */
160:
161: part = &r->headers_in.headers.part;
162: header = part->elts;
163:
164: hash = rlcf->hash;
165: len = rlcf->header.len;
166: p = rlcf->header.data;
167:
168: for (i = 0; /* void */ ; i++) {
169:
170: if (i >= part->nelts) {
171: if (part->next == NULL) {
172: break;
173: }
174:
175: part = part->next;
176: header = part->elts;
177: i = 0;
178: }
179:
180: if (hash == header[i].hash
181: && len == header[i].key.len
182: && ngx_strncmp(p, header[i].lowcase_key, len) == 0)
183: {
184: value = &header[i].value;
185: xfwd = NULL;
186:
187: goto found;
188: }
189: }
190:
191: return NGX_DECLINED;
192: }
193:
194: found:
195:
196: c = r->connection;
197:
198: addr.sockaddr = c->sockaddr;
199: addr.socklen = c->socklen;
200: /* addr.name = c->addr_text; */
201:
202: if (ngx_http_get_forwarded_addr(r, &addr, xfwd, value, rlcf->from,
203: rlcf->recursive)
204: != NGX_DECLINED)
205: {
206: return ngx_http_realip_set_addr(r, &addr);
207: }
208:
209: return NGX_DECLINED;
210: }
211:
212:
213: static ngx_int_t
214: ngx_http_realip_set_addr(ngx_http_request_t *r, ngx_addr_t *addr)
215: {
216: size_t len;
217: u_char *p;
218: u_char text[NGX_SOCKADDR_STRLEN];
219: ngx_connection_t *c;
220: ngx_pool_cleanup_t *cln;
221: ngx_http_realip_ctx_t *ctx;
222:
223: cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_realip_ctx_t));
224: if (cln == NULL) {
225: return NGX_HTTP_INTERNAL_SERVER_ERROR;
226: }
227:
228: ctx = cln->data;
229: ngx_http_set_ctx(r, ctx, ngx_http_realip_module);
230:
231: c = r->connection;
232:
233: len = ngx_sock_ntop(addr->sockaddr, text, NGX_SOCKADDR_STRLEN, 0);
234: if (len == 0) {
235: return NGX_HTTP_INTERNAL_SERVER_ERROR;
236: }
237:
238: p = ngx_pnalloc(c->pool, len);
239: if (p == NULL) {
240: return NGX_HTTP_INTERNAL_SERVER_ERROR;
241: }
242:
243: ngx_memcpy(p, text, len);
244:
245: cln->handler = ngx_http_realip_cleanup;
246:
247: ctx->connection = c;
248: ctx->sockaddr = c->sockaddr;
249: ctx->socklen = c->socklen;
250: ctx->addr_text = c->addr_text;
251:
252: c->sockaddr = addr->sockaddr;
253: c->socklen = addr->socklen;
254: c->addr_text.len = len;
255: c->addr_text.data = p;
256:
257: return NGX_DECLINED;
258: }
259:
260:
261: static void
262: ngx_http_realip_cleanup(void *data)
263: {
264: ngx_http_realip_ctx_t *ctx = data;
265:
266: ngx_connection_t *c;
267:
268: c = ctx->connection;
269:
270: c->sockaddr = ctx->sockaddr;
271: c->socklen = ctx->socklen;
272: c->addr_text = ctx->addr_text;
273: }
274:
275:
276: static char *
277: ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
278: {
279: ngx_http_realip_loc_conf_t *rlcf = conf;
280:
281: ngx_int_t rc;
282: ngx_str_t *value;
283: ngx_cidr_t *cidr;
284:
285: value = cf->args->elts;
286:
287: if (rlcf->from == NULL) {
288: rlcf->from = ngx_array_create(cf->pool, 2,
289: sizeof(ngx_cidr_t));
290: if (rlcf->from == NULL) {
291: return NGX_CONF_ERROR;
292: }
293: }
294:
295: cidr = ngx_array_push(rlcf->from);
296: if (cidr == NULL) {
297: return NGX_CONF_ERROR;
298: }
299:
300: #if (NGX_HAVE_UNIX_DOMAIN)
301:
302: if (ngx_strcmp(value[1].data, "unix:") == 0) {
303: cidr->family = AF_UNIX;
304: return NGX_CONF_OK;
305: }
306:
307: #endif
308:
309: rc = ngx_ptocidr(&value[1], cidr);
310:
311: if (rc == NGX_ERROR) {
312: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
313: &value[1]);
314: return NGX_CONF_ERROR;
315: }
316:
317: if (rc == NGX_DONE) {
318: ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
319: "low address bits of %V are meaningless", &value[1]);
320: }
321:
322: return NGX_CONF_OK;
323: }
324:
325:
326: static char *
327: ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
328: {
329: ngx_http_realip_loc_conf_t *rlcf = conf;
330:
331: ngx_str_t *value;
332:
333: value = cf->args->elts;
334:
335: if (ngx_strcmp(value[1].data, "X-Real-IP") == 0) {
336: rlcf->type = NGX_HTTP_REALIP_XREALIP;
337: return NGX_CONF_OK;
338: }
339:
340: if (ngx_strcmp(value[1].data, "X-Forwarded-For") == 0) {
341: rlcf->type = NGX_HTTP_REALIP_XFWD;
342: return NGX_CONF_OK;
343: }
344:
345: rlcf->type = NGX_HTTP_REALIP_HEADER;
346: rlcf->hash = ngx_hash_strlow(value[1].data, value[1].data, value[1].len);
347: rlcf->header = value[1];
348:
349: return NGX_CONF_OK;
350: }
351:
352:
353: static void *
354: ngx_http_realip_create_loc_conf(ngx_conf_t *cf)
355: {
356: ngx_http_realip_loc_conf_t *conf;
357:
358: conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_realip_loc_conf_t));
359: if (conf == NULL) {
360: return NULL;
361: }
362:
363: /*
364: * set by ngx_pcalloc():
365: *
366: * conf->from = NULL;
367: * conf->hash = 0;
368: * conf->header = { 0, NULL };
369: */
370:
371: conf->type = NGX_CONF_UNSET_UINT;
372: conf->recursive = NGX_CONF_UNSET;
373:
374: return conf;
375: }
376:
377:
378: static char *
379: ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
380: {
381: ngx_http_realip_loc_conf_t *prev = parent;
382: ngx_http_realip_loc_conf_t *conf = child;
383:
384: if (conf->from == NULL) {
385: conf->from = prev->from;
386: }
387:
388: ngx_conf_merge_uint_value(conf->type, prev->type, NGX_HTTP_REALIP_XREALIP);
389: ngx_conf_merge_value(conf->recursive, prev->recursive, 0);
390:
391: if (conf->header.len == 0) {
392: conf->hash = prev->hash;
393: conf->header = prev->header;
394: }
395:
396: return NGX_CONF_OK;
397: }
398:
399:
400: static ngx_int_t
401: ngx_http_realip_init(ngx_conf_t *cf)
402: {
403: ngx_http_handler_pt *h;
404: ngx_http_core_main_conf_t *cmcf;
405:
406: cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
407:
408: h = ngx_array_push(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers);
409: if (h == NULL) {
410: return NGX_ERROR;
411: }
412:
413: *h = ngx_http_realip_handler;
414:
415: h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
416: if (h == NULL) {
417: return NGX_ERROR;
418: }
419:
420: *h = ngx_http_realip_handler;
421:
422: return NGX_OK;
423: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>