Skip to content

Commit 02f3dcb

Browse files
author
ru
committed
New function ngx_http_get_forwarded_addr() to look up real client address.
On input it takes an original address, string in the X-Forwarded-For format and its length, list of trusted proxies, and a flag indicating to perform the recursive search. On output it returns NGX_OK and the "deepest" valid address in a chain, or NGX_DECLINED. It supports AF_INET and AF_INET6. Additionally, original address and/or proxy may be specified as AF_UNIX.
1 parent 43afe3b commit 02f3dcb

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

src/http/ngx_http_core_module.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2699,6 +2699,102 @@ ngx_http_set_disable_symlinks(ngx_http_request_t *r,
26992699
}
27002700

27012701

2702+
ngx_int_t
2703+
ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
2704+
u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive)
2705+
{
2706+
u_char *p;
2707+
in_addr_t *inaddr;
2708+
ngx_addr_t paddr;
2709+
ngx_cidr_t *cidr;
2710+
ngx_uint_t family, i;
2711+
#if (NGX_HAVE_INET6)
2712+
ngx_uint_t n;
2713+
struct in6_addr *inaddr6;
2714+
#endif
2715+
2716+
family = addr->sockaddr->sa_family;
2717+
2718+
if (family == AF_INET) {
2719+
inaddr = &((struct sockaddr_in *) addr->sockaddr)->sin_addr.s_addr;
2720+
}
2721+
2722+
#if (NGX_HAVE_INET6)
2723+
else if (family == AF_INET6) {
2724+
inaddr6 = &((struct sockaddr_in6 *) addr->sockaddr)->sin6_addr;
2725+
2726+
if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
2727+
family = AF_INET;
2728+
inaddr = (in_addr_t *) &inaddr6->s6_addr[12];
2729+
}
2730+
}
2731+
#endif
2732+
2733+
for (cidr = proxies->elts, i = 0; i < proxies->nelts; i++) {
2734+
if (cidr[i].family != family) {
2735+
goto next;
2736+
}
2737+
2738+
switch (family) {
2739+
2740+
#if (NGX_HAVE_INET6)
2741+
case AF_INET6:
2742+
for (n = 0; n < 16; n++) {
2743+
if ((inaddr6->s6_addr[n] & cidr[i].u.in6.mask.s6_addr[n])
2744+
!= cidr[i].u.in6.addr.s6_addr[n])
2745+
{
2746+
goto next;
2747+
}
2748+
}
2749+
break;
2750+
#endif
2751+
2752+
#if (NGX_HAVE_UNIX_DOMAIN)
2753+
case AF_UNIX:
2754+
break;
2755+
#endif
2756+
2757+
default: /* AF_INET */
2758+
if ((*inaddr & cidr[i].u.in.mask) != cidr[i].u.in.addr) {
2759+
goto next;
2760+
}
2761+
break;
2762+
}
2763+
2764+
for (p = xff + xfflen - 1; p > xff; p--, xfflen--) {
2765+
if (*p != ' ' && *p != ',') {
2766+
break;
2767+
}
2768+
}
2769+
2770+
for ( /* void */ ; p > xff; p--) {
2771+
if (*p == ' ' || *p == ',') {
2772+
p++;
2773+
break;
2774+
}
2775+
}
2776+
2777+
if (ngx_parse_addr(r->pool, &paddr, p, xfflen - (p - xff)) != NGX_OK) {
2778+
return NGX_DECLINED;
2779+
}
2780+
2781+
*addr = paddr;
2782+
2783+
if (recursive && p > xff) {
2784+
(void) ngx_http_get_forwarded_addr(r, addr, xff, p - 1 - xff,
2785+
proxies, 1);
2786+
}
2787+
2788+
return NGX_OK;
2789+
2790+
next:
2791+
continue;
2792+
}
2793+
2794+
return NGX_DECLINED;
2795+
}
2796+
2797+
27022798
static char *
27032799
ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
27042800
{

src/http/ngx_http_core_module.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@ ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *chain);
513513
ngx_int_t ngx_http_set_disable_symlinks(ngx_http_request_t *r,
514514
ngx_http_core_loc_conf_t *clcf, ngx_str_t *path, ngx_open_file_info_t *of);
515515

516+
ngx_int_t ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
517+
u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive);
518+
516519

517520
extern ngx_module_t ngx_http_core_module;
518521

0 commit comments

Comments
 (0)