diff --git a/net/haproxy/Makefile b/net/haproxy/Makefile new file mode 100644 index 000000000..604646a62 --- /dev/null +++ b/net/haproxy/Makefile @@ -0,0 +1,62 @@ +# +# Copyright (C) 2009-2014 Thomas Heil +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=haproxy +PKG_VERSION:=1.4.25 +PKG_RELEASE:=01 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://haproxy.1wt.eu/download/1.4/src +PKG_MD5SUM:=74b5ec1f0f9b4d148c8083bcfb512ccd +PKG_MAINTAINER:=Thomas Heil +PKG_LICENSE:=GPL-2.0 + +include $(INCLUDE_DIR)/package.mk + +define Package/haproxy + SUBMENU:=Web Servers/Proxies + SECTION:=net + CATEGORY:=Network + TITLE:=The Reliable, High Performance TCP/HTTP Load Balancer + URL:=http://haproxy.1wt.eu/ + DEPENDS:=+libpcre +libltdl +endef + +define Package/haproxy/conffiles +/etc/haproxy.cfg +endef + +define Package/haproxy/description + Open source High Performance TCP/HTTP Load Balancer +endef + +define Build/Compile + $(MAKE) TARGET=linux2628 -C $(PKG_BUILD_DIR) \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + CC="$(TARGET_CC)" \ + CFLAGS="$(TARGET_CFLAGS)" \ + LD="$(TARGET_CC)" \ + LDFLAGS="$(TARGET_LDFLAGS)" \ + SMALL_OPTS="-DBUFSIZE=16384 -DMAXREWRITE=8192 -DSYSTEM_MAXCONN=65530" USE_LINUX_TPROXY=1 USE_LINUX_SPLICE=1 \ + VERSION="$(PKG_VERSION)-patch$(PKG_RELEASE)" \ + all install +endef + +define Package/haproxy/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/haproxy $(1)/usr/sbin/ + $(INSTALL_DIR) $(1)/etc + $(INSTALL_CONF) ./files/haproxy.cfg $(1)/etc/ + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/haproxy.init $(1)/etc/init.d/haproxy + $(INSTALL_DIR) $(1)/etc/hotplug.d/net + $(INSTALL_BIN) ./files/haproxy.hotplug $(1)/etc/hotplug.d/net/90-haproxy +endef + +$(eval $(call BuildPackage,haproxy)) diff --git a/net/haproxy/files/haproxy.cfg b/net/haproxy/files/haproxy.cfg new file mode 100644 index 000000000..a54f5f5dd --- /dev/null +++ b/net/haproxy/files/haproxy.cfg @@ -0,0 +1,100 @@ +# Example configuration file for HAProxy 1.3, refer to the url below for +# a full documentation and examples for configuration: +# http://haproxy.1wt.eu/download/1.3/doc/configuration.txt + + +# Global parameters +global + + # Log events to a remote syslog server at given address using the + # specified facility and verbosity level. Multiple log options + # are allowed. + #log 10.0.0.1 daemon info + + # Specifiy the maximum number of allowed connections. + maxconn 32000 + + # Raise the ulimit for the maximum allowed number of open socket + # descriptors per process. This is usually at least twice the + # number of allowed connections (maxconn * 2 + nb_servers + 1) . + ulimit-n 65535 + + # Drop privileges (setuid, setgid), default is "root" on OpenWrt. + uid 0 + gid 0 + + # Perform chroot into the specified directory. + #chroot /var/run/haproxy/ + + # Daemonize on startup + daemon + + nosplice + # Enable debugging + #debug + + # Spawn given number of processes and distribute load among them, + # used for multi-core environments or to circumvent per-process + # limits like number of open file descriptors. Default is 1. + #nbproc 2 + + +# Example HTTP proxy listener +listen my_http_proxy + + # Bind to port 81 and 444 on all interfaces (0.0.0.0) + bind :81,:444 + + # We're proxying HTTP here... + mode http + + # Simple HTTP round robin over two servers using the specified + # source ip 192.168.1.1 . + balance roundrobin + server server01 192.168.1.10:80 source 192.168.1.1 + server server02 192.168.1.20:80 source 192.168.1.1 + + # Serve an internal statistics page on /stats: + stats enable + stats uri /stats + + # Enable HTTP basic auth for the statistics: + stats realm HA_Stats + stats auth username:password + + +# Example SMTP proxy listener +listen my_smtp_proxy + + # Disable this instance without commenting out the section. + disabled + + # Bind to port 26 and 588 on localhost + bind 127.0.0.1:26,127.0.0.1:588 + + # This is a TCP proxy + mode tcp + + # Round robin load balancing over two servers on port 123 forcing + # the address 192.168.1.1 and port 25 as source. + balance roundrobin + #use next line for transparent proxy, so the servers can see the + #original ip-address and remove source keyword in server definition + #source 0.0.0.0 usesrc clientip + server server01 192.168.1.10:123 source 192.168.1.1:25 + server server02 192.168.1.20:123 source 192.168.1.1:25 + + +# Special health check listener for integration with external load +# balancers. +listen local_health_check + + # Listen on port 60000 + bind :60000 + + # This is a health check + mode health + + # Enable HTTP-style responses: "HTTP/1.0 200 OK" + # else just print "OK". + #option httpchk diff --git a/net/haproxy/files/haproxy.hotplug b/net/haproxy/files/haproxy.hotplug new file mode 100644 index 000000000..d14b5bf3f --- /dev/null +++ b/net/haproxy/files/haproxy.hotplug @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ "$ACTION" = add ]; then + + /etc/init.d/haproxy enabled && \ + /etc/init.d/haproxy start +fi + diff --git a/net/haproxy/files/haproxy.init b/net/haproxy/files/haproxy.init new file mode 100644 index 000000000..96b13badd --- /dev/null +++ b/net/haproxy/files/haproxy.init @@ -0,0 +1,23 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2009-2010 OpenWrt.org + +START=99 +STOP=80 + +SERVICE_USE_PID=1 + +HAPROXY_BIN="/usr/sbin/haproxy" +HAPROXY_CONFIG="/etc/haproxy.cfg" +HAPROXY_PID="/var/run/haproxy.pid" + +start() { + service_start $HAPROXY_BIN -q -D -f "$HAPROXY_CONFIG" -p "$HAPROXY_PID" +} + +stop() { + service_stop $HAPROXY_BIN +} + +reload() { + $HAPROXY_BIN -D -q -f $HAPROXY_CONFIG -p $HAPROXY_PID -sf $(cat $HAPROXY_PID) +} 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 index 000000000..401d57ffd --- /dev/null +++ b/net/haproxy/patches/001-haproxy-1.4.x-sendproxy.patch @@ -0,0 +1,506 @@ +From af2038557a14bf6e2915bed545e216a0f1a95fc5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cyril=20Bont=C3=A9?= +Date: Mon, 15 Apr 2013 22:05:00 +0200 +Subject: [PATCH] Proxy Protocol based on haproxy 1.4.23 + +--- + doc/configuration.txt | 26 ++++++- + include/common/standard.h | 25 ++++++- + include/proto/client.h | 1 + + include/types/buffers.h | 20 ++--- + include/types/protocols.h | 1 + + src/cfgparse.c | 15 +++- + src/client.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++ + src/proto_http.c | 4 +- + src/session.c | 7 ++ + src/standard.c | 9 ++- + 10 files changed, 275 insertions(+), 19 deletions(-) + +Index: haproxy-1.4.25/doc/configuration.txt +=================================================================== +--- haproxy-1.4.25.orig/doc/configuration.txt ++++ haproxy-1.4.25/doc/configuration.txt +@@ -1343,6 +1343,7 @@ bind [
]: [, ...] tr + bind [
]: [, ...] id + bind [
]: [, ...] name + bind [
]: [, ...] defer-accept ++bind [
]: [, ...] 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 +@@ -1423,6 +1424,19 @@ bind [
]: [, ...] 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 +@@ -1433,8 +1447,10 @@ bind [
]: [, ...] 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 | ] ... +@@ -7257,7 +7273,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. + +@@ -7430,7 +7448,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.25/include/common/standard.h +=================================================================== +--- haproxy-1.4.25.orig/include/common/standard.h ++++ haproxy-1.4.25/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 ++ * and returns it. The pointer is adjusted to point to the first unread ++ * char. The function automatically stops at . ++ */ ++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,9 +298,10 @@ 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); ++unsigned int inetaddr_host_lim_ret(char *text, char *stop, char **ret); + + static inline char *cut_crlf(char *s) { + +Index: haproxy-1.4.25/include/proto/client.h +=================================================================== +--- haproxy-1.4.25.orig/include/proto/client.h ++++ haproxy-1.4.25/include/proto/client.h +@@ -25,6 +25,7 @@ + #include + #include + ++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.25/include/types/buffers.h +=================================================================== +--- haproxy-1.4.25.orig/include/types/buffers.h ++++ haproxy-1.4.25/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.25/include/types/protocols.h +=================================================================== +--- haproxy-1.4.25.orig/include/types/protocols.h ++++ haproxy-1.4.25/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.25/src/cfgparse.c +=================================================================== +--- haproxy-1.4.25.orig/src/cfgparse.c ++++ haproxy-1.4.25/src/cfgparse.c +@@ -1467,6 +1467,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; + +@@ -1519,7 +1529,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; +@@ -5743,6 +5753,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.25/src/client.c +=================================================================== +--- haproxy-1.4.25.orig/src/client.c ++++ haproxy-1.4.25/src/client.c +@@ -22,6 +22,7 @@ + + #include + #include ++#include + #include + + #include +@@ -43,6 +44,191 @@ + #include + + ++/* This analyser tries to fetch a line from the request buffer which looks like : ++ * ++ * "PROXY" PROTO SRC3 DST3 SRC4 "\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.25/src/proto_http.c +=================================================================== +--- haproxy-1.4.25.orig/src/proto_http.c ++++ haproxy-1.4.25/src/proto_http.c +@@ -4209,7 +4209,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); +@@ -7807,7 +7808,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.25/src/session.c +=================================================================== +--- haproxy-1.4.25.orig/src/session.c ++++ haproxy-1.4.25/src/session.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1083,6 +1084,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.25/src/standard.c +=================================================================== +--- haproxy-1.4.25.orig/src/standard.c ++++ haproxy-1.4.25/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. +@@ -993,12 +998,12 @@ unsigned int inetaddr_host_lim(const cha + * Idem except the pointer to first unparsed byte is returned into which + * must not be NULL. + */ +-unsigned int inetaddr_host_lim_ret(const char *text, char *stop, const char **ret) ++unsigned int inetaddr_host_lim_ret(char *text, char *stop, char **ret) + { + const unsigned int ascii_zero = ('0' << 24) | ('0' << 16) | ('0' << 8) | '0'; + register unsigned int dig100, dig10, dig1; + int s; +- const char *p, *d; ++ char *p, *d; + + dig1 = dig10 = dig100 = ascii_zero; + s = 24;