~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/modules/ngx_http_realip_module.c

Version: ~ [ nginx-1.4.1 ] ~ [ nginx-1.5.0 ] ~

  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 }
424 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.