IPv6 & IPv4 backend with proxy_bind
SplitIce
mat999 at gmail.com
Mon Dec 9 11:33:29 UTC 2013
Im not sure that patch would suit my needs, simply because most of the time
I am matching on the upstream address only and need it to work regardless
of the port (i.e a regex match on just the IP component).
Perhaps your patch could be extended to support -
map $upstream_peer_addr $bind_addr {
127.0.0.1:8001 127.0.0.1;
127.0.0.2 <http://127.0.0.1:8002/> 127.0.0.1;
[::1]:8003 ::1;
}
Where 127.0.0.2 would match 127.0.0.2:*
I certainly like that it doesn't require a conversion to string.
I have also attached V2 of my patch (changes to the patch to remove windows
path style).
On Mon, Dec 9, 2013 at 8:59 PM, Ruslan Ermilov <ru at nginx.com> wrote:
> On Sat, Nov 23, 2013 at 12:15:28PM +1030, SplitIce wrote:
> > Attached is the patch,
> >
> > This is the first time I have created a variable or really done anything
> > inside the http request processing flow so feel free to let me know if
> > there is a better way to do something or if I have any edge cases.
> >
> > This patch provides a $upstream_connecting variable which contains the IP
> > address and port of the upstream being connected. If there is no
> upstream,
> > it will return "-" my understanding is this may happen if the upstream is
> > DNS resolved (untested). There may be a better way of doing this?
> >
> > This should be used in a config like the following -
> > map $upstream_connecting $test {
> > ~^93\.184\.216\.119\: 192.168.2.40;
> > ~^192\.168\.2\.([0-9]+)\: 192.168.2.40;
> > }
> >
> > proxy_bind $test;
>
> I took a different approach. I've made "local" a peer's method,
> so the computation of the local address is delayed until it's
> actually needed. By that time, the peer address is already known.
>
> I've also patched "map" so it creates non-cacheable variables.
>
> This way, $upstream_peer_addr can be mapped into the local address:
>
> map $upstream_peer_addr $bind_addr {
> 127.0.0.1:8001 127.0.0.1;
> 127.0.0.1:8002 127.0.0.1;
> [::1]:8003 ::1;
> }
>
> server {
> ...
> location / {
> proxy_pass ...;
> proxy_bind $bind_addr;
> ...
> }
> }
>
> diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c
> --- a/src/event/ngx_event_connect.c
> +++ b/src/event/ngx_event_connect.c
> @@ -17,6 +17,7 @@ ngx_event_connect_peer(ngx_peer_connecti
> int rc;
> ngx_int_t event;
> ngx_err_t err;
> + ngx_addr_t *local;
> ngx_uint_t level;
> ngx_socket_t s;
> ngx_event_t *rev, *wev;
> @@ -67,9 +68,13 @@ ngx_event_connect_peer(ngx_peer_connecti
> }
>
> if (pc->local) {
> - if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) {
> + local = pc->local(pc, pc->data);
> +
> + if (local != NULL
> + && bind(s, local->sockaddr, local->socklen) == -1)
> + {
> ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno,
> - "bind(%V) failed", &pc->local->name);
> + "bind(%V) failed", &local->name);
>
> goto failed;
> }
> diff --git a/src/event/ngx_event_connect.h b/src/event/ngx_event_connect.h
> --- a/src/event/ngx_event_connect.h
> +++ b/src/event/ngx_event_connect.h
> @@ -25,6 +25,8 @@ typedef ngx_int_t (*ngx_event_get_peer_p
> void *data);
> typedef void (*ngx_event_free_peer_pt)(ngx_peer_connection_t *pc, void
> *data,
> ngx_uint_t state);
> +typedef ngx_addr_t *(*ngx_event_get_local_pt)(ngx_peer_connection_t *pc,
> + void *data);
> #if (NGX_SSL)
>
> typedef ngx_int_t (*ngx_event_set_peer_session_pt)(ngx_peer_connection_t
> *pc,
> @@ -45,6 +47,7 @@ struct ngx_peer_connection_s {
>
> ngx_event_get_peer_pt get;
> ngx_event_free_peer_pt free;
> + ngx_event_get_local_pt local;
> void *data;
>
> #if (NGX_SSL)
> @@ -56,8 +59,6 @@ struct ngx_peer_connection_s {
> ngx_atomic_t *lock;
> #endif
>
> - ngx_addr_t *local;
> -
> int rcvbuf;
>
> ngx_log_t *log;
> diff --git a/src/http/modules/ngx_http_map_module.c
> b/src/http/modules/ngx_http_map_module.c
> --- a/src/http/modules/ngx_http_map_module.c
> +++ b/src/http/modules/ngx_http_map_module.c
> @@ -477,7 +477,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command
> }
>
> var->valid = 1;
> - var->no_cacheable = 0;
> + var->no_cacheable = 1;
> var->not_found = 0;
>
> vp = ngx_array_push(&ctx->values_hash[key]);
> diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c
> b/src/http/modules/ngx_http_upstream_keepalive_module.c
> --- a/src/http/modules/ngx_http_upstream_keepalive_module.c
> +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c
> @@ -31,6 +31,7 @@ typedef struct {
>
> ngx_event_get_peer_pt original_get_peer;
> ngx_event_free_peer_pt original_free_peer;
> + ngx_event_get_local_pt original_get_local;
>
> #if (NGX_HTTP_SSL)
> ngx_event_set_peer_session_pt original_set_session;
> @@ -63,6 +64,9 @@ static void ngx_http_upstream_keepalive_
> static void ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev);
> static void ngx_http_upstream_keepalive_close(ngx_connection_t *c);
>
> +static ngx_addr_t *ngx_http_upstream_get_keepalive_local(
> + ngx_peer_connection_t *pc, void *data);
> +
>
> #if (NGX_HTTP_SSL)
> static ngx_int_t ngx_http_upstream_keepalive_set_session(
> @@ -189,10 +193,12 @@ ngx_http_upstream_init_keepalive_peer(ng
> kp->data = r->upstream->peer.data;
> kp->original_get_peer = r->upstream->peer.get;
> kp->original_free_peer = r->upstream->peer.free;
> + kp->original_get_local = r->upstream->peer.local;
>
> r->upstream->peer.data = kp;
> r->upstream->peer.get = ngx_http_upstream_get_keepalive_peer;
> r->upstream->peer.free = ngx_http_upstream_free_keepalive_peer;
> + r->upstream->peer.local = ngx_http_upstream_get_keepalive_local;
>
> #if (NGX_HTTP_SSL)
> kp->original_set_session = r->upstream->peer.set_session;
> @@ -430,6 +436,16 @@ ngx_http_upstream_keepalive_close(ngx_co
> }
>
>
> +static ngx_addr_t *
> +ngx_http_upstream_get_keepalive_local(ngx_peer_connection_t *pc,
> + void *data)
> +{
> + ngx_http_upstream_keepalive_peer_data_t *kp = data;
> +
> + return kp->original_get_local(pc, kp->data);
> +}
> +
> +
> #if (NGX_HTTP_SSL)
>
> static ngx_int_t
> diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
> --- a/src/http/ngx_http_upstream.c
> +++ b/src/http/ngx_http_upstream.c
> @@ -141,14 +141,13 @@ static ngx_int_t ngx_http_upstream_respo
> ngx_http_variable_value_t *v, uintptr_t data);
> static ngx_int_t ngx_http_upstream_response_length_variable(
> ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
> +static ngx_int_t ngx_http_upstream_peer_addr_variable(ngx_http_request_t
> *r,
> + ngx_http_variable_value_t *v, uintptr_t data);
>
> static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void
> *dummy);
> static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
> void *conf);
>
> -static ngx_addr_t *ngx_http_upstream_get_local(ngx_http_request_t *r,
> - ngx_http_upstream_local_t *local);
> -
> static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
> static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);
>
> @@ -366,6 +365,10 @@ static ngx_http_variable_t ngx_http_ups
>
> #endif
>
> + { ngx_string("upstream_peer_addr"), NULL,
> + ngx_http_upstream_peer_addr_variable, 0,
> + NGX_HTTP_VAR_NOCACHEABLE, 0 },
> +
> { ngx_null_string, NULL, NULL, 0, 0, 0 }
> };
>
> @@ -534,8 +537,6 @@ ngx_http_upstream_init_request(ngx_http_
> return;
> }
>
> - u->peer.local = ngx_http_upstream_get_local(r, u->conf->local);
> -
> clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
>
> u->output.alignment = clcf->directio_alignment;
> @@ -4509,6 +4510,25 @@ ngx_http_upstream_response_length_variab
> }
>
>
> +static ngx_int_t
> +ngx_http_upstream_peer_addr_variable(ngx_http_request_t *r,
> + ngx_http_variable_value_t *v, uintptr_t data)
> +{
> + if (r->upstream == NULL || r->upstream->peer.name == NULL) {
> + v->not_found = 1;
> + return NGX_OK;
> + }
> +
> + v->len = r->upstream->peer.name->len;
> + v->data = r->upstream->peer.name->data;
> + v->valid = 1;
> + v->no_cacheable = 0;
> + v->not_found = 0;
> +
> + return NGX_OK;
> +}
> +
> +
> ngx_int_t
> ngx_http_upstream_header_variable(ngx_http_request_t *r,
> ngx_http_variable_value_t *v, uintptr_t data)
> @@ -5022,53 +5042,6 @@ ngx_http_upstream_bind_set_slot(ngx_conf
> }
>
>
> -static ngx_addr_t *
> -ngx_http_upstream_get_local(ngx_http_request_t *r,
> - ngx_http_upstream_local_t *local)
> -{
> - ngx_int_t rc;
> - ngx_str_t val;
> - ngx_addr_t *addr;
> -
> - if (local == NULL) {
> - return NULL;
> - }
> -
> - if (local->value == NULL) {
> - return local->addr;
> - }
> -
> - if (ngx_http_complex_value(r, local->value, &val) != NGX_OK) {
> - return NULL;
> - }
> -
> - if (val.len == 0) {
> - return NULL;
> - }
> -
> - addr = ngx_palloc(r->pool, sizeof(ngx_addr_t));
> - if (addr == NULL) {
> - return NULL;
> - }
> -
> - rc = ngx_parse_addr(r->pool, addr, val.data, val.len);
> -
> - switch (rc) {
> - case NGX_OK:
> - addr->name = val;
> - return addr;
> -
> - case NGX_DECLINED:
> - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
> - "invalid local address \"%V\"", &val);
> - /* fall through */
> -
> - default:
> - return NULL;
> - }
> -}
> -
> -
> char *
> ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
> void *conf)
> diff --git a/src/http/ngx_http_upstream_round_robin.c
> b/src/http/ngx_http_upstream_round_robin.c
> --- a/src/http/ngx_http_upstream_round_robin.c
> +++ b/src/http/ngx_http_upstream_round_robin.c
> @@ -22,6 +22,9 @@ static void ngx_http_upstream_empty_save
>
> #endif
>
> +static ngx_addr_t *ngx_http_upstream_get_local(ngx_peer_connection_t *pc,
> + void *data);
> +
>
> ngx_int_t
> ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
> @@ -246,6 +249,8 @@ ngx_http_upstream_init_round_robin_peer(
> }
> }
>
> + rrp->request = r;
> +
> r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer;
> r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer;
> r->upstream->peer.tries = rrp->peers->number;
> @@ -255,6 +260,7 @@ ngx_http_upstream_init_round_robin_peer(
> r->upstream->peer.save_session =
>
> ngx_http_upstream_save_round_robin_peer_session;
> #endif
> + r->upstream->peer.local = ngx_http_upstream_get_local;
>
> return NGX_OK;
> }
> @@ -679,3 +685,56 @@ ngx_http_upstream_empty_save_session(ngx
> }
>
> #endif
> +
> +
> +static ngx_addr_t *
> +ngx_http_upstream_get_local(ngx_peer_connection_t *pc, void *data)
> +{
> + ngx_http_upstream_rr_peer_data_t *rrp = data;
> +
> + ngx_int_t rc;
> + ngx_str_t val;
> + ngx_addr_t *addr;
> + ngx_http_request_t *r;
> + ngx_http_upstream_local_t *local;
> +
> + r = rrp->request;
> + local = r->upstream->conf->local;
> +
> + if (local == NULL) {
> + return NULL;
> + }
> +
> + if (local->value == NULL) {
> + return local->addr;
> + }
> +
> + if (ngx_http_complex_value(r, local->value, &val) != NGX_OK) {
> + return NULL;
> + }
> +
> + if (val.len == 0) {
> + return NULL;
> + }
> +
> + addr = ngx_palloc(r->pool, sizeof(ngx_addr_t));
> + if (addr == NULL) {
> + return NULL;
> + }
> +
> + rc = ngx_parse_addr(r->pool, addr, val.data, val.len);
> +
> + switch (rc) {
> + case NGX_OK:
> + addr->name = val;
> + return addr;
> +
> + case NGX_DECLINED:
> + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
> + "invalid local address \"%V\"", &val);
> + /* fall through */
> +
> + default:
> + return NULL;
> + }
> +}
> diff --git a/src/http/ngx_http_upstream_round_robin.h
> b/src/http/ngx_http_upstream_round_robin.h
> --- a/src/http/ngx_http_upstream_round_robin.h
> +++ b/src/http/ngx_http_upstream_round_robin.h
> @@ -63,6 +63,7 @@ typedef struct {
> ngx_uint_t current;
> uintptr_t *tried;
> uintptr_t data;
> + ngx_http_request_t *request;
> } ngx_http_upstream_rr_peer_data_t;
>
>
>
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20131209/acff16c1/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch-upstream.patch
Type: application/octet-stream
Size: 3196 bytes
Desc: not available
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20131209/acff16c1/attachment-0001.obj>
More information about the nginx-devel
mailing list