header for a known source address or network by adding the "except" keyword
followed by the network address. In this case, any source IP matching the
network will not cause an addition of this header. Most common uses are with
- private networks or 127.0.0.1.
+ private networks or 127.0.0.1. IPv4 and IPv6 are both supported.
Alternatively, the keyword "if-none" states that the header will only be
added if it is not present. This should only be used in perfectly trusted
header for a known source address or network by adding the "except" keyword
followed by the network address. In this case, any source IP matching the
network will not cause an addition of this header. Most common uses are with
- private networks or 127.0.0.1.
+ private networks or 127.0.0.1. IPv4 and IPv6 are both supported.
This option may be specified either in the frontend or in the backend. If at
least one of them uses it, the header will be added. Note that the backend's
#include <haproxy/stats-t.h>
#include <haproxy/tcpcheck-t.h>
#include <haproxy/thread-t.h>
+#include <haproxy/tools-t.h>
#include <haproxy/uri_auth-t.h>
/* values for proxy->mode */
unsigned int fe_sps_lim; /* limit on new sessions per second on the frontend */
unsigned int fullconn; /* #conns on backend above which servers are used at full load */
unsigned int tot_fe_maxconn; /* #maxconn of frontends linked to that backend, it is used to compute fullconn */
- struct in_addr except_net, except_mask; /* don't x-forward-for for this address. FIXME: should support IPv6 */
- struct in_addr except_to; /* don't x-original-to for this address. */
- struct in_addr except_mask_to; /* the netmask for except_to. */
+ struct net_addr except_xff_net; /* don't x-forward-for for this address. */
+ struct net_addr except_xot_net; /* don't x-original-to for this address. */
char *fwdfor_hdr_name; /* header to use - default: "x-forwarded-for" */
char *orgto_hdr_name; /* header to use - default: "x-original-to" */
int fwdfor_hdr_len; /* length of "x-forwarded-for" header */
free(curproxy->fwdfor_hdr_name);
curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
+ curproxy->except_xff_net.family = AF_UNSPEC;
/* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
cur_arg = 2;
while (*(args[cur_arg])) {
if (strcmp(args[cur_arg], "except") == 0) {
+ unsigned char mask;
+ int i;
+
/* suboption except - needs additional argument for it */
- if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
+ if (*(args[cur_arg+1]) &&
+ str2net(args[cur_arg+1], 1, &curproxy->except_xff_net.addr.v4.ip, &curproxy->except_xff_net.addr.v4.mask)) {
+ curproxy->except_xff_net.family = AF_INET;
+ curproxy->except_xff_net.addr.v4.ip.s_addr &= curproxy->except_xff_net.addr.v4.mask.s_addr;
+ }
+ else if (*(args[cur_arg+1]) &&
+ str62net(args[cur_arg+1], &curproxy->except_xff_net.addr.v6.ip, &mask)) {
+ curproxy->except_xff_net.family = AF_INET6;
+ len2mask6(mask, &curproxy->except_xff_net.addr.v6.mask);
+ for (i = 0; i < 16; i++)
+ curproxy->except_xff_net.addr.v6.ip.s6_addr[i] &= curproxy->except_xff_net.addr.v6.mask.s6_addr[i];
+ }
+ else {
ha_alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
file, linenum, args[0], args[1], args[cur_arg]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
/* flush useless bits */
- curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
cur_arg += 2;
} else if (strcmp(args[cur_arg], "header") == 0) {
/* suboption header - needs additional argument for it */
free(curproxy->orgto_hdr_name);
curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
+ curproxy->except_xot_net.family = AF_UNSPEC;
/* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
cur_arg = 2;
while (*(args[cur_arg])) {
if (strcmp(args[cur_arg], "except") == 0) {
+ unsigned char mask;
+ int i;
+
/* suboption except - needs additional argument for it */
- if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_to, &curproxy->except_mask_to)) {
+ if (*(args[cur_arg+1]) &&
+ str2net(args[cur_arg+1], 1, &curproxy->except_xot_net.addr.v4.ip, &curproxy->except_xot_net.addr.v4.mask)) {
+ curproxy->except_xot_net.family = AF_INET;
+ curproxy->except_xot_net.addr.v4.ip.s_addr &= curproxy->except_xot_net.addr.v4.mask.s_addr;
+ }
+ else if (*(args[cur_arg+1]) &&
+ str62net(args[cur_arg+1], &curproxy->except_xot_net.addr.v6.ip, &mask)) {
+ curproxy->except_xot_net.family = AF_INET6;
+ len2mask6(mask, &curproxy->except_xot_net.addr.v6.mask);
+ for (i = 0; i < 16; i++)
+ curproxy->except_xot_net.addr.v6.ip.s6_addr[i] &= curproxy->except_xot_net.addr.v6.mask.s6_addr[i];
+ }
+ else {
ha_alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
file, linenum, args[0], args[1], args[cur_arg]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
- /* flush useless bits */
- curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
cur_arg += 2;
} else if (strcmp(args[cur_arg], "header") == 0) {
/* suboption header - needs additional argument for it */
/* Add an X-Forwarded-For header unless the source IP is
* in the 'except' network range.
*/
- if ((!sess->fe->except_mask.s_addr ||
- (((struct sockaddr_in *)cli_conn->src)->sin_addr.s_addr & sess->fe->except_mask.s_addr)
- != sess->fe->except_net.s_addr) &&
- (!s->be->except_mask.s_addr ||
- (((struct sockaddr_in *)cli_conn->src)->sin_addr.s_addr & s->be->except_mask.s_addr)
- != s->be->except_net.s_addr)) {
+ if (ipcmp2net(cli_conn->src, &sess->fe->except_xff_net) &&
+ ipcmp2net(cli_conn->src, &s->be->except_xff_net)) {
unsigned char *pn = (unsigned char *)&((struct sockaddr_in *)cli_conn->src)->sin_addr;
/* Note: we rely on the backend to get the header name to be used for
}
}
else if (cli_conn && conn_get_src(cli_conn) && cli_conn->src->ss_family == AF_INET6) {
- /* FIXME: for the sake of completeness, we should also support
- * 'except' here, although it is mostly useless in this case.
+ /* Add an X-Forwarded-For header unless the source IP is
+ * in the 'except' network range.
*/
- char pn[INET6_ADDRSTRLEN];
+ if (ipcmp2net(cli_conn->src, &sess->fe->except_xff_net) &&
+ ipcmp2net(cli_conn->src, &s->be->except_xff_net)) {
+ char pn[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6,
- (const void *)&((struct sockaddr_in6 *)(cli_conn->src))->sin6_addr,
- pn, sizeof(pn));
+ inet_ntop(AF_INET6,
+ (const void *)&((struct sockaddr_in6 *)(cli_conn->src))->sin6_addr,
+ pn, sizeof(pn));
- /* Note: we rely on the backend to get the header name to be used for
- * x-forwarded-for, because the header is really meant for the backends.
- * However, if the backend did not specify any option, we have to rely
- * on the frontend's header name.
- */
- chunk_printf(&trash, "%s", pn);
- if (unlikely(!http_add_header(htx, hdr, ist2(trash.area, trash.data))))
- goto return_int_err;
+ /* Note: we rely on the backend to get the header name to be used for
+ * x-forwarded-for, because the header is really meant for the backends.
+ * However, if the backend did not specify any option, we have to rely
+ * on the frontend's header name.
+ */
+ chunk_printf(&trash, "%s", pn);
+ if (unlikely(!http_add_header(htx, hdr, ist2(trash.area, trash.data))))
+ goto return_int_err;
+ }
}
}
* asks for it.
*/
if ((sess->fe->options | s->be->options) & PR_O_ORGTO) {
+ struct ist hdr = ist2(s->be->orgto_hdr_len ? s->be->orgto_hdr_name : sess->fe->orgto_hdr_name,
+ s->be->orgto_hdr_len ? s->be->orgto_hdr_len : sess->fe->orgto_hdr_len);
- /* FIXME: don't know if IPv6 can handle that case too. */
if (cli_conn && conn_get_dst(cli_conn) && cli_conn->dst->ss_family == AF_INET) {
/* Add an X-Original-To header unless the destination IP is
* in the 'except' network range.
*/
- if (cli_conn->dst->ss_family == AF_INET &&
- ((!sess->fe->except_mask_to.s_addr ||
- (((struct sockaddr_in *)cli_conn->dst)->sin_addr.s_addr & sess->fe->except_mask_to.s_addr)
- != sess->fe->except_to.s_addr) &&
- (!s->be->except_mask_to.s_addr ||
- (((struct sockaddr_in *)cli_conn->dst)->sin_addr.s_addr & s->be->except_mask_to.s_addr)
- != s->be->except_to.s_addr))) {
- struct ist hdr;
+ if (ipcmp2net(cli_conn->dst, &sess->fe->except_xot_net) &&
+ ipcmp2net(cli_conn->dst, &s->be->except_xot_net)) {
unsigned char *pn = (unsigned char *)&((struct sockaddr_in *)cli_conn->dst)->sin_addr;
/* Note: we rely on the backend to get the header name to be used for
* However, if the backend did not specify any option, we have to rely
* on the frontend's header name.
*/
- if (s->be->orgto_hdr_len)
- hdr = ist2(s->be->orgto_hdr_name, s->be->orgto_hdr_len);
- else
- hdr = ist2(sess->fe->orgto_hdr_name, sess->fe->orgto_hdr_len);
-
chunk_printf(&trash, "%d.%d.%d.%d", pn[0], pn[1], pn[2], pn[3]);
if (unlikely(!http_add_header(htx, hdr, ist2(trash.area, trash.data))))
goto return_int_err;
}
}
+ else if (cli_conn && conn_get_dst(cli_conn) && cli_conn->dst->ss_family == AF_INET6) {
+ /* Add an X-Original-To header unless the source IP is
+ * in the 'except' network range.
+ */
+ if (ipcmp2net(cli_conn->dst, &sess->fe->except_xot_net) &&
+ ipcmp2net(cli_conn->dst, &s->be->except_xot_net)) {
+ char pn[INET6_ADDRSTRLEN];
+
+ inet_ntop(AF_INET6,
+ (const void *)&((struct sockaddr_in6 *)(cli_conn->dst))->sin6_addr,
+ pn, sizeof(pn));
+
+ /* Note: we rely on the backend to get the header name to be used for
+ * x-forwarded-for, because the header is really meant for the backends.
+ * However, if the backend did not specify any option, we have to rely
+ * on the frontend's header name.
+ */
+ chunk_printf(&trash, "%s", pn);
+ if (unlikely(!http_add_header(htx, hdr, ist2(trash.area, trash.data))))
+ goto return_int_err;
+ }
+ }
}
/* If we have no server assigned yet and we're balancing on url_param
curproxy->no_options = defproxy->no_options;
curproxy->no_options2 = defproxy->no_options2;
curproxy->bind_proc = defproxy->bind_proc;
- curproxy->except_net = defproxy->except_net;
- curproxy->except_mask = defproxy->except_mask;
- curproxy->except_to = defproxy->except_to;
- curproxy->except_mask_to = defproxy->except_mask_to;
+ curproxy->except_xff_net = defproxy->except_xff_net;
+ curproxy->except_xot_net = defproxy->except_xot_net;
curproxy->retry_type = defproxy->retry_type;
if (defproxy->fwdfor_hdr_len) {