diff --git a/doc/configuration.txt b/doc/configuration.txt index 93914a570..b8636acc8 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -6555,6 +6555,11 @@ The list of currently supported pattern fetch functions is the following : ports to some clients for a whole application session. It is of type integer and only works with such tables. + hdr(name) This extracts the last occurrence of header in an HTTP + request and converts it to an IP address. This IP address is + then used to match the table. A typical use is with the + x-forwarded-for header. + The currently available list of transformations include : diff --git a/src/proto_http.c b/src/proto_http.c index 1f134385f..0209391b1 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -7429,11 +7430,40 @@ static struct acl_kw_list acl_kws = {{ },{ { NULL, NULL, NULL, NULL }, }}; +/************************************************************************/ +/* The code below is dedicated to pattern fetching and matching */ +/************************************************************************/ + +/* extract the IP address from the last occurrence of specified header. Note + * that we should normally first extract the string then convert it to IP, + * but right now we have all the functions to do this seemlessly, and we will + * be able to change that later without touching the configuration. + */ +static int +pattern_fetch_hdr_ip(struct proxy *px, struct session *l4, void *l7, int dir, + const char *arg, int arg_len, union pattern_data *data) +{ + struct http_txn *txn = l7; + + data->ip.s_addr = htonl(get_ip_from_hdr2(&txn->req, arg, arg_len, &txn->hdr_idx, -1)); + return data->ip.s_addr != 0; +} + +/************************************************************************/ +/* All supported keywords must be declared here. */ +/************************************************************************/ +/* Note: must not be declared as its list will be overwritten */ +static struct pattern_fetch_kw_list pattern_fetch_keywords = {{ },{ + { "hdr", pattern_fetch_hdr_ip, PATTERN_TYPE_IP, PATTERN_FETCH_REQ }, + { NULL, NULL, 0, 0 }, +}}; + __attribute__((constructor)) static void __http_protocol_init(void) { acl_register_keywords(&acl_kws); + pattern_register_fetches(&pattern_fetch_keywords); }