Re: stick-table question

From: Willy Tarreau <w#1wt.eu>
Date: Wed, 12 May 2010 08:18:24 +0200


On Tue, May 11, 2010 at 05:34:08PM -0700, Shannon Lee wrote:
> The xforwardedfor stuff is in our stunnel, I just need to figure out how to
> use the X-Forwarded-For header as the key in the stick table. For
> example...
>
> stick-table type ip size 200k expire 30m
> stick on src
>
> ..sends every incoming connection to the same backend host while we're using
> stunnel. The docs make it seem like the 'stick on' and 'stick match'
> pattern extraction is pretty limited...?

yes, as I indicated in previous mail, *right now* the pattern extraction is limited. The reason is that it does not share much code with the ACL patterns and we thought it was wasted to duplicate everything, we'd better adapt the pattern extraction to serve both stick-tables and ACLs. But the way it is done makes it very easy to add new rules anyway if needed.

Hey, finally I took a few minutes to implement it while typing this mail. Please find the patch at the end of this mail. You can apply it on top of 1.4.4. You'll then have to use :

       stick on hdr(x-forwarded-for)

and it will use the last occurrence of the header as an IP address to stick on.

regards,
Willy


From 9e327a7c9e9add69c3dc2f70a1b41b776a2143b1 Mon Sep 17 00:00:00 2001 From: Willy Tarreau <w#1wt.eu>
Date: Wed, 12 May 2010 08:08:50 +0200
Subject: [MINOR] stick-tables: add support for "stick on hdr"

It is now possible to stick on an IP address found in a HTTP header. Right now only the last occurrence of the header can be used, which is generally enough for most uses. Also, the header extraction rule only knows how to convert the header to IP. Later it will be usable as a plain string with an implicit conversion, and the syntax will not change.

---
 doc/configuration.txt |    5 +++++
 src/proto_http.c      |   30 ++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/doc/configuration.txt b/doc/configuration.txt
index 1ca54fe..0df8ac9 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -6548,6 +6548,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 <name> 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 c8835a5..9c43cf2 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -49,6 +49,7 @@
 #include <proto/fd.h>
 #include <proto/log.h>
 #include <proto/hdr_idx.h>
+#include <proto/pattern.h>
 #include <proto/proto_tcp.h>
 #include <proto/proto_http.h>
 #include <proto/proxy.h>
@@ -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 <const> 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);
 }
 
 
-- 
1.6.4.4
Received on 2010/05/12 08:18

This archive was generated by hypermail 2.2.0 : 2010/05/12 08:30 CEST