Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_stream.h>
0011 
0012 
0013 typedef struct {
0014     ngx_array_t       *from;     /* array of ngx_cidr_t */
0015 } ngx_stream_realip_srv_conf_t;
0016 
0017 
0018 typedef struct {
0019     struct sockaddr   *sockaddr;
0020     socklen_t          socklen;
0021     ngx_str_t          addr_text;
0022 } ngx_stream_realip_ctx_t;
0023 
0024 
0025 static ngx_int_t ngx_stream_realip_handler(ngx_stream_session_t *s);
0026 static ngx_int_t ngx_stream_realip_set_addr(ngx_stream_session_t *s,
0027     ngx_addr_t *addr);
0028 static char *ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
0029     void *conf);
0030 static void *ngx_stream_realip_create_srv_conf(ngx_conf_t *cf);
0031 static char *ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent,
0032     void *child);
0033 static ngx_int_t ngx_stream_realip_add_variables(ngx_conf_t *cf);
0034 static ngx_int_t ngx_stream_realip_init(ngx_conf_t *cf);
0035 
0036 
0037 static ngx_int_t ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s,
0038     ngx_stream_variable_value_t *v, uintptr_t data);
0039 static ngx_int_t ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s,
0040     ngx_stream_variable_value_t *v, uintptr_t data);
0041 
0042 
0043 static ngx_command_t  ngx_stream_realip_commands[] = {
0044 
0045     { ngx_string("set_real_ip_from"),
0046       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0047       ngx_stream_realip_from,
0048       NGX_STREAM_SRV_CONF_OFFSET,
0049       0,
0050       NULL },
0051 
0052       ngx_null_command
0053 };
0054 
0055 
0056 static ngx_stream_module_t  ngx_stream_realip_module_ctx = {
0057     ngx_stream_realip_add_variables,       /* preconfiguration */
0058     ngx_stream_realip_init,                /* postconfiguration */
0059 
0060     NULL,                                  /* create main configuration */
0061     NULL,                                  /* init main configuration */
0062 
0063     ngx_stream_realip_create_srv_conf,     /* create server configuration */
0064     ngx_stream_realip_merge_srv_conf       /* merge server configuration */
0065 };
0066 
0067 
0068 ngx_module_t  ngx_stream_realip_module = {
0069     NGX_MODULE_V1,
0070     &ngx_stream_realip_module_ctx,         /* module context */
0071     ngx_stream_realip_commands,            /* module directives */
0072     NGX_STREAM_MODULE,                     /* module type */
0073     NULL,                                  /* init master */
0074     NULL,                                  /* init module */
0075     NULL,                                  /* init process */
0076     NULL,                                  /* init thread */
0077     NULL,                                  /* exit thread */
0078     NULL,                                  /* exit process */
0079     NULL,                                  /* exit master */
0080     NGX_MODULE_V1_PADDING
0081 };
0082 
0083 
0084 static ngx_stream_variable_t  ngx_stream_realip_vars[] = {
0085 
0086     { ngx_string("realip_remote_addr"), NULL,
0087       ngx_stream_realip_remote_addr_variable, 0, 0, 0 },
0088 
0089     { ngx_string("realip_remote_port"), NULL,
0090       ngx_stream_realip_remote_port_variable, 0, 0, 0 },
0091 
0092     { ngx_null_string, NULL, NULL, 0, 0, 0 }
0093 };
0094 
0095 
0096 static ngx_int_t
0097 ngx_stream_realip_handler(ngx_stream_session_t *s)
0098 {
0099     ngx_addr_t                     addr;
0100     ngx_connection_t              *c;
0101     ngx_stream_realip_srv_conf_t  *rscf;
0102 
0103     rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_realip_module);
0104 
0105     if (rscf->from == NULL) {
0106         return NGX_DECLINED;
0107     }
0108 
0109     c = s->connection;
0110 
0111     if (c->proxy_protocol_addr.len == 0) {
0112         return NGX_DECLINED;
0113     }
0114 
0115     if (ngx_cidr_match(c->sockaddr, rscf->from) != NGX_OK) {
0116         return NGX_DECLINED;
0117     }
0118 
0119     if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol_addr.data,
0120                        c->proxy_protocol_addr.len)
0121         != NGX_OK)
0122     {
0123         return NGX_DECLINED;
0124     }
0125 
0126     ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port);
0127 
0128     return ngx_stream_realip_set_addr(s, &addr);
0129 }
0130 
0131 
0132 static ngx_int_t
0133 ngx_stream_realip_set_addr(ngx_stream_session_t *s, ngx_addr_t *addr)
0134 {
0135     size_t                    len;
0136     u_char                   *p;
0137     u_char                    text[NGX_SOCKADDR_STRLEN];
0138     ngx_connection_t         *c;
0139     ngx_stream_realip_ctx_t  *ctx;
0140 
0141     c = s->connection;
0142 
0143     ctx = ngx_palloc(c->pool, sizeof(ngx_stream_realip_ctx_t));
0144     if (ctx == NULL) {
0145         return NGX_ERROR;
0146     }
0147 
0148     len = ngx_sock_ntop(addr->sockaddr, addr->socklen, text,
0149                         NGX_SOCKADDR_STRLEN, 0);
0150     if (len == 0) {
0151         return NGX_ERROR;
0152     }
0153 
0154     p = ngx_pnalloc(c->pool, len);
0155     if (p == NULL) {
0156         return NGX_ERROR;
0157     }
0158 
0159     ngx_memcpy(p, text, len);
0160 
0161     ngx_stream_set_ctx(s, ctx, ngx_stream_realip_module);
0162 
0163     ctx->sockaddr = c->sockaddr;
0164     ctx->socklen = c->socklen;
0165     ctx->addr_text = c->addr_text;
0166 
0167     c->sockaddr = addr->sockaddr;
0168     c->socklen = addr->socklen;
0169     c->addr_text.len = len;
0170     c->addr_text.data = p;
0171 
0172     return NGX_DECLINED;
0173 }
0174 
0175 
0176 static char *
0177 ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0178 {
0179     ngx_stream_realip_srv_conf_t *rscf = conf;
0180 
0181     ngx_int_t                rc;
0182     ngx_str_t               *value;
0183     ngx_cidr_t              *cidr;
0184 
0185     value = cf->args->elts;
0186 
0187     if (rscf->from == NULL) {
0188         rscf->from = ngx_array_create(cf->pool, 2,
0189                                       sizeof(ngx_cidr_t));
0190         if (rscf->from == NULL) {
0191             return NGX_CONF_ERROR;
0192         }
0193     }
0194 
0195     cidr = ngx_array_push(rscf->from);
0196     if (cidr == NULL) {
0197         return NGX_CONF_ERROR;
0198     }
0199 
0200 #if (NGX_HAVE_UNIX_DOMAIN)
0201 
0202     if (ngx_strcmp(value[1].data, "unix:") == 0) {
0203         cidr->family = AF_UNIX;
0204         return NGX_CONF_OK;
0205     }
0206 
0207 #endif
0208 
0209     rc = ngx_ptocidr(&value[1], cidr);
0210 
0211     if (rc == NGX_ERROR) {
0212         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
0213                            &value[1]);
0214         return NGX_CONF_ERROR;
0215     }
0216 
0217     if (rc == NGX_DONE) {
0218         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
0219                            "low address bits of %V are meaningless", &value[1]);
0220     }
0221 
0222     return NGX_CONF_OK;
0223 }
0224 
0225 
0226 static void *
0227 ngx_stream_realip_create_srv_conf(ngx_conf_t *cf)
0228 {
0229     ngx_stream_realip_srv_conf_t  *conf;
0230 
0231     conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_realip_srv_conf_t));
0232     if (conf == NULL) {
0233         return NULL;
0234     }
0235 
0236     /*
0237      * set by ngx_pcalloc():
0238      *
0239      *     conf->from = NULL;
0240      */
0241 
0242     return conf;
0243 }
0244 
0245 
0246 static char *
0247 ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
0248 {
0249     ngx_stream_realip_srv_conf_t *prev = parent;
0250     ngx_stream_realip_srv_conf_t *conf = child;
0251 
0252     if (conf->from == NULL) {
0253         conf->from = prev->from;
0254     }
0255 
0256     return NGX_CONF_OK;
0257 }
0258 
0259 
0260 static ngx_int_t
0261 ngx_stream_realip_add_variables(ngx_conf_t *cf)
0262 {
0263     ngx_stream_variable_t  *var, *v;
0264 
0265     for (v = ngx_stream_realip_vars; v->name.len; v++) {
0266         var = ngx_stream_add_variable(cf, &v->name, v->flags);
0267         if (var == NULL) {
0268             return NGX_ERROR;
0269         }
0270 
0271         var->get_handler = v->get_handler;
0272         var->data = v->data;
0273     }
0274 
0275     return NGX_OK;
0276 }
0277 
0278 
0279 static ngx_int_t
0280 ngx_stream_realip_init(ngx_conf_t *cf)
0281 {
0282     ngx_stream_handler_pt        *h;
0283     ngx_stream_core_main_conf_t  *cmcf;
0284 
0285     cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
0286 
0287     h = ngx_array_push(&cmcf->phases[NGX_STREAM_POST_ACCEPT_PHASE].handlers);
0288     if (h == NULL) {
0289         return NGX_ERROR;
0290     }
0291 
0292     *h = ngx_stream_realip_handler;
0293 
0294     return NGX_OK;
0295 }
0296 
0297 
0298 static ngx_int_t
0299 ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s,
0300     ngx_stream_variable_value_t *v, uintptr_t data)
0301 {
0302     ngx_str_t                *addr_text;
0303     ngx_stream_realip_ctx_t  *ctx;
0304 
0305     ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module);
0306 
0307     addr_text = ctx ? &ctx->addr_text : &s->connection->addr_text;
0308 
0309     v->len = addr_text->len;
0310     v->valid = 1;
0311     v->no_cacheable = 0;
0312     v->not_found = 0;
0313     v->data = addr_text->data;
0314 
0315     return NGX_OK;
0316 }
0317 
0318 
0319 static ngx_int_t
0320 ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s,
0321     ngx_stream_variable_value_t *v, uintptr_t data)
0322 {
0323     ngx_uint_t                port;
0324     struct sockaddr          *sa;
0325     ngx_stream_realip_ctx_t  *ctx;
0326 
0327     ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module);
0328 
0329     sa = ctx ? ctx->sockaddr : s->connection->sockaddr;
0330 
0331     v->len = 0;
0332     v->valid = 1;
0333     v->no_cacheable = 0;
0334     v->not_found = 0;
0335 
0336     v->data = ngx_pnalloc(s->connection->pool, sizeof("65535") - 1);
0337     if (v->data == NULL) {
0338         return NGX_ERROR;
0339     }
0340 
0341     port = ngx_inet_get_port(sa);
0342 
0343     if (port > 0 && port < 65536) {
0344         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
0345     }
0346 
0347     return NGX_OK;
0348 }