Index: modules/proxy/proxy_util.c =================================================================== --- modules/proxy/proxy_util.c (revision 620505) +++ modules/proxy/proxy_util.c (working copy) @@ -1599,6 +1599,15 @@ PROXY_DECLARE(int) ap_proxy_connect_to_b "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_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); @@ -2266,6 +2275,7 @@ PROXY_DECLARE(int) ap_proxy_connect_back int connected = 0; int loglevel; apr_sockaddr_t *backend_addr = conn->addr; + apr_sockaddr_t *local_addr; apr_socket_t *newsock; void *sconf = s->module_config; proxy_server_conf *conf = @@ -2339,6 +2349,18 @@ PROXY_DECLARE(int) ap_proxy_connect_back "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); Index: modules/proxy/mod_proxy.c =================================================================== --- modules/proxy/mod_proxy.c (revision 620505) +++ modules/proxy/mod_proxy.c (working copy) @@ -1035,6 +1035,8 @@ static void * create_proxy_config(apr_po ps->timeout_set = 0; ps->badopt = bad_error; ps->badopt_set = 0; + ps->source_address = 0; + ps->source_address_set = 0; ps->pool = p; return ps; @@ -1078,6 +1080,8 @@ static void * merge_proxy_config(apr_poo 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; } @@ -1846,6 +1850,24 @@ static const char *set_ftp_directory_cha return NULL; } +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 ap_add_per_proxy_conf(server_rec *s, ap_conf_vector_t *dir_config) { proxy_server_conf *sconf = ap_get_module_config(s->module_config, @@ -2058,6 +2080,8 @@ static const command_rec proxy_cmds[] = "A balancer or worker name with list of params"), AP_INIT_TAKE1("ProxyFtpDirCharset", set_ftp_directory_charset, NULL, RSRC_CONF|ACCESS_CONF, "Define the character set for proxied FTP listings"), + AP_INIT_TAKE1("ProxySourceAddress", set_source_address, NULL, RSRC_CONF, + "Configure local source IP used for request forward"), {NULL} }; Index: modules/proxy/mod_proxy.h =================================================================== --- modules/proxy/mod_proxy.h (revision 620505) +++ modules/proxy/mod_proxy.h (working copy) @@ -192,6 +192,8 @@ typedef struct { status_full } proxy_status; /* Status display options */ char proxy_status_set; + apr_sockaddr_t *source_address; + char source_address_set; apr_pool_t *pool; /* Pool used for allocating this struct */ } proxy_server_conf;