From 3bad5b17805e75f1b94c13dae70b9c989e417974 Mon Sep 17 00:00:00 2001 From: Nick Kew Date: Sun, 14 Nov 2010 00:01:43 +0000 Subject: [PATCH] Fix mod_proxy to support setting source address. PR 29404 Seems lots of users want this, and a couple of them have recenly asked nicely git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1034916 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 5 +++++ include/ap_mmn.h | 5 +++-- modules/proxy/mod_proxy.c | 24 ++++++++++++++++++++++++ modules/proxy/mod_proxy.h | 2 ++ modules/proxy/proxy_util.c | 23 +++++++++++++++++++++++ 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 4d780b102b..6963dba9d6 100644 --- a/CHANGES +++ b/CHANGES @@ -243,6 +243,11 @@ Changes with Apache 2.3.9 and executing perl-style regexp ops (e.g s/foo/bar/i) and regexp memory [Nick Kew] + *) Proxy: support setting source address. PR 29404 + [Multiple contributors iterating through bugzilla, + Aron Ujvari , Aleksey Midenkov , + timeout_set = 0; ps->badopt = bad_error; ps->badopt_set = 0; + ps->source_address = NULL; + ps->source_address_set = 0; ps->pool = p; return ps; @@ -1188,9 +1190,29 @@ static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv) ps->badopt_set = overrides->badopt_set || base->badopt_set; ps->proxy_status = (overrides->proxy_status_set == 0) ? base->proxy_status : overrides->proxy_status; ps->proxy_status_set = overrides->proxy_status_set || base->proxy_status_set; + ps->source_address = (overrides->source_address_set == 0) ? base->source_address : overrides->source_address; + ps->source_address_set = overrides->source_address_set || base->source_address_set; ps->pool = p; return ps; } +static const char *set_source_address(cmd_parms *parms, void *dummy, + const char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + struct apr_sockaddr_t *addr; + + if (APR_SUCCESS == apr_sockaddr_info_get(&addr, arg, APR_UNSPEC, 0, 0, + psf->pool)) { + psf->source_address = addr; + psf->source_address_set = 1; + } + else { + return "ProxySourceAddress invalid value"; + } + + return NULL; +} static void *create_proxy_dir_config(apr_pool_t *p, char *dummy) { @@ -2190,6 +2212,8 @@ static const command_rec proxy_cmds[] = "Configure Status: proxy status to one of: on | off | full"), AP_INIT_RAW_ARGS("ProxySet", set_proxy_param, NULL, RSRC_CONF|ACCESS_CONF, "A balancer or worker name with list of params"), + AP_INIT_TAKE1("ProxySourceAddress", set_source_address, NULL, RSRC_CONF, + "Configure local source IP used for request forward"), {NULL} }; diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 28dedadd56..6da213cbca 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -150,6 +150,7 @@ typedef struct { status_on, status_full } proxy_status; /* Status display options */ + apr_sockaddr_t *source_address; int req_set:1; int viaopt_set:1; @@ -159,6 +160,7 @@ typedef struct { int timeout_set:1; int badopt_set:1; int proxy_status_set:1; + int source_address_set:1; } proxy_server_conf; diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index bb01a56ba2..277c7d4155 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -1682,6 +1682,15 @@ PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **newsock, "proxy: %s: fam %d socket created to connect to %s", proxy_function, backend_addr->family, backend_name); + if (conf->source_address) { + rv = apr_socket_bind(*newsock, conf->source_address); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "proxy: %s: failed to bind socket to local address", + proxy_function); + } + } + /* make the connection out of the socket */ rv = apr_socket_connect(*newsock, backend_addr); @@ -2453,6 +2462,8 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, int connected = 0; int loglevel; apr_sockaddr_t *backend_addr = conn->addr; + /* the local address to use for the outgoing connection */ + apr_sockaddr_t *local_addr; apr_socket_t *newsock; void *sconf = s->module_config; proxy_server_conf *conf = @@ -2527,6 +2538,18 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, "proxy: %s: fam %d socket created to connect to %s", proxy_function, backend_addr->family, worker->hostname); + if (conf->source_address_set == 1) { + local_addr = apr_pcalloc(conn->pool, sizeof(apr_sockaddr_t)); + memcpy(local_addr, conf->source_address, sizeof(apr_sockaddr_t)); + local_addr->pool = conn->pool; + rv = apr_socket_bind(newsock, local_addr); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + "proxy: %s: failed to bind socket to local address", + proxy_function); + } + } + /* make the connection out of the socket */ rv = apr_socket_connect(newsock, backend_addr); -- 2.40.0