source: packages/net/haproxy/patches/001-haproxy-1.4.x-sendproxy.patch @ 29702

Last change on this file since 29702 was 29702, checked in by heil, 5 years ago

package: haproxy

  • bump to version 1.4.19
  • ensure haproxy is not listen on port 80 by default
  • add sendproxy patch written by Cyril Bonte
File size: 16.7 KB
  • doc/configuration.txt

    old new bind [<address>]:<port_range> [, ...] tr 
    13371337bind [<address>]:<port_range> [, ...] id <id> 
    13381338bind [<address>]:<port_range> [, ...] name <name> 
    13391339bind [<address>]:<port_range> [, ...] defer-accept 
     1340bind [<address>]:<port_range> [, ...] accept-proxy 
    13401341  Define one or several listening addresses and/or ports in a frontend. 
    13411342  May be used in sections :   defaults | frontend | listen | backend 
    13421343                                  no   |    yes   |   yes  |   no 
    bind [<address>]:<port_range> [, ...] de 
    14171418                  with front firewalls which would see an established 
    14181419                  connection while the proxy will only see it in SYN_RECV. 
    14191420 
     1421    accept-proxy  is an optional keyword which enforces use of the PROXY 
     1422                  protocol over any connection accepted by this listener. The 
     1423                  PROXY protocol dictates the layer 3/4 addresses of the 
     1424                  incoming connection to be used everywhere an address is used, 
     1425                  with the only exception of "tcp-request connection" rules 
     1426                  which will only see the real connection address. Logs will 
     1427                  reflect the addresses indicated in the protocol, unless it is 
     1428                  violated, in which case the real address will still be used. 
     1429                  This keyword combined with support from external components 
     1430                  can be used as an efficient and reliable alternative to the 
     1431                  X-Forwarded-For mechanism which is not always reliable and 
     1432                  not even always usable. 
     1433 
    14201434  It is possible to specify a list of address:port combinations delimited by 
    14211435  commas. The frontend will then listen on all of these addresses. There is no 
    14221436  fixed limit to the number of addresses and ports which can be listened on in 
    bind [<address>]:<port_range> [, ...] de 
    14271441        listen http_proxy 
    14281442            bind :80,:443 
    14291443            bind 10.0.0.1:10080,10.0.0.1:10443 
     1444            bind 127.0.0.1:8443 accept-proxy 
    14301445 
    1431   See also : "source". 
     1446  See also : "source", "option forwardfor" and the PROXY protocol 
     1447             documentation. 
    14321448 
    14331449 
    14341450bind-process [ all | odd | even | <number 1-32> ] ... 
    marked with a star ('*') after the field 
    72157231 
    72167232Detailed fields description : 
    72177233  - "client_ip" is the IP address of the client which initiated the TCP 
    7218     connection to haproxy. 
     7234    connection to haproxy. Note that when the connection is accepted on a 
     7235    socket configured with "accept-proxy" and the PROXY protocol is correctly 
     7236    used, then the logs will reflect the forwarded connection's information. 
    72197237 
    72207238  - "client_port" is the TCP port of the client which initiated the connection. 
    72217239 
    with a star ('*') after the field name b 
    73887406 
    73897407Detailed fields description : 
    73907408  - "client_ip" is the IP address of the client which initiated the TCP 
    7391     connection to haproxy. 
     7409    connection to haproxy. Note that when the connection is accepted on a 
     7410    socket configured with "accept-proxy" and the PROXY protocol is correctly 
     7411    used, then the logs will reflect the forwarded connection's information. 
    73927412 
    73937413  - "client_port" is the TCP port of the client which initiated the connection. 
    73947414 
  • include/common/standard.h

    old new static inline unsigned int __strl2uic(co 
    269269        return i; 
    270270} 
    271271 
     272/* This function reads an unsigned integer from the string pointed to by <s> 
     273 * and returns it. The <s> pointer is adjusted to point to the first unread 
     274 * char. The function automatically stops at <end>. 
     275 */ 
     276static inline unsigned int __read_uint(const char **s, const char *end) 
     277{ 
     278        const char *ptr = *s; 
     279        unsigned int i = 0; 
     280        unsigned int j, k; 
     281 
     282        while (ptr < end) { 
     283                j = *ptr - '0'; 
     284                k = i * 10; 
     285                if (j > 9) 
     286                        break; 
     287                i = k + j; 
     288                ptr++; 
     289        } 
     290        *s = ptr; 
     291        return i; 
     292} 
     293 
    272294extern unsigned int str2ui(const char *s); 
    273295extern unsigned int str2uic(const char *s); 
    274296extern unsigned int strl2ui(const char *s, int len); 
    extern unsigned int strl2uic(const char  
    276298extern int strl2ic(const char *s, int len); 
    277299extern int strl2irc(const char *s, int len, int *ret); 
    278300extern int strl2llrc(const char *s, int len, long long *ret); 
     301extern unsigned int read_uint(const char **s, const char *end); 
    279302unsigned int inetaddr_host(const char *text); 
    280303unsigned int inetaddr_host_lim(const char *text, const char *stop); 
    281304unsigned int inetaddr_host_lim_ret(const char *text, char *stop, const char **ret); 
  • include/proto/client.h

    old new  
    2525#include <common/config.h> 
    2626#include <types/session.h> 
    2727 
     28int frontend_decode_proxy_request(struct session *s, struct buffer *req, int an_bit); 
    2829void get_frt_addr(struct session *s); 
    2930int event_accept(int fd); 
    3031 
  • include/types/buffers.h

    old new  
    135135 * The field is blanked by buffer_init() and only by analysers themselves 
    136136 * afterwards. 
    137137 */ 
    138 #define AN_REQ_INSPECT          0x00000001  /* inspect request contents */ 
    139 #define AN_REQ_WAIT_HTTP        0x00000002  /* wait for an HTTP request */ 
    140 #define AN_REQ_HTTP_PROCESS_FE  0x00000004  /* process the frontend's HTTP part */ 
    141 #define AN_REQ_SWITCHING_RULES  0x00000008  /* apply the switching rules */ 
    142 #define AN_REQ_HTTP_PROCESS_BE  0x00000010  /* process the backend's HTTP part */ 
    143 #define AN_REQ_HTTP_INNER       0x00000020  /* inner processing of HTTP request */ 
    144 #define AN_REQ_HTTP_TARPIT      0x00000040  /* wait for end of HTTP tarpit */ 
    145 #define AN_REQ_HTTP_BODY        0x00000080  /* inspect HTTP request body */ 
    146 #define AN_REQ_STICKING_RULES   0x00000100  /* table persistence matching */ 
    147 /* unused: 0x200 */ 
     138#define AN_REQ_DECODE_PROXY     0x00000001  /* take the proxied address from a 'PROXY' line */ 
     139#define AN_REQ_INSPECT          0x00000002  /* inspect request contents */ 
     140#define AN_REQ_WAIT_HTTP        0x00000004  /* wait for an HTTP request */ 
     141#define AN_REQ_HTTP_PROCESS_FE  0x00000008  /* process the frontend's HTTP part */ 
     142#define AN_REQ_SWITCHING_RULES  0x00000010  /* apply the switching rules */ 
     143#define AN_REQ_HTTP_PROCESS_BE  0x00000020  /* process the backend's HTTP part */ 
     144#define AN_REQ_HTTP_INNER       0x00000040  /* inner processing of HTTP request */ 
     145#define AN_REQ_HTTP_TARPIT      0x00000080  /* wait for end of HTTP tarpit */ 
     146#define AN_REQ_HTTP_BODY        0x00000100  /* inspect HTTP request body */ 
     147#define AN_REQ_STICKING_RULES   0x00000200  /* table persistence matching */ 
    148148#define AN_REQ_PRST_RDP_COOKIE  0x00000400  /* persistence on rdp cookie */ 
    149149#define AN_REQ_HTTP_XFER_BODY   0x00000800  /* forward request body */ 
    150150 
  • include/types/protocols.h

    old new  
    7272#define LI_O_FOREIGN    0x0002  /* permit listening on foreing addresses */ 
    7373#define LI_O_NOQUICKACK 0x0004  /* disable quick ack of immediate data (linux) */ 
    7474#define LI_O_DEF_ACCEPT 0x0008  /* wait up to 1 second for data before accepting */ 
     75#define LI_O_ACC_PROXY  0x0010  /* find the proxied address in the first request line */ 
    7576 
    7677/* The listener will be directly referenced by the fdtab[] which holds its 
    7778 * socket. The listener provides the protocol-specific accept() function to 
  • src/cfgparse.c

    old new int cfg_parse_listen(const char *file, i 
    14641464#endif 
    14651465                        } 
    14661466 
     1467                        if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */ 
     1468                                struct listener *l; 
     1469 
     1470                                for (l = curproxy->listen; l != last_listen; l = l->next) 
     1471                                        l->options |= LI_O_ACC_PROXY; 
     1472 
     1473                                cur_arg ++; 
     1474                                continue; 
     1475                        } 
     1476 
    14671477                        if (!strcmp(args[cur_arg], "name")) { 
    14681478                                struct listener *l; 
    14691479 
    int cfg_parse_listen(const char *file, i 
    15161526                                continue; 
    15171527                        } 
    15181528 
    1519                         Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n", 
     1529                        Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n", 
    15201530                              file, linenum, args[0]); 
    15211531                        err_code |= ERR_ALERT | ERR_FATAL; 
    15221532                        goto out; 
    out_uri_auth_compat: 
    57025712                        listener->handler = process_session; 
    57035713                        listener->analysers |= curproxy->fe_req_ana; 
    57045714 
     5715                        if (listener->options & LI_O_ACC_PROXY) 
     5716                                listener->analysers |= AN_REQ_DECODE_PROXY; 
     5717 
    57055718                        /* smart accept mode is automatic in HTTP mode */ 
    57065719                        if ((curproxy->options2 & PR_O2_SMARTACC) || 
    57075720                            (curproxy->mode == PR_MODE_HTTP && 
  • haproxy-1.4.19

    old new  
    2222 
    2323#include <common/compat.h> 
    2424#include <common/config.h> 
     25#include <common/debug.h> 
    2526#include <common/time.h> 
    2627 
    2728#include <types/global.h> 
     
    4344#include <proto/task.h> 
    4445 
    4546 
     47/* This analyser tries to fetch a line from the request buffer which looks like : 
     48 * 
     49 *   "PROXY" <SP> PROTO <SP> SRC3 <SP> DST3 <SP> SRC4 <SP> <DST4> "\r\n" 
     50 * 
     51 * There must be exactly one space between each field. Fields are : 
     52 *  - PROTO : layer 4 protocol, which must be "TCP4" or "TCP6". 
     53 *  - SRC3  : layer 3 (eg: IP) source address in standard text form 
     54 *  - DST3  : layer 3 (eg: IP) destination address in standard text form 
     55 *  - SRC4  : layer 4 (eg: TCP port) source address in standard text form 
     56 *  - DST4  : layer 4 (eg: TCP port) destination address in standard text form 
     57 * 
     58 * This line MUST be at the beginning of the buffer and MUST NOT wrap. 
     59 * 
     60 * Once the data is fetched, the values are set in the session's field and data 
     61 * are removed from the buffer. The function returns zero if it needs to wait 
     62 * for more data (max: timeout_client), or 1 if it has finished and removed itself. 
     63 */ 
     64int frontend_decode_proxy_request(struct session *s, struct buffer *req, int an_bit) 
     65{ 
     66        char *line = req->data; 
     67        char *end = req->data + req->l; 
     68        int len; 
     69 
     70        DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n", 
     71                now_ms, __FUNCTION__, 
     72                s, 
     73                req, 
     74                req->rex, req->wex, 
     75                req->flags, 
     76                req->l, 
     77                req->analysers); 
     78 
     79        if (req->flags & (BF_READ_ERROR|BF_READ_TIMEOUT)) 
     80                goto fail; 
     81 
     82        len = MIN(req->l, 6); 
     83        if (!len) 
     84                goto missing; 
     85 
     86        /* Decode a possible proxy request, fail early if it does not match */ 
     87        if (strncmp(line, "PROXY ", len) != 0) 
     88                goto fail; 
     89 
     90        line += 6; 
     91        if (req->l < 18) /* shortest possible line */ 
     92                goto missing; 
     93 
     94        if (!memcmp(line, "TCP4 ", 5) != 0) { 
     95                u32 src3, dst3, sport, dport; 
     96 
     97                line += 5; 
     98 
     99                src3 = inetaddr_host_lim_ret(line, end, &line); 
     100                if (line == end) 
     101                        goto missing; 
     102                if (*line++ != ' ') 
     103                        goto fail; 
     104 
     105                dst3 = inetaddr_host_lim_ret(line, end, &line); 
     106                if (line == end) 
     107                        goto missing; 
     108                if (*line++ != ' ') 
     109                        goto fail; 
     110 
     111                sport = read_uint((const char **)&line, end); 
     112                if (line == end) 
     113                        goto missing; 
     114                if (*line++ != ' ') 
     115                        goto fail; 
     116 
     117                dport = read_uint((const char **)&line, end); 
     118                if (line > end - 2) 
     119                        goto missing; 
     120                if (*line++ != '\r') 
     121                        goto fail; 
     122                if (*line++ != '\n') 
     123                        goto fail; 
     124 
     125                /* update the session's addresses and mark them set */ 
     126                ((struct sockaddr_in *)&s->cli_addr)->sin_family      = AF_INET; 
     127                ((struct sockaddr_in *)&s->cli_addr)->sin_addr.s_addr = htonl(src3); 
     128                ((struct sockaddr_in *)&s->cli_addr)->sin_port        = htons(sport); 
     129 
     130                ((struct sockaddr_in *)&s->frt_addr)->sin_family      = AF_INET; 
     131                ((struct sockaddr_in *)&s->frt_addr)->sin_addr.s_addr = htonl(dst3); 
     132                ((struct sockaddr_in *)&s->frt_addr)->sin_port        = htons(dport); 
     133                s->flags |= SN_FRT_ADDR_SET; 
     134 
     135        } 
     136        else if (!memcmp(line, "TCP6 ", 5) != 0) { 
     137                u32 sport, dport; 
     138                char *src_s; 
     139                char *dst_s, *sport_s, *dport_s; 
     140                struct in6_addr src3, dst3; 
     141 
     142                line+=5; 
     143 
     144                src_s = line; 
     145                dst_s = sport_s = dport_s = NULL; 
     146                while (1) { 
     147                        if (line > end - 2) { 
     148                                goto missing; 
     149                        } 
     150                        else if (*line == '\r') { 
     151                                *line = 0; 
     152                                line++; 
     153                                if (*line++ != '\n') 
     154                                        goto fail; 
     155                                break; 
     156                        } 
     157 
     158                        if (*line == ' ') { 
     159                                *line = 0; 
     160                                if (!dst_s) 
     161                                        dst_s = line+1; 
     162                                else if (!sport_s) 
     163                                        sport_s = line+1; 
     164                                else if (!dport_s) 
     165                                        dport_s = line+1; 
     166                        } 
     167                        line++; 
     168                } 
     169 
     170                if (!dst_s || !sport_s || !dport_s) 
     171                        goto fail; 
     172 
     173                sport = read_uint((const char **)&sport_s,dport_s-1); 
     174                if ( *sport_s != 0 ) 
     175                        goto fail; 
     176 
     177                dport = read_uint((const char **)&dport_s,line-2); 
     178                if ( *dport_s != 0 ) 
     179                        goto fail; 
     180 
     181                if (inet_pton(AF_INET6, src_s, (void *)&src3) != 1) 
     182                        goto fail; 
     183 
     184                if (inet_pton(AF_INET6, dst_s, (void *)&dst3) != 1) 
     185                        goto fail; 
     186 
     187                /* update the session's addresses and mark them set */ 
     188                ((struct sockaddr_in6 *)&s->cli_addr)->sin6_family      = AF_INET6; 
     189                memcpy(&((struct sockaddr_in6 *)&s->cli_addr)->sin6_addr, &src3, sizeof(struct in6_addr)); 
     190                ((struct sockaddr_in6 *)&s->cli_addr)->sin6_port        = htons(sport); 
     191 
     192                ((struct sockaddr_in6 *)&s->frt_addr)->sin6_family      = AF_INET6; 
     193                memcpy(&((struct sockaddr_in6 *)&s->frt_addr)->sin6_addr, &dst3, sizeof(struct in6_addr)); 
     194                ((struct sockaddr_in6 *)&s->frt_addr)->sin6_port        = htons(dport); 
     195                s->flags |= SN_FRT_ADDR_SET; 
     196        } 
     197        else { 
     198                goto fail; 
     199        } 
     200 
     201        /* remove the PROXY line from the request */ 
     202        len = line - req->data; 
     203        buffer_replace2(req, req->data, line, NULL, 0); 
     204        req->total -= len; /* don't count the header line */ 
     205 
     206        req->analysers &= ~an_bit; 
     207        return 1; 
     208 
     209 missing: 
     210        if (!(req->flags & (BF_SHUTR|BF_FULL))) { 
     211                buffer_dont_connect(s->req); 
     212                return 0; 
     213        } 
     214        /* missing data and buffer is either full or shutdown => fail */ 
     215 
     216 fail: 
     217        buffer_abort(req); 
     218        buffer_abort(s->rep); 
     219        req->analysers = 0; 
     220 
     221        s->fe->counters.failed_req++; 
     222        if (s->listener->counters) 
     223                s->listener->counters->failed_req++; 
     224 
     225        if (!(s->flags & SN_ERR_MASK)) 
     226                s->flags |= SN_ERR_PRXCOND; 
     227        if (!(s->flags & SN_FINST_MASK)) 
     228                s->flags |= SN_FINST_R; 
     229        return 0; 
     230} 
     231 
    46232/* Retrieves the original destination address used by the client, and sets the 
    47233 * SN_FRT_ADDR_SET flag. 
    48234 */ 
  • src/proto_http.c

    old new void http_end_txn_clean_session(struct s 
    40284028        if (s->rep->lr >= s->rep->data + s->rep->size) 
    40294029                s->rep->lr -= s->req->size; 
    40304030 
    4031         s->req->analysers |= s->fe->fe_req_ana; 
     4031        s->req->analysers = s->fe->fe_req_ana; 
     4032        s->req->analysers &= ~AN_REQ_DECODE_PROXY; 
    40324033        s->rep->analysers = 0; 
    40334034 
    40344035        http_silent_debug(__LINE__, s); 
    void http_reset_txn(struct session *s) 
    75537554        http_init_txn(s); 
    75547555 
    75557556        s->be = s->fe; 
    7556         s->req->analysers = s->listener->analysers; 
    75577557        s->logs.logwait = s->fe->to_log; 
    75587558        s->srv = s->prev_srv = s->srv_conn = NULL; 
    75597559        /* re-init store persistence */ 
  • src/session.c

    old new resync_stream_interface: 
    10551055                        while (ana_list && max_loops--) { 
    10561056                                /* Warning! ensure that analysers are always placed in ascending order! */ 
    10571057 
     1058                                if (ana_list & AN_REQ_DECODE_PROXY) { 
     1059                                        if (!frontend_decode_proxy_request(s, s->req, AN_REQ_DECODE_PROXY)) 
     1060                                                break; 
     1061                                        UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_DECODE_PROXY); 
     1062                                } 
     1063 
    10581064                                if (ana_list & AN_REQ_INSPECT) { 
    10591065                                        if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT)) 
    10601066                                                break; 
  • src/standard.c

    old new unsigned int strl2uic(const char *s, int 
    569569        return __strl2uic(s, len); 
    570570} 
    571571 
     572unsigned int read_uint(const char **s, const char *end) 
     573{ 
     574        return __read_uint(s, end); 
     575} 
     576 
    572577/* This one is 7 times faster than strtol() on athlon with checks. 
    573578 * It returns the value of the number composed of all valid digits read, 
    574579 * and can process negative numbers too. 
Note: See TracBrowser for help on using the repository browser.