3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
16 ngx_uint_t deny
; /* unsigned deny:1; */
17 } ngx_http_access_rule_t
;
24 ngx_uint_t deny
; /* unsigned deny:1; */
25 } ngx_http_access_rule6_t
;
30 ngx_array_t
*rules
; /* array of ngx_http_access_rule_t */
32 ngx_array_t
*rules6
; /* array of ngx_http_access_rule6_t */
34 } ngx_http_access_loc_conf_t
;
37 static ngx_int_t
ngx_http_access_handler(ngx_http_request_t
*r
);
38 static ngx_int_t
ngx_http_access_inet(ngx_http_request_t
*r
,
39 ngx_http_access_loc_conf_t
*alcf
, in_addr_t addr
);
41 static ngx_int_t
ngx_http_access_inet6(ngx_http_request_t
*r
,
42 ngx_http_access_loc_conf_t
*alcf
, u_char
*p
);
44 static ngx_int_t
ngx_http_access_found(ngx_http_request_t
*r
, ngx_uint_t deny
);
45 static char *ngx_http_access_rule(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
47 static void *ngx_http_access_create_loc_conf(ngx_conf_t
*cf
);
48 static char *ngx_http_access_merge_loc_conf(ngx_conf_t
*cf
,
49 void *parent
, void *child
);
50 static ngx_int_t
ngx_http_access_init(ngx_conf_t
*cf
);
53 static ngx_command_t ngx_http_access_commands
[] = {
55 { ngx_string("allow"),
56 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_HTTP_LMT_CONF
59 NGX_HTTP_LOC_CONF_OFFSET
,
64 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_HTTP_LMT_CONF
67 NGX_HTTP_LOC_CONF_OFFSET
,
76 static ngx_http_module_t ngx_http_access_module_ctx
= {
77 NULL
, /* preconfiguration */
78 ngx_http_access_init
, /* postconfiguration */
80 NULL
, /* create main configuration */
81 NULL
, /* init main configuration */
83 NULL
, /* create server configuration */
84 NULL
, /* merge server configuration */
86 ngx_http_access_create_loc_conf
, /* create location configuration */
87 ngx_http_access_merge_loc_conf
/* merge location configuration */
91 ngx_module_t ngx_http_access_module
= {
93 &ngx_http_access_module_ctx
, /* module context */
94 ngx_http_access_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
108 ngx_http_access_handler(ngx_http_request_t
*r
)
110 struct sockaddr_in
*sin
;
111 ngx_http_access_loc_conf_t
*alcf
;
115 struct sockaddr_in6
*sin6
;
118 alcf
= ngx_http_get_module_loc_conf(r
, ngx_http_access_module
);
120 switch (r
->connection
->sockaddr
->sa_family
) {
124 sin
= (struct sockaddr_in
*) r
->connection
->sockaddr
;
125 return ngx_http_access_inet(r
, alcf
, sin
->sin_addr
.s_addr
);
132 sin6
= (struct sockaddr_in6
*) r
->connection
->sockaddr
;
133 p
= sin6
->sin6_addr
.s6_addr
;
135 if (alcf
->rules
&& IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)) {
140 return ngx_http_access_inet(r
, alcf
, htonl(addr
));
144 return ngx_http_access_inet6(r
, alcf
, p
);
155 ngx_http_access_inet(ngx_http_request_t
*r
, ngx_http_access_loc_conf_t
*alcf
,
159 ngx_http_access_rule_t
*rule
;
161 rule
= alcf
->rules
->elts
;
162 for (i
= 0; i
< alcf
->rules
->nelts
; i
++) {
164 ngx_log_debug3(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
165 "access: %08XD %08XD %08XD",
166 addr
, rule
[i
].mask
, rule
[i
].addr
);
168 if ((addr
& rule
[i
].mask
) == rule
[i
].addr
) {
169 return ngx_http_access_found(r
, rule
[i
].deny
);
180 ngx_http_access_inet6(ngx_http_request_t
*r
, ngx_http_access_loc_conf_t
*alcf
,
185 ngx_http_access_rule6_t
*rule6
;
187 rule6
= alcf
->rules6
->elts
;
188 for (i
= 0; i
< alcf
->rules6
->nelts
; i
++) {
193 u_char ct
[NGX_INET6_ADDRSTRLEN
];
194 u_char mt
[NGX_INET6_ADDRSTRLEN
];
195 u_char at
[NGX_INET6_ADDRSTRLEN
];
197 cl
= ngx_inet6_ntop(p
, ct
, NGX_INET6_ADDRSTRLEN
);
198 ml
= ngx_inet6_ntop(rule6
[i
].mask
.s6_addr
, mt
, NGX_INET6_ADDRSTRLEN
);
199 al
= ngx_inet6_ntop(rule6
[i
].addr
.s6_addr
, at
, NGX_INET6_ADDRSTRLEN
);
201 ngx_log_debug6(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
202 "access: %*s %*s %*s", cl
, ct
, ml
, mt
, al
, at
);
206 for (n
= 0; n
< 16; n
++) {
207 if ((p
[n
] & rule6
[i
].mask
.s6_addr
[n
]) != rule6
[i
].addr
.s6_addr
[n
]) {
212 return ngx_http_access_found(r
, rule6
[i
].deny
);
225 ngx_http_access_found(ngx_http_request_t
*r
, ngx_uint_t deny
)
227 ngx_http_core_loc_conf_t
*clcf
;
230 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
232 if (clcf
->satisfy
== NGX_HTTP_SATISFY_ALL
) {
233 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
234 "access forbidden by rule");
237 return NGX_HTTP_FORBIDDEN
;
245 ngx_http_access_rule(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
247 ngx_http_access_loc_conf_t
*alcf
= conf
;
253 ngx_http_access_rule_t
*rule
;
255 ngx_http_access_rule6_t
*rule6
;
258 ngx_memzero(&cidr
, sizeof(ngx_cidr_t
));
260 value
= cf
->args
->elts
;
262 all
= (value
[1].len
== 3 && ngx_strcmp(value
[1].data
, "all") == 0);
266 rc
= ngx_ptocidr(&value
[1], &cidr
);
268 if (rc
== NGX_ERROR
) {
269 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
270 "invalid parameter \"%V\"", &value
[1]);
271 return NGX_CONF_ERROR
;
274 if (rc
== NGX_DONE
) {
275 ngx_conf_log_error(NGX_LOG_WARN
, cf
, 0,
276 "low address bits of %V are meaningless", &value
[1]);
280 switch (cidr
.family
) {
286 if (alcf
->rules6
== NULL
) {
287 alcf
->rules6
= ngx_array_create(cf
->pool
, 4,
288 sizeof(ngx_http_access_rule6_t
));
289 if (alcf
->rules6
== NULL
) {
290 return NGX_CONF_ERROR
;
294 rule6
= ngx_array_push(alcf
->rules6
);
296 return NGX_CONF_ERROR
;
299 rule6
->mask
= cidr
.u
.in6
.mask
;
300 rule6
->addr
= cidr
.u
.in6
.addr
;
301 rule6
->deny
= (value
[0].data
[0] == 'd') ? 1 : 0;
307 /* "all" passes through */
310 default: /* AF_INET */
312 if (alcf
->rules
== NULL
) {
313 alcf
->rules
= ngx_array_create(cf
->pool
, 4,
314 sizeof(ngx_http_access_rule_t
));
315 if (alcf
->rules
== NULL
) {
316 return NGX_CONF_ERROR
;
320 rule
= ngx_array_push(alcf
->rules
);
322 return NGX_CONF_ERROR
;
325 rule
->mask
= cidr
.u
.in
.mask
;
326 rule
->addr
= cidr
.u
.in
.addr
;
327 rule
->deny
= (value
[0].data
[0] == 'd') ? 1 : 0;
335 ngx_http_access_create_loc_conf(ngx_conf_t
*cf
)
337 ngx_http_access_loc_conf_t
*conf
;
339 conf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_access_loc_conf_t
));
349 ngx_http_access_merge_loc_conf(ngx_conf_t
*cf
, void *parent
, void *child
)
351 ngx_http_access_loc_conf_t
*prev
= parent
;
352 ngx_http_access_loc_conf_t
*conf
= child
;
356 if (conf
->rules
== NULL
&& conf
->rules6
== NULL
) {
357 conf
->rules
= prev
->rules
;
358 conf
->rules6
= prev
->rules6
;
363 if (conf
->rules
== NULL
) {
364 conf
->rules
= prev
->rules
;
374 ngx_http_access_init(ngx_conf_t
*cf
)
376 ngx_http_handler_pt
*h
;
377 ngx_http_core_main_conf_t
*cmcf
;
379 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
381 h
= ngx_array_push(&cmcf
->phases
[NGX_HTTP_ACCESS_PHASE
].handlers
);
386 *h
= ngx_http_access_handler
;