Mercurial > hg > nginx
comparison src/stream/ngx_stream_realip_module.c @ 6684:9cac11efb205
Stream: realip module.
author | Dmitry Volyntsev <xeioex@nginx.com> |
---|---|
date | Thu, 01 Sep 2016 14:45:33 +0300 |
parents | src/http/modules/ngx_http_realip_module.c@6b1b8c4b7a95 |
children | 3908156a51fa |
comparison
equal
deleted
inserted
replaced
6683:b802b7e1d9bc | 6684:9cac11efb205 |
---|---|
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_stream.h> | |
11 | |
12 | |
13 typedef struct { | |
14 ngx_array_t *from; /* array of ngx_cidr_t */ | |
15 } ngx_stream_realip_srv_conf_t; | |
16 | |
17 | |
18 typedef struct { | |
19 struct sockaddr *sockaddr; | |
20 socklen_t socklen; | |
21 ngx_str_t addr_text; | |
22 } ngx_stream_realip_ctx_t; | |
23 | |
24 | |
25 static ngx_int_t ngx_stream_realip_handler(ngx_stream_session_t *s); | |
26 static ngx_int_t ngx_stream_realip_set_addr(ngx_stream_session_t *s, | |
27 ngx_addr_t *addr); | |
28 static char *ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, | |
29 void *conf); | |
30 static void *ngx_stream_realip_create_srv_conf(ngx_conf_t *cf); | |
31 static char *ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, | |
32 void *child); | |
33 static ngx_int_t ngx_stream_realip_add_variables(ngx_conf_t *cf); | |
34 static ngx_int_t ngx_stream_realip_init(ngx_conf_t *cf); | |
35 | |
36 | |
37 static ngx_int_t ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s, | |
38 ngx_stream_variable_value_t *v, uintptr_t data); | |
39 static ngx_int_t ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s, | |
40 ngx_stream_variable_value_t *v, uintptr_t data); | |
41 | |
42 | |
43 static ngx_command_t ngx_stream_realip_commands[] = { | |
44 | |
45 { ngx_string("set_real_ip_from"), | |
46 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, | |
47 ngx_stream_realip_from, | |
48 NGX_STREAM_SRV_CONF_OFFSET, | |
49 0, | |
50 NULL }, | |
51 | |
52 ngx_null_command | |
53 }; | |
54 | |
55 | |
56 static ngx_stream_module_t ngx_stream_realip_module_ctx = { | |
57 ngx_stream_realip_add_variables, /* preconfiguration */ | |
58 ngx_stream_realip_init, /* postconfiguration */ | |
59 | |
60 NULL, /* create main configuration */ | |
61 NULL, /* init main configuration */ | |
62 | |
63 ngx_stream_realip_create_srv_conf, /* create server configuration */ | |
64 ngx_stream_realip_merge_srv_conf /* merge server configuration */ | |
65 }; | |
66 | |
67 | |
68 ngx_module_t ngx_stream_realip_module = { | |
69 NGX_MODULE_V1, | |
70 &ngx_stream_realip_module_ctx, /* module context */ | |
71 ngx_stream_realip_commands, /* module directives */ | |
72 NGX_STREAM_MODULE, /* module type */ | |
73 NULL, /* init master */ | |
74 NULL, /* init module */ | |
75 NULL, /* init process */ | |
76 NULL, /* init thread */ | |
77 NULL, /* exit thread */ | |
78 NULL, /* exit process */ | |
79 NULL, /* exit master */ | |
80 NGX_MODULE_V1_PADDING | |
81 }; | |
82 | |
83 | |
84 static ngx_stream_variable_t ngx_stream_realip_vars[] = { | |
85 | |
86 { ngx_string("realip_remote_addr"), NULL, | |
87 ngx_stream_realip_remote_addr_variable, 0, 0, 0 }, | |
88 | |
89 { ngx_string("realip_remote_port"), NULL, | |
90 ngx_stream_realip_remote_port_variable, 0, 0, 0 }, | |
91 | |
92 { ngx_null_string, NULL, NULL, 0, 0, 0 } | |
93 }; | |
94 | |
95 | |
96 static ngx_int_t | |
97 ngx_stream_realip_handler(ngx_stream_session_t *s) | |
98 { | |
99 ngx_addr_t addr; | |
100 ngx_connection_t *c; | |
101 ngx_stream_realip_srv_conf_t *rscf; | |
102 | |
103 rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_realip_module); | |
104 | |
105 if (rscf->from == NULL) { | |
106 return NGX_DECLINED; | |
107 } | |
108 | |
109 c = s->connection; | |
110 | |
111 if (c->proxy_protocol_addr.len == 0) { | |
112 return NGX_DECLINED; | |
113 } | |
114 | |
115 if (ngx_cidr_match(c->sockaddr, rscf->from) != NGX_OK) { | |
116 return NGX_DECLINED; | |
117 } | |
118 | |
119 if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol_addr.data, | |
120 c->proxy_protocol_addr.len) | |
121 != NGX_OK) | |
122 { | |
123 return NGX_DECLINED; | |
124 } | |
125 | |
126 ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port); | |
127 | |
128 return ngx_stream_realip_set_addr(s, &addr); | |
129 } | |
130 | |
131 | |
132 static ngx_int_t | |
133 ngx_stream_realip_set_addr(ngx_stream_session_t *s, ngx_addr_t *addr) | |
134 { | |
135 size_t len; | |
136 u_char *p; | |
137 u_char text[NGX_SOCKADDR_STRLEN]; | |
138 ngx_connection_t *c; | |
139 ngx_stream_realip_ctx_t *ctx; | |
140 | |
141 c = s->connection; | |
142 | |
143 ctx = ngx_palloc(c->pool, sizeof(ngx_stream_realip_ctx_t)); | |
144 if (ctx == NULL) { | |
145 return NGX_ERROR; | |
146 } | |
147 | |
148 len = ngx_sock_ntop(addr->sockaddr, addr->socklen, text, | |
149 NGX_SOCKADDR_STRLEN, 0); | |
150 if (len == 0) { | |
151 return NGX_ERROR; | |
152 } | |
153 | |
154 p = ngx_pnalloc(c->pool, len); | |
155 if (p == NULL) { | |
156 return NGX_ERROR; | |
157 } | |
158 | |
159 ngx_memcpy(p, text, len); | |
160 | |
161 ngx_stream_set_ctx(s, ctx, ngx_stream_realip_module); | |
162 | |
163 ctx->sockaddr = c->sockaddr; | |
164 ctx->socklen = c->socklen; | |
165 ctx->addr_text = c->addr_text; | |
166 | |
167 c->sockaddr = addr->sockaddr; | |
168 c->socklen = addr->socklen; | |
169 c->addr_text.len = len; | |
170 c->addr_text.data = p; | |
171 | |
172 return NGX_DECLINED; | |
173 } | |
174 | |
175 | |
176 static char * | |
177 ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
178 { | |
179 ngx_stream_realip_srv_conf_t *rscf = conf; | |
180 | |
181 ngx_int_t rc; | |
182 ngx_str_t *value; | |
183 ngx_cidr_t *cidr; | |
184 | |
185 value = cf->args->elts; | |
186 | |
187 if (rscf->from == NULL) { | |
188 rscf->from = ngx_array_create(cf->pool, 2, | |
189 sizeof(ngx_cidr_t)); | |
190 if (rscf->from == NULL) { | |
191 return NGX_CONF_ERROR; | |
192 } | |
193 } | |
194 | |
195 cidr = ngx_array_push(rscf->from); | |
196 if (cidr == NULL) { | |
197 return NGX_CONF_ERROR; | |
198 } | |
199 | |
200 #if (NGX_HAVE_UNIX_DOMAIN) | |
201 | |
202 if (ngx_strcmp(value[1].data, "unix:") == 0) { | |
203 cidr->family = AF_UNIX; | |
204 return NGX_CONF_OK; | |
205 } | |
206 | |
207 #endif | |
208 | |
209 rc = ngx_ptocidr(&value[1], cidr); | |
210 | |
211 if (rc == NGX_ERROR) { | |
212 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", | |
213 &value[1]); | |
214 return NGX_CONF_ERROR; | |
215 } | |
216 | |
217 if (rc == NGX_DONE) { | |
218 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
219 "low address bits of %V are meaningless", &value[1]); | |
220 } | |
221 | |
222 return NGX_CONF_OK; | |
223 } | |
224 | |
225 | |
226 static void * | |
227 ngx_stream_realip_create_srv_conf(ngx_conf_t *cf) | |
228 { | |
229 ngx_stream_realip_srv_conf_t *conf; | |
230 | |
231 conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_realip_srv_conf_t)); | |
232 if (conf == NULL) { | |
233 return NULL; | |
234 } | |
235 | |
236 /* | |
237 * set by ngx_pcalloc(): | |
238 * | |
239 * conf->from = NULL; | |
240 */ | |
241 | |
242 return conf; | |
243 } | |
244 | |
245 | |
246 static char * | |
247 ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) | |
248 { | |
249 ngx_stream_realip_srv_conf_t *prev = parent; | |
250 ngx_stream_realip_srv_conf_t *conf = child; | |
251 | |
252 if (conf->from == NULL) { | |
253 conf->from = prev->from; | |
254 } | |
255 | |
256 return NGX_CONF_OK; | |
257 } | |
258 | |
259 | |
260 static ngx_int_t | |
261 ngx_stream_realip_add_variables(ngx_conf_t *cf) | |
262 { | |
263 ngx_stream_variable_t *var, *v; | |
264 | |
265 for (v = ngx_stream_realip_vars; v->name.len; v++) { | |
266 var = ngx_stream_add_variable(cf, &v->name, v->flags); | |
267 if (var == NULL) { | |
268 return NGX_ERROR; | |
269 } | |
270 | |
271 var->get_handler = v->get_handler; | |
272 var->data = v->data; | |
273 } | |
274 | |
275 return NGX_OK; | |
276 } | |
277 | |
278 | |
279 static ngx_int_t | |
280 ngx_stream_realip_init(ngx_conf_t *cf) | |
281 { | |
282 ngx_stream_core_main_conf_t *cmcf; | |
283 | |
284 cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); | |
285 | |
286 cmcf->realip_handler = ngx_stream_realip_handler; | |
287 | |
288 return NGX_OK; | |
289 } | |
290 | |
291 | |
292 static ngx_int_t | |
293 ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s, | |
294 ngx_stream_variable_value_t *v, uintptr_t data) | |
295 { | |
296 ngx_str_t *addr_text; | |
297 ngx_stream_realip_ctx_t *ctx; | |
298 | |
299 ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module); | |
300 | |
301 addr_text = ctx ? &ctx->addr_text : &s->connection->addr_text; | |
302 | |
303 v->len = addr_text->len; | |
304 v->valid = 1; | |
305 v->no_cacheable = 0; | |
306 v->not_found = 0; | |
307 v->data = addr_text->data; | |
308 | |
309 return NGX_OK; | |
310 } | |
311 | |
312 | |
313 static ngx_int_t | |
314 ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s, | |
315 ngx_stream_variable_value_t *v, uintptr_t data) | |
316 { | |
317 ngx_uint_t port; | |
318 struct sockaddr *sa; | |
319 ngx_stream_realip_ctx_t *ctx; | |
320 | |
321 ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module); | |
322 | |
323 sa = ctx ? ctx->sockaddr : s->connection->sockaddr; | |
324 | |
325 v->len = 0; | |
326 v->valid = 1; | |
327 v->no_cacheable = 0; | |
328 v->not_found = 0; | |
329 | |
330 v->data = ngx_pnalloc(s->connection->pool, sizeof("65535") - 1); | |
331 if (v->data == NULL) { | |
332 return NGX_ERROR; | |
333 } | |
334 | |
335 port = ngx_inet_get_port(sa); | |
336 | |
337 if (port > 0 && port < 65536) { | |
338 v->len = ngx_sprintf(v->data, "%ui", port) - v->data; | |
339 } | |
340 | |
341 return NGX_OK; | |
342 } |