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>