package: haproxy - bump to version 1.4.19 - ensure haproxy is not listen on port...
authorThomas Heil <heil@terminal-consulting.de>
Mon, 9 Jan 2012 22:00:25 +0000 (22:00 +0000)
committerThomas Heil <heil@terminal-consulting.de>
Mon, 9 Jan 2012 22:00:25 +0000 (22:00 +0000)
SVN-Revision: 29702

net/haproxy/Makefile
net/haproxy/files/haproxy.cfg
net/haproxy/patches/001-haproxy-1.4.x-sendproxy.patch [new file with mode: 0644]

index e8d9a36e9f37b3e8bd7b903d317752a96cc40990..bd901cbf4694958fc916bd2a6f9904e55f49eb8a 100644 (file)
@@ -9,12 +9,12 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=haproxy
-PKG_VERSION:=1.4.18
-PKG_RELEASE:=2
+PKG_VERSION:=1.4.19
+PKG_RELEASE:=1
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://haproxy.1wt.eu/download/1.4/src
-PKG_MD5SUM:=4ac88bb1a76c4b84ed4f6131183bedbe
+PKG_MD5SUM:=41392d738460dbf99295fd928031c6a4
 
 include $(INCLUDE_DIR)/package.mk
 
index 1c56884a6243c13b25546e245de4d312d5e28a7a..fe2ec5a3a04d3d2a11ce749f94b80bf899975d1c 100644 (file)
@@ -29,6 +29,7 @@ global
        # Daemonize on startup
        daemon
 
+       nosplice
        # Enable debugging
        #debug
 
@@ -42,7 +43,7 @@ global
 listen my_http_proxy
 
        # Bind to port 80 and 443 on all interfaces (0.0.0.0)
-       bind :80,:443
+       bind :81,:444
 
        # We're proxying HTTP here...
        mode http
@@ -69,7 +70,7 @@ listen my_smtp_proxy
        disabled
 
        # Bind to port 25 and 587 on localhost
-       bind 127.0.0.1:25,127.0.0.1:587
+       bind 127.0.0.1:26,127.0.0.1:588
 
        # This is a TCP proxy
        mode tcp
diff --git a/net/haproxy/patches/001-haproxy-1.4.x-sendproxy.patch b/net/haproxy/patches/001-haproxy-1.4.x-sendproxy.patch
new file mode 100644 (file)
index 0000000..87f77dc
--- /dev/null
@@ -0,0 +1,461 @@
+Index: haproxy-1.4.19/doc/configuration.txt
+===================================================================
+--- haproxy-1.4.19.orig/doc/configuration.txt
++++ haproxy-1.4.19/doc/configuration.txt
+@@ -1337,6 +1337,7 @@ bind [<address>]:<port_range> [, ...] tr
+ bind [<address>]:<port_range> [, ...] id <id>
+ bind [<address>]:<port_range> [, ...] name <name>
+ bind [<address>]:<port_range> [, ...] defer-accept
++bind [<address>]:<port_range> [, ...] accept-proxy
+   Define one or several listening addresses and/or ports in a frontend.
+   May be used in sections :   defaults | frontend | listen | backend
+                                   no   |    yes   |   yes  |   no
+@@ -1417,6 +1418,19 @@ bind [<address>]:<port_range> [, ...] de
+                   with front firewalls which would see an established
+                   connection while the proxy will only see it in SYN_RECV.
++    accept-proxy  is an optional keyword which enforces use of the PROXY
++                  protocol over any connection accepted by this listener. The
++                  PROXY protocol dictates the layer 3/4 addresses of the
++                  incoming connection to be used everywhere an address is used,
++                  with the only exception of "tcp-request connection" rules
++                  which will only see the real connection address. Logs will
++                  reflect the addresses indicated in the protocol, unless it is
++                  violated, in which case the real address will still be used.
++                  This keyword combined with support from external components
++                  can be used as an efficient and reliable alternative to the
++                  X-Forwarded-For mechanism which is not always reliable and
++                  not even always usable.
++
+   It is possible to specify a list of address:port combinations delimited by
+   commas. The frontend will then listen on all of these addresses. There is no
+   fixed limit to the number of addresses and ports which can be listened on in
+@@ -1427,8 +1441,10 @@ bind [<address>]:<port_range> [, ...] de
+         listen http_proxy
+             bind :80,:443
+             bind 10.0.0.1:10080,10.0.0.1:10443
++            bind 127.0.0.1:8443 accept-proxy
+-  See also : "source".
++  See also : "source", "option forwardfor" and the PROXY protocol
++             documentation.
+ bind-process [ all | odd | even | <number 1-32> ] ...
+@@ -7215,7 +7231,9 @@ marked with a star ('*') after the field
+ Detailed fields description :
+   - "client_ip" is the IP address of the client which initiated the TCP
+-    connection to haproxy.
++    connection to haproxy. Note that when the connection is accepted on a
++    socket configured with "accept-proxy" and the PROXY protocol is correctly
++    used, then the logs will reflect the forwarded connection's information.
+   - "client_port" is the TCP port of the client which initiated the connection.
+@@ -7388,7 +7406,9 @@ with a star ('*') after the field name b
+ Detailed fields description :
+   - "client_ip" is the IP address of the client which initiated the TCP
+-    connection to haproxy.
++    connection to haproxy. Note that when the connection is accepted on a
++    socket configured with "accept-proxy" and the PROXY protocol is correctly
++    used, then the logs will reflect the forwarded connection's information.
+   - "client_port" is the TCP port of the client which initiated the connection.
+Index: haproxy-1.4.19/include/common/standard.h
+===================================================================
+--- haproxy-1.4.19.orig/include/common/standard.h
++++ haproxy-1.4.19/include/common/standard.h
+@@ -269,6 +269,28 @@ static inline unsigned int __strl2uic(co
+       return i;
+ }
++/* This function reads an unsigned integer from the string pointed to by <s>
++ * and returns it. The <s> pointer is adjusted to point to the first unread
++ * char. The function automatically stops at <end>.
++ */
++static inline unsigned int __read_uint(const char **s, const char *end)
++{
++      const char *ptr = *s;
++      unsigned int i = 0;
++      unsigned int j, k;
++
++      while (ptr < end) {
++              j = *ptr - '0';
++              k = i * 10;
++              if (j > 9)
++                      break;
++              i = k + j;
++              ptr++;
++      }
++      *s = ptr;
++      return i;
++}
++
+ extern unsigned int str2ui(const char *s);
+ extern unsigned int str2uic(const char *s);
+ extern unsigned int strl2ui(const char *s, int len);
+@@ -276,6 +298,7 @@ extern unsigned int strl2uic(const char 
+ extern int strl2ic(const char *s, int len);
+ extern int strl2irc(const char *s, int len, int *ret);
+ extern int strl2llrc(const char *s, int len, long long *ret);
++extern unsigned int read_uint(const char **s, const char *end);
+ unsigned int inetaddr_host(const char *text);
+ unsigned int inetaddr_host_lim(const char *text, const char *stop);
+ unsigned int inetaddr_host_lim_ret(const char *text, char *stop, const char **ret);
+Index: haproxy-1.4.19/include/proto/client.h
+===================================================================
+--- haproxy-1.4.19.orig/include/proto/client.h
++++ haproxy-1.4.19/include/proto/client.h
+@@ -25,6 +25,7 @@
+ #include <common/config.h>
+ #include <types/session.h>
++int frontend_decode_proxy_request(struct session *s, struct buffer *req, int an_bit);
+ void get_frt_addr(struct session *s);
+ int event_accept(int fd);
+Index: haproxy-1.4.19/include/types/buffers.h
+===================================================================
+--- haproxy-1.4.19.orig/include/types/buffers.h
++++ haproxy-1.4.19/include/types/buffers.h
+@@ -135,16 +135,16 @@
+  * The field is blanked by buffer_init() and only by analysers themselves
+  * afterwards.
+  */
+-#define AN_REQ_INSPECT          0x00000001  /* inspect request contents */
+-#define AN_REQ_WAIT_HTTP        0x00000002  /* wait for an HTTP request */
+-#define AN_REQ_HTTP_PROCESS_FE  0x00000004  /* process the frontend's HTTP part */
+-#define AN_REQ_SWITCHING_RULES  0x00000008  /* apply the switching rules */
+-#define AN_REQ_HTTP_PROCESS_BE  0x00000010  /* process the backend's HTTP part */
+-#define AN_REQ_HTTP_INNER       0x00000020  /* inner processing of HTTP request */
+-#define AN_REQ_HTTP_TARPIT      0x00000040  /* wait for end of HTTP tarpit */
+-#define AN_REQ_HTTP_BODY        0x00000080  /* inspect HTTP request body */
+-#define AN_REQ_STICKING_RULES   0x00000100  /* table persistence matching */
+-/* unused: 0x200 */
++#define AN_REQ_DECODE_PROXY     0x00000001  /* take the proxied address from a 'PROXY' line */
++#define AN_REQ_INSPECT          0x00000002  /* inspect request contents */
++#define AN_REQ_WAIT_HTTP        0x00000004  /* wait for an HTTP request */
++#define AN_REQ_HTTP_PROCESS_FE  0x00000008  /* process the frontend's HTTP part */
++#define AN_REQ_SWITCHING_RULES  0x00000010  /* apply the switching rules */
++#define AN_REQ_HTTP_PROCESS_BE  0x00000020  /* process the backend's HTTP part */
++#define AN_REQ_HTTP_INNER       0x00000040  /* inner processing of HTTP request */
++#define AN_REQ_HTTP_TARPIT      0x00000080  /* wait for end of HTTP tarpit */
++#define AN_REQ_HTTP_BODY        0x00000100  /* inspect HTTP request body */
++#define AN_REQ_STICKING_RULES   0x00000200  /* table persistence matching */
+ #define AN_REQ_PRST_RDP_COOKIE  0x00000400  /* persistence on rdp cookie */
+ #define AN_REQ_HTTP_XFER_BODY   0x00000800  /* forward request body */
+Index: haproxy-1.4.19/include/types/protocols.h
+===================================================================
+--- haproxy-1.4.19.orig/include/types/protocols.h
++++ haproxy-1.4.19/include/types/protocols.h
+@@ -72,6 +72,7 @@
+ #define LI_O_FOREIGN  0x0002  /* permit listening on foreing addresses */
+ #define LI_O_NOQUICKACK       0x0004  /* disable quick ack of immediate data (linux) */
+ #define LI_O_DEF_ACCEPT       0x0008  /* wait up to 1 second for data before accepting */
++#define LI_O_ACC_PROXY  0x0010  /* find the proxied address in the first request line */
+ /* The listener will be directly referenced by the fdtab[] which holds its
+  * socket. The listener provides the protocol-specific accept() function to
+Index: haproxy-1.4.19/src/cfgparse.c
+===================================================================
+--- haproxy-1.4.19.orig/src/cfgparse.c
++++ haproxy-1.4.19/src/cfgparse.c
+@@ -1464,6 +1464,16 @@ int cfg_parse_listen(const char *file, i
+ #endif
+                       }
++                      if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
++                              struct listener *l;
++
++                              for (l = curproxy->listen; l != last_listen; l = l->next)
++                                      l->options |= LI_O_ACC_PROXY;
++
++                              cur_arg ++;
++                              continue;
++                      }
++
+                       if (!strcmp(args[cur_arg], "name")) {
+                               struct listener *l;
+@@ -1516,7 +1526,7 @@ int cfg_parse_listen(const char *file, i
+                               continue;
+                       }
+-                      Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
++                      Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
+                             file, linenum, args[0]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+@@ -5702,6 +5712,9 @@ out_uri_auth_compat:
+                       listener->handler = process_session;
+                       listener->analysers |= curproxy->fe_req_ana;
++                      if (listener->options & LI_O_ACC_PROXY)
++                              listener->analysers |= AN_REQ_DECODE_PROXY;
++
+                       /* smart accept mode is automatic in HTTP mode */
+                       if ((curproxy->options2 & PR_O2_SMARTACC) ||
+                           (curproxy->mode == PR_MODE_HTTP &&
+Index: haproxy-1.4.19/src/client.c
+===================================================================
+--- haproxy-1.4.19.orig/src/client.c
++++ haproxy-1.4.19/src/client.c
+@@ -22,6 +22,7 @@
+ #include <common/compat.h>
+ #include <common/config.h>
++#include <common/debug.h>
+ #include <common/time.h>
+ #include <types/global.h>
+@@ -43,6 +44,191 @@
+ #include <proto/task.h>
++/* This analyser tries to fetch a line from the request buffer which looks like :
++ *
++ *   "PROXY" <SP> PROTO <SP> SRC3 <SP> DST3 <SP> SRC4 <SP> <DST4> "\r\n"
++ *
++ * There must be exactly one space between each field. Fields are :
++ *  - PROTO : layer 4 protocol, which must be "TCP4" or "TCP6".
++ *  - SRC3  : layer 3 (eg: IP) source address in standard text form
++ *  - DST3  : layer 3 (eg: IP) destination address in standard text form
++ *  - SRC4  : layer 4 (eg: TCP port) source address in standard text form
++ *  - DST4  : layer 4 (eg: TCP port) destination address in standard text form
++ *
++ * This line MUST be at the beginning of the buffer and MUST NOT wrap.
++ *
++ * Once the data is fetched, the values are set in the session's field and data
++ * are removed from the buffer. The function returns zero if it needs to wait
++ * for more data (max: timeout_client), or 1 if it has finished and removed itself.
++ */
++int frontend_decode_proxy_request(struct session *s, struct buffer *req, int an_bit)
++{
++      char *line = req->data;
++      char *end = req->data + req->l;
++      int len;
++
++      DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
++              now_ms, __FUNCTION__,
++              s,
++              req,
++              req->rex, req->wex,
++              req->flags,
++              req->l,
++              req->analysers);
++
++      if (req->flags & (BF_READ_ERROR|BF_READ_TIMEOUT))
++              goto fail;
++
++      len = MIN(req->l, 6);
++      if (!len)
++              goto missing;
++
++      /* Decode a possible proxy request, fail early if it does not match */
++      if (strncmp(line, "PROXY ", len) != 0)
++              goto fail;
++
++      line += 6;
++      if (req->l < 18) /* shortest possible line */
++              goto missing;
++
++      if (!memcmp(line, "TCP4 ", 5) != 0) {
++              u32 src3, dst3, sport, dport;
++
++              line += 5;
++
++              src3 = inetaddr_host_lim_ret(line, end, &line);
++              if (line == end)
++                      goto missing;
++              if (*line++ != ' ')
++                      goto fail;
++
++              dst3 = inetaddr_host_lim_ret(line, end, &line);
++              if (line == end)
++                      goto missing;
++              if (*line++ != ' ')
++                      goto fail;
++
++              sport = read_uint((const char **)&line, end);
++              if (line == end)
++                      goto missing;
++              if (*line++ != ' ')
++                      goto fail;
++
++              dport = read_uint((const char **)&line, end);
++              if (line > end - 2)
++                      goto missing;
++              if (*line++ != '\r')
++                      goto fail;
++              if (*line++ != '\n')
++                      goto fail;
++
++              /* update the session's addresses and mark them set */
++              ((struct sockaddr_in *)&s->cli_addr)->sin_family      = AF_INET;
++              ((struct sockaddr_in *)&s->cli_addr)->sin_addr.s_addr = htonl(src3);
++              ((struct sockaddr_in *)&s->cli_addr)->sin_port        = htons(sport);
++
++              ((struct sockaddr_in *)&s->frt_addr)->sin_family      = AF_INET;
++              ((struct sockaddr_in *)&s->frt_addr)->sin_addr.s_addr = htonl(dst3);
++              ((struct sockaddr_in *)&s->frt_addr)->sin_port        = htons(dport);
++              s->flags |= SN_FRT_ADDR_SET;
++
++      }
++      else if (!memcmp(line, "TCP6 ", 5) != 0) {
++              u32 sport, dport;
++              char *src_s;
++              char *dst_s, *sport_s, *dport_s;
++              struct in6_addr src3, dst3;
++
++              line+=5;
++
++              src_s = line;
++              dst_s = sport_s = dport_s = NULL;
++              while (1) {
++                      if (line > end - 2) {
++                              goto missing;
++                      }
++                      else if (*line == '\r') {
++                              *line = 0;
++                              line++;
++                              if (*line++ != '\n')
++                                      goto fail;
++                              break;
++                      }
++
++                      if (*line == ' ') {
++                              *line = 0;
++                              if (!dst_s)
++                                      dst_s = line+1;
++                              else if (!sport_s)
++                                      sport_s = line+1;
++                              else if (!dport_s)
++                                      dport_s = line+1;
++                      }
++                      line++;
++              }
++
++              if (!dst_s || !sport_s || !dport_s)
++                      goto fail;
++
++              sport = read_uint((const char **)&sport_s,dport_s-1);
++              if ( *sport_s != 0 )
++                      goto fail;
++
++              dport = read_uint((const char **)&dport_s,line-2);
++              if ( *dport_s != 0 )
++                      goto fail;
++
++              if (inet_pton(AF_INET6, src_s, (void *)&src3) != 1)
++                      goto fail;
++
++              if (inet_pton(AF_INET6, dst_s, (void *)&dst3) != 1)
++                      goto fail;
++
++              /* update the session's addresses and mark them set */
++              ((struct sockaddr_in6 *)&s->cli_addr)->sin6_family      = AF_INET6;
++              memcpy(&((struct sockaddr_in6 *)&s->cli_addr)->sin6_addr, &src3, sizeof(struct in6_addr));
++              ((struct sockaddr_in6 *)&s->cli_addr)->sin6_port        = htons(sport);
++
++              ((struct sockaddr_in6 *)&s->frt_addr)->sin6_family      = AF_INET6;
++              memcpy(&((struct sockaddr_in6 *)&s->frt_addr)->sin6_addr, &dst3, sizeof(struct in6_addr));
++              ((struct sockaddr_in6 *)&s->frt_addr)->sin6_port        = htons(dport);
++              s->flags |= SN_FRT_ADDR_SET;
++      }
++      else {
++              goto fail;
++      }
++
++      /* remove the PROXY line from the request */
++      len = line - req->data;
++      buffer_replace2(req, req->data, line, NULL, 0);
++      req->total -= len; /* don't count the header line */
++
++      req->analysers &= ~an_bit;
++      return 1;
++
++ missing:
++      if (!(req->flags & (BF_SHUTR|BF_FULL))) {
++              buffer_dont_connect(s->req);
++              return 0;
++      }
++      /* missing data and buffer is either full or shutdown => fail */
++
++ fail:
++      buffer_abort(req);
++      buffer_abort(s->rep);
++      req->analysers = 0;
++
++      s->fe->counters.failed_req++;
++      if (s->listener->counters)
++              s->listener->counters->failed_req++;
++
++      if (!(s->flags & SN_ERR_MASK))
++              s->flags |= SN_ERR_PRXCOND;
++      if (!(s->flags & SN_FINST_MASK))
++              s->flags |= SN_FINST_R;
++      return 0;
++}
++
+ /* Retrieves the original destination address used by the client, and sets the
+  * SN_FRT_ADDR_SET flag.
+  */
+Index: haproxy-1.4.19/src/proto_http.c
+===================================================================
+--- haproxy-1.4.19.orig/src/proto_http.c
++++ haproxy-1.4.19/src/proto_http.c
+@@ -4028,7 +4028,8 @@ void http_end_txn_clean_session(struct s
+       if (s->rep->lr >= s->rep->data + s->rep->size)
+               s->rep->lr -= s->req->size;
+-      s->req->analysers |= s->fe->fe_req_ana;
++      s->req->analysers = s->fe->fe_req_ana;
++      s->req->analysers &= ~AN_REQ_DECODE_PROXY;
+       s->rep->analysers = 0;
+       http_silent_debug(__LINE__, s);
+@@ -7553,7 +7554,6 @@ void http_reset_txn(struct session *s)
+       http_init_txn(s);
+       s->be = s->fe;
+-      s->req->analysers = s->listener->analysers;
+       s->logs.logwait = s->fe->to_log;
+       s->srv = s->prev_srv = s->srv_conn = NULL;
+       /* re-init store persistence */
+Index: haproxy-1.4.19/src/session.c
+===================================================================
+--- haproxy-1.4.19.orig/src/session.c
++++ haproxy-1.4.19/src/session.c
+@@ -1055,6 +1055,12 @@ resync_stream_interface:
+                       while (ana_list && max_loops--) {
+                               /* Warning! ensure that analysers are always placed in ascending order! */
++                              if (ana_list & AN_REQ_DECODE_PROXY) {
++                                      if (!frontend_decode_proxy_request(s, s->req, AN_REQ_DECODE_PROXY))
++                                              break;
++                                      UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_DECODE_PROXY);
++                              }
++
+                               if (ana_list & AN_REQ_INSPECT) {
+                                       if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT))
+                                               break;
+Index: haproxy-1.4.19/src/standard.c
+===================================================================
+--- haproxy-1.4.19.orig/src/standard.c
++++ haproxy-1.4.19/src/standard.c
+@@ -569,6 +569,11 @@ unsigned int strl2uic(const char *s, int
+       return __strl2uic(s, len);
+ }
++unsigned int read_uint(const char **s, const char *end)
++{
++      return __read_uint(s, end);
++}
++
+ /* This one is 7 times faster than strtol() on athlon with checks.
+  * It returns the value of the number composed of all valid digits read,
+  * and can process negative numbers too.