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

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

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

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

~ [ 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.