mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 07:37:02 +02:00
[MEDIUM] add the "except" keyword to the "forwardfor" option
Patch from Bryan Germann for 1.2.17. In some circumstances, it is useful not to add the X-Forwarded-For header, for instance when the client is another reverse-proxy or stunnel running on the same machine and which already adds it. This patch adds the "except" keyword to the "forwardfor" option, allowing to specify an address or network which will not be added to this header.
This commit is contained in:
parent
95c20aca35
commit
7ac51f61f5
@ -2142,7 +2142,12 @@ Examples :
|
||||
|
||||
Also, the 'forwardfor' option creates an HTTP 'X-Forwarded-For' header which
|
||||
contains the client's IP address. This is useful to let the final web server
|
||||
know what the client address was (eg for statistics on domains).
|
||||
know what the client address was (eg for statistics on domains). Starting with
|
||||
version 1.3.8, it is possible to specify the "except" keyword followed by a
|
||||
source IP address or network for which no header will be added. This is very
|
||||
useful when another reverse-proxy which already adds the header runs on the
|
||||
same machine or in a known DMZ, the most common case being the local use of
|
||||
stunnel on the same system.
|
||||
|
||||
Last, the 'httpclose' option removes any 'Connection' header both ways, and
|
||||
adds a 'Connection: close' header in each direction. This makes it easier to
|
||||
@ -2155,7 +2160,7 @@ Example :
|
||||
log global
|
||||
option httplog
|
||||
option dontlognull
|
||||
option forwardfor
|
||||
option forwardfor except 127.0.0.1/8
|
||||
option httpclose
|
||||
|
||||
Note that some HTTP servers do not necessarily close the connections when they
|
||||
|
@ -2223,7 +2223,12 @@ Exemples :
|
||||
|
||||
De plus, l'option 'forwardfor' ajoute l'adresse IP du client dans un champ
|
||||
'X-Forwarded-For' de la requête, ce qui permet à un serveur web final de
|
||||
connaître l'adresse IP du client initial.
|
||||
connaître l'adresse IP du client initial. Depuis la version 1.3.8, il est
|
||||
possible de préciser le mot-clé "except" suivi d'une adresse ou un réseau
|
||||
IP source pour lequel l'entête ne sera pas ajouté. C'est très pratique dans le
|
||||
cas où un autre reverse-proxy ajoutant déjà l'entête est installé sur la même
|
||||
machine ou dans une DMZ connue. Le cas le plus fréquent est lié à l'utilisation
|
||||
de stunnel en local.
|
||||
|
||||
Enfin, l'option 'httpclose' apparue dans la version 1.1.28/1.2.1 supprime tout
|
||||
en-tête de type 'Connection:' et ajoute 'Connection: close' dans les deux sens.
|
||||
@ -2237,7 +2242,7 @@ Exemple :
|
||||
log global
|
||||
option httplog
|
||||
option dontlognull
|
||||
option forwardfor
|
||||
option forwardfor except 127.0.0.1/8
|
||||
option httpclose
|
||||
|
||||
Notons que certains serveurs HTTP ne referment pas nécessairement la session
|
||||
|
@ -113,6 +113,7 @@ struct proxy {
|
||||
unsigned int cum_feconn, cum_beconn; /* cumulated number of processed sessions */
|
||||
unsigned int maxconn; /* max # of active sessions on the frontend */
|
||||
unsigned int fullconn; /* #conns on backend above which servers are used at full load */
|
||||
struct in_addr except_net, except_mask; /* don't x-forward-for for this address. FIXME: should support IPv6 */
|
||||
unsigned failed_conns, failed_resp; /* failed connect() and responses */
|
||||
unsigned denied_req, denied_resp; /* blocked requests/responses because of security concerns */
|
||||
unsigned failed_req; /* failed requests (eg: invalid or timeout) */
|
||||
|
@ -85,7 +85,6 @@ static const struct {
|
||||
#endif
|
||||
{ "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
|
||||
{ "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
|
||||
{ "forwardfor", PR_O_FWDFOR, PR_CAP_FE | PR_CAP_BE, 0 },
|
||||
{ "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
|
||||
{ "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
|
||||
{ "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
|
||||
@ -501,6 +500,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
|
||||
/* set default values */
|
||||
curproxy->state = defproxy.state;
|
||||
curproxy->options = defproxy.options;
|
||||
curproxy->except_net = defproxy.except_net;
|
||||
curproxy->except_mask = defproxy.except_mask;
|
||||
|
||||
if (curproxy->cap & PR_CAP_FE) {
|
||||
curproxy->maxconn = defproxy.maxconn;
|
||||
@ -1022,6 +1023,27 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
|
||||
curproxy->options &= ~PR_O_HTTP_CHK;
|
||||
curproxy->options |= PR_O_SSL3_CHK;
|
||||
}
|
||||
else if (!strcmp(args[1], "forwardfor")) {
|
||||
/* insert x-forwarded-for field, but not for the
|
||||
* IP address listed as an except.
|
||||
*/
|
||||
if (*(args[2])) {
|
||||
if (!strcmp(args[2], "except")) {
|
||||
if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
|
||||
Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
|
||||
file, linenum, args[0]);
|
||||
return -1;
|
||||
}
|
||||
/* flush useless bits */
|
||||
curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
|
||||
} else {
|
||||
Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
|
||||
file, linenum, args[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
curproxy->options |= PR_O_FWDFOR;
|
||||
}
|
||||
else {
|
||||
Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
|
||||
return -1;
|
||||
|
@ -1656,17 +1656,31 @@ int process_cli(struct session *t)
|
||||
*/
|
||||
if ((t->fe->options | t->be->beprm->options) & PR_O_FWDFOR) {
|
||||
if (t->cli_addr.ss_family == AF_INET) {
|
||||
int len;
|
||||
unsigned char *pn;
|
||||
pn = (unsigned char *)&((struct sockaddr_in *)&t->cli_addr)->sin_addr;
|
||||
len = sprintf(trash, "X-Forwarded-For: %d.%d.%d.%d",
|
||||
pn[0], pn[1], pn[2], pn[3]);
|
||||
/* Add an X-Forwarded-For header unless the source IP is
|
||||
* in the 'except' network range.
|
||||
*/
|
||||
if ((!t->fe->except_mask.s_addr ||
|
||||
(((struct sockaddr_in *)&t->cli_addr)->sin_addr.s_addr & t->fe->except_mask.s_addr)
|
||||
!= t->fe->except_net.s_addr) &&
|
||||
(!t->be->except_mask.s_addr ||
|
||||
(((struct sockaddr_in *)&t->cli_addr)->sin_addr.s_addr & t->be->except_mask.s_addr)
|
||||
!= t->be->except_net.s_addr)) {
|
||||
int len;
|
||||
unsigned char *pn;
|
||||
pn = (unsigned char *)&((struct sockaddr_in *)&t->cli_addr)->sin_addr;
|
||||
|
||||
if (unlikely(http_header_add_tail2(req, &txn->req,
|
||||
&txn->hdr_idx, trash, len)) < 0)
|
||||
goto return_bad_req;
|
||||
len = sprintf(trash, "X-Forwarded-For: %d.%d.%d.%d",
|
||||
pn[0], pn[1], pn[2], pn[3]);
|
||||
|
||||
if (unlikely(http_header_add_tail2(req, &txn->req,
|
||||
&txn->hdr_idx, trash, len)) < 0)
|
||||
goto return_bad_req;
|
||||
}
|
||||
}
|
||||
else if (t->cli_addr.ss_family == AF_INET6) {
|
||||
/* FIXME: for the sake of completeness, we should also support
|
||||
* 'except' here, although it is mostly useless in this case.
|
||||
*/
|
||||
int len;
|
||||
char pn[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6,
|
||||
|
Loading…
Reference in New Issue
Block a user