Commit Graph

3201 Commits

Author SHA1 Message Date
Willy Tarreau
379357af58 BUG/MAJOR: http: always ensure response buffer has some room for a response
Since 1.5-dev12 and commit 3bf1b2b8 (MAJOR: channel: stop relying on
BF_FULL to take action), the HTTP parser switched to channel_full()
instead of BF_FULL to decide whether a buffer had enough room to start
parsing a request or response. The problem is that channel_full()
intentionally ignores outgoing data, so a corner case exists where a
large response might still be left in a response buffer with just a
few bytes left (much less than the reserve), enough to accept a second
response past the last data, but not enough to permit the HTTP processor
to add some headers. Since all the processing relies on this space being
available, we can get some random crashes when clients pipeline requests.

The analysis of a core from haproxy configured with 20480 bytes buffers
shows this : with enough "luck", when sending back the response for the
first request, the client is slow, the TCP window is congested, the socket
buffers are full, and haproxy's buffer fills up. We still have 20230 bytes
of response data in a 20480 response buffer. The second request is sent to
the server which returns 214 bytes which fit in the small 250 bytes left
in this buffer. And the buffer arrangement makes it possible to escape all
the controls in http_wait_for_response() :

    |<------ response buffer = 20480 bytes ------>|
    [ 2/2  | 3 | 4 |          1/2                 ]
           ^ start of circular buffer

      1/2 = beginning of previous response (18240)
      2/2 = end of previous response       (1990)
        3 = current response               (214)
        4 = free space                     (36)

  - channel_full() returns false (20230 bytes are going to leave)
  - the response headers does not wrap at the end of the buffer
  - the remaining linear room after the headers is larger than the
    reserve, because it's the previous response which wraps :
  => response is processed

Header rewriting causes it to reach 260 bytes, 10 bytes larger than what
the buffer could hold. So all computations during header addition are
wrong and lead to the corruption we've observed.

All the conditions are very hard to meet (which explains why it took
almost one year for this bug to show up) and are almost impossible to
reproduce on purpose on a test platform. But the bug is clearly there.

This issue was reported by Dinko Korunic who kindly devoted a lot of
time to provide countless traces and cores, and to experiment with
troubleshooting patches to knock the bug down. Thanks Dinko!

No backport is needed, but all 1.5-dev versions between dev12 and dev18
included must be upgraded. A workaround consists in setting option
forceclose to prevent pipelined requests from being processed.
2013-06-08 13:14:17 +02:00
Emmanuel Hocdet
79274e2c40 BUG: ssl: fix crt-list for clients not supporting SNI
I left a mistake in my previous patch bringing the crt-list feature,
it breaks clients with no SNI support.

Also remove the useless wildp = NULL as per a previous discussion.
2013-05-31 13:59:35 +02:00
Kevin Hester
cad8234b00 BUG: ssl: send payload gets corrupted if tune.ssl.maxrecord is used
We were using "tune.ssl.maxrecord 2000" and discovered an interesting
problem: SSL data sent from the server to the client showed occasional
corruption of the payload data.

The root cause was:
When ssl_max_record is smaller than the requested send amount
the ring buffer wrapping wasn't properly adjusting the
number of bytes to send.

I solved this by selecting the initial size based on the number
of output bytes that can be sent without splitting _before_ checking
against ssl_max_record.
2013-05-31 12:17:04 +02:00
Willy Tarreau
ba2ffd18b5 MEDIUM: counters: add a new "gpc0_rate" counter in stick-tables
This counter is special in that instead of reporting the gpc0 cumulative
count, it returns its increase rate over the configured period.
2013-05-29 15:54:14 +02:00
Willy Tarreau
e25c917af8 MEDIUM: counters: add support for tracking a third counter
We're often missin a third counter to track base, src and base+src at
the same time. Here we introduce track_sc3 to have this third counter.
It would be wise not to add much more counters because that slightly
increases the session size and processing time though the real issue
is more the declaration of the keywords in the code and in the doc.
2013-05-29 00:37:16 +02:00
Willy Tarreau
d5ca9abb0d MINOR: counters: make it easier to extend the amount of tracked counters
By properly affecting the flags and values, it becomes easier to add
more tracked counters, for example for experimentation. It also slightly
reduces the code and the number of tests. No counters were added with
this patch.
2013-05-28 17:43:40 +02:00
Lukas Tribus
3fe9f1e131 DOC: readme: add suggestion to link against static openssl
Adds a suggestion in README howto link against a static build of openssl.

This is useful if the OS includes an old openssl releas and recent features
or ciphers are required.
2013-05-27 13:52:56 +02:00
Willy Tarreau
5e80e02c2b DOC: fix wrong copy-paste in the rspdel example
As reported by Cristian Ditoiu, the rspdel example is based on the reqrep
action, which is quite confusing!
2013-05-25 08:31:25 +02:00
Prach Pongpanich
b837e68fc9 CLEANUP: fix minor typo in error message.
"accomodate" => "accommodate".
2013-05-14 20:56:28 +02:00
James Voth
a051b4aa3a MINOR: ssl: add pattern fetch 'ssl_c_sha1'
This new pattern fetch returns the client certificate's SHA-1 fingerprint
(i.e. SHA-1 hash of DER-encoded certificate) in a binary chunk.

This can be useful to pass it to a server in a header or to stick a client
to a server across multiple SSL connections.
2013-05-14 20:55:30 +02:00
Pieter Baauw
06da4df056 DOC: examples: provide an example of transparent proxy configuration for FreeBSD 8
There is very little documentation on how to make haproxy work in
transparent mode under FreeBSD, so let's start with this example.
2013-05-11 08:03:57 +02:00
Pieter Baauw
1eb7592bba MINOR: tproxy: add support for OpenBSD
OpenBSD uses (SOL_SOCKET, SO_BINDANY) to enable transparent
proxy on a socket.

This patch adds support for the relevant setsockopt() calls.
2013-05-11 08:03:50 +02:00
Pieter Baauw
ff30b6667b MINOR: tproxy: add support for FreeBSD
FreeBSD uses (IPPROTO_IP, IP_BINDANY) and (IPPROTO_IPV6, IPV6_BINDANY)
to enable transparent proxy on a socket.

This patch adds support for the relevant setsockopt() calls.
2013-05-11 08:03:43 +02:00
Pieter Baauw
d551fb5a8d REORG: tproxy: prepare the transparent proxy defines for accepting other OSes
This patch does not change the logic of the code, it only changes the
way OS-specific defines are tested.

At the moment the transparent proxy code heavily depends on Linux-specific
defines. This first patch introduces a new define "CONFIG_HAP_TRANSPARENT"
which is set every time the defines used by transparent proxy are present.
This also means that with an up-to-date libc, it should not be necessary
anymore to force CONFIG_HAP_LINUX_TPROXY during the build, as the flags
will automatically be detected.

The CTTPROXY flags still remain separate because this older API doesn't
work the same way.

A new line has been added in the version output for haproxy -vv to indicate
what transparent proxy support is available.
2013-05-11 08:03:37 +02:00
Willy Tarreau
dd11293e84 BUG/MINOR: acl: fix a double free during exit when using PCRE_JIT
When freeing ACL regex, we don't want to perform the free() in regex_free()
as it's already performed in free_pattern(). The double free only happens
when using PCRE_JIT when freeing everything during exit so it's harmless
but exhibits libc errors during a reload/restart.

Bug reported by Seri.
2013-05-08 18:14:18 +02:00
Emmanuel Hocdet
7c41a1b59b MEDIUM: ssl: improve crt-list format to support negation
Improve the crt-list file format to allow a rule to negate a certain SNI :

        <crtfile> [[!]<snifilter> ...]

This can be useful when a domain supports a wildcard but you don't want to
deliver the wildcard cert for certain specific domains.
2013-05-07 22:11:54 +02:00
Willy Tarreau
2b5702030d MINOR: ebtree: add new eb_next_dup/eb_prev_dup() functions to visit duplicates
Sometimes it's very useful to visit duplicates of a same node, but doing
so from the application is not convenient because keys have to be compared,
while all the information is available during the next/prev steps.

Let's introduce a couple of new eb_next_dup/eb_prev_dup functions to visit
only duplicates of the current node and return NULL once it's done. Now we
have all 3 combinations :
  - next        : returns next node in the tree
  - next_dup    : returns next dup in the sub-tree
  - next_unique : returns next value after skipping dups

(cherry picked from commit 3327b8ae6866f3878322a1a29e70b450226d216d)
2013-05-07 16:10:02 +02:00
Willy Tarreau
2ddccb7ed4 DOC: readme: add a small reminder about restrictions to respect in the code
For code portability, we need to respect a few restrictions (mainly no C99 etc).
2013-05-01 10:09:30 +02:00
Willy Tarreau
9046bbf05b BUILD: stdbool is not portable (again)
Another build issue on Solaris without c99. Please don't use stdbool.
2013-05-01 10:09:30 +02:00
Willy Tarreau
c5599e7c49 BUG/MEDIUM: compression: the deflate algorithm must use global settings as well
Global compression settings (windowsize and memlevel) were only considered
for the gzip algorithm but not the deflate algorithm. Since a single allocator
is used for both algos, if gzip was first initialized the memory with parameters
smaller than default, then initializing deflate after with default settings
would result in overusing the small allocated areas.

To fix this, we make use of deflateInit2() for deflate_init() as well.

Thanks to Godbach for reporting this bug, introduced by in 1.5-dev13 by commit
8b52bb38. No backport is needed.
2013-04-28 09:01:11 +02:00
Emeric Brun
f27af0dcc6 BUG/MEDIUM: shctx: makes the code independent on SSL runtime version.
struct SSL(ssl_st) defintion changed between openssl versions and must not be dereferenced.
2013-04-26 19:15:52 +02:00
Willy Tarreau
0cff0dbfc0 MINOR: init: indicate the SSL runtime version on -vv.
It happens that openssl's API can differ between versions, causing some
serious trouble if the version used at runtime is not the same as used
for building.

Now we report the two versions separately along with a warning if the
version differs (except the patch version).
2013-04-26 18:16:13 +02:00
Emeric Brun
41fdb3cb70 BUG/MEDIUM: ssl: EDH ciphers are not usable if no DH parameters present in pem file.
Uses default defined DH parameters when none present in pem file.
2013-04-26 11:19:48 +02:00
Willy Tarreau
c621d36ba3 BUILD: last fix broke non-linux platforms
src.tproxy_addr only exists on linux.
2013-04-25 17:35:22 +02:00
Godbach
9f04853bd9 BUG/MINOR: config: "source" does not work in defaults section
Source function will not work with the following line in default section:
     source 0.0.0.0 usesrc clientip
even that related settings by iptables and ip rule have been set correctly.
But it can work well in backend setcion.

The reason is that the operation in line 1815 in cfgparse.c as below:
     curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;

clears three low bits of conn_src.opts which stores the configuration of
'usesrc'. Without correct bits set, the source address function can not
work well. They should be copied to the backend proxy without being modified.

Since conn_src.tproxy_addr had not copied from defproxy to backend proxy
while initializing backend proxy, source function will not work well
with explicit source address set in default section either.

Signed-off-by: Godbach <nylzhaowei@gmail.com>

Note: the bug was introduced in 1.5-dev16 with commit ef9a3605
2013-04-24 08:41:16 +02:00
Willy Tarreau
7f6fa69221 BUG/MINOR: fix unterminated ACL array in compression
Recent commit 727db8b4 was lacking a NULL ACL descriptor to terminate
the array, causing a random behaviour upon startup. No backport is needed.
2013-04-23 19:39:43 +02:00
Emeric Brun
50bcecc11d BUG/MEDIUM: Fix crt-list file parsing error: filtered name was ignored.
Also add support for multiple filtered names on same certificate (per line).
2013-04-22 14:49:01 +02:00
Willy Tarreau
7fe3300b76 BUG/MEDIUM: stats: fix a regression when dealing with POST requests
In 1.5-dev17 (commit 1facd6d6), we reorganized the way HTTP stats
requests are handled. When moving the code, we dropped a "return 0"
which happens upon incomplete POST request, so we now end up with
the next return 1 which causes processing to go on with next
analyser. This causes incomplete POST requests to try to forward
the request to servers, resulting in either a 404 or a 503 depending
on the configuration.

This patch fixes this regression to restore the previous behaviour.
It's not enough though, as it happens that the stats code is handled
after all http header processing but in the same function. The net
effect is that incomplete requests cause the headers manipulation to
be performed multiple times, possibly resulting in multiple headers
in the request buffer. Since the stats requests are not meant to be
forwarded, it's not an issue yet but this is something to take care
of later.

A remaining issue that's not handled yet is that if the client does
not send the complete POST headers, then the request is finally
forwarded. This is not a regression, it has always been there and
seems to be caused by the lack of timeout processing when waiting
for the POST body. The solution to this issue would be to move the
handling of stats requests into a dedicated analyser placed after
http_process_request_body().

Bug reported by Guillaume de Lafond.
2013-04-21 08:16:10 +02:00
William Lallemand
727db8b4ea MINOR: compression: acl "res.comp" and fetch "res.comp_algo"
Implements the "res.comp" ACL which is a boolean returning 1 when a
response has been compressed by HAProxy or 0 otherwise.

Implements the "res.comp_algo" fetch which contains the name of the
algorithm HAProxy used to compress the response.
2013-04-20 23:53:33 +02:00
Willy Tarreau
913195715d BUG/MEDIUM: stats: allocate the stats frontend also on "stats bind-process"
Bryan Talbot reported that a config with only "stats bind-process 1" in
the global section would crash during parsing. This bug was introduced
with this new statement in 1.5-dev13. The stats frontend must be allocated
if it was not yet.

No backport is needed. The workaround consists in having previously declared
any other stats keyword (generally stats socket).
2013-04-20 09:48:50 +02:00
Geoff Bucar
cc8bb92f32 MINOR: stats: show soft-stopped servers in different color
A "soft-stopped" server (weight 0) can be missed easily in the
webinterface. Fix this by using a specific class (and color).

Signed-off-by: Lukas Tribus <luky-37@hotmail.com>
2013-04-19 22:32:15 +02:00
Willy Tarreau
656a9cee91 BUG/MINOR: stats: the status bar does not appear anymore after a change
When a server state change happens, a status bar appears with a link. Since
commit 1.5-dev16 (commit e7dbfc66), it was not visible anymore because of
the CSS properties set on the whole "div" tag used by the tooltips. Fix this
by using a specific class for the tooltips.
2013-04-19 14:41:29 +02:00
Willy Tarreau
ba6be983d6 BUG/MINOR: stats: fix confirmation links on the stats interface
The confirmation link on the web interface forgets to set the displaying
options, so that when one clicks on "[X] Action processed successfully",
the auto-refresh, up/down and scope search settings are lost. We need to
pass all these info in the new link.
2013-04-19 12:16:55 +02:00
Cyril Bont
5465684e20 MINOR: stats: remove the autofocus on the scope input field
commit 88c278fadf provided a new input field on the statistics page which was
focused by default. The autofocus prevent to scroll down the page with the
keyboard immediately afterloading it, without the need to leave that field.
It also interfered with "stats refresh" by scrolling up to this field on each
refresh.

This small patch removes the autofocus keyword and adds a tabindex="1" as
suggested by Vincent Bernat. It also cleans up the generated html code.
2013-04-18 22:42:33 +02:00
de Lafond Guillaume
88c278fadf MEDIUM: stats: add proxy name filtering on the statistic page
This patch adds a "scope" box in the statistics page in order to
display only proxies with a name that contains the requested value.
The scope filter is preserved across all clicks on the page.
2013-04-15 22:50:33 +02:00
Lukas Tribus
d9bdccda55 BUG/MINOR: jit: don't rely on USE flag to detect support
Since ea68d36 we show whether JIT is enabled, based on the USE-flag
(USE_PCRE_JIT). This is too naive; libpcre may be built without JIT
support (which is the default).

Fix this by calling pcre_config(), which has the accurate information
we are looking for.

Example of a libpcre without JIT support after this patch:
> ./haproxy -vv | grep PCRE
>   OPTIONS = USE_STATIC_PCRE=1 USE_PCRE_JIT=1
> Built with PCRE version : 8.32 2012-11-30
> PCRE library supports JIT : no (libpcre build without JIT?)
2013-04-15 01:24:16 +02:00
Willy Tarreau
667c2a3d2a BUG/MAJOR: http: compression still has defects on chunked responses
The compression state machine happens to start work it cannot undo if
there's no more data in the input buffer, and has trouble accounting
for it. Fixing it requires more than a few lines, as the confusion is
in part caused by the way the pointers to the various places in the
message are handled internally. So as a temporary fix, let's disable
compression on chunk-encoded responses. This will give us more time
to perform the required changes.
2013-04-14 23:32:53 +02:00
Willy Tarreau
04b3a19709 BUG/MINOR: cli: "clear table xx data.xx" does not work anymore
Commit 654694e1 introduced in 1.5-dev12 broke the ability to clear
some entries in a table by the value of their data fields.
2013-04-13 09:41:37 +02:00
Willy Tarreau
20e993239d BUG/MINOR: cli: "clear table" did not work anymore without a key
Will Glass-Husain reported this breakage which was caused by commit
dec9814e merged in 1.5-dev12, and which was incomplete, resulting in
both "clear table" and "show table" to do the same thing.

No backport is needed.
2013-04-13 09:22:25 +02:00
Willy Tarreau
b1f3af2327 MEDIUM: log: report file name, line number, and directive name with log-format errors
Improve error log reporting in the format parser by always giving the
file name, line number, and directive name instead of the hard-coded
"log-format".

Previously we got this when dealing with log-format errors:
  [WARNING] 101/183012 (8561) : Warning: log-format variable name 'r' is not suited to HTTP mode
  [WARNING] 101/183012 (8561) : log-format: sample fetch <hdr(a,1)> may not be reliably used with 'log-format' because it needs 'HTTP request headers,HTTP response headers' which is not available here.
  [WARNING] 101/183012 (8561) : Warning: no such variable name 'k' in log-format

Now we have this :
  [WARNING] 101/183016 (8593) : parsing [fmt.cfg:8] : 'log-format' variable name 'r' is reserved for HTTP mode
  [WARNING] 101/183016 (8593) : parsing [fmt.cfg:8] : 'log-format' : sample fetch <hdr(a,1)> may not be reliably used here because it needs 'HTTP request headers,HTTP response headers' which is not available here.
  [WARNING] 101/183016 (8593) : parsing [fmt.cfg:15] : no such variable name 'k' in 'unique-id-format'
2013-04-12 18:36:00 +02:00
Willy Tarreau
62a6123fed BUG/MEDIUM: log: fix regression on log-format handling
Commit a4312fa2 merged into dev18 improved log-format management by
processing "log-format" and "unique-id-format" where they were declared,
so that the faulty args could be reported with their correct line numbers.

Unfortunately, the log-format parser considers the proxy mode (TCP/HTTP)
and now if the directive is set before the "mode" statement, it can be
rejected and report warnings.

So we really need to parse these directives at the end of a section at
least. Right now we do not have an "end of section" event, so we need
to store the file name and line number for each of these directives,
and take care of them at the end.

One of the benefits is that now the line numbers can be inherited from
the line passing "option httplog" even if it's in a defaults section.

Future improvements should be performed to report line numbers in every
log-format processed by the parser.
2013-04-12 18:13:46 +02:00
Willy Tarreau
d16a1b2a81 BUG/MAJOR: backend: consistent hash can loop forever in certain circumstances
When the parameter passed to a consistent hash is not found, we fall back to
round-robin using chash_get_next_server(). This one stores the last visited
server in lbprm.chash.last, which can be NULL upon the first invocation or if
the only server was recently brought up.

The loop used to scan for a server is able to skip the previously attempted
server in case of a redispatch, by passing this previous server in srvtoavoid.
For this reason, the loop stops when the currently considered server is
different from srvtoavoid and different from the original chash.last.

A problem happens in a special sequence : if a connection to a server fails,
then all servers are removed from the farm, then the original server is added
again before the redispatch happens, we have chash.last = NULL and srvtoavoid
set to the only server in the farm. Then this server is always equal to
srvtoavoid and never to NULL, and the loop never stops.

The fix consists in assigning the stop point to the first encountered node if
it was not yet set.

This issue cannot happen with the map-based algorithm since it's based on an
index and not a stop point.

This issue was reported by Henry Qian who kindly provided lots of critically
useful information to figure out the conditions to reproduce the issue.

The fix needs to be backported to 1.4 which is also affected.
2013-04-12 14:46:51 +02:00
Willy Tarreau
33c60dece5 MINOR: tcp: report the erroneous word in tcp-request track*
We used to report the word after the fetch.
2013-04-12 08:26:32 +02:00
Willy Tarreau
1e5dfdad77 MINOR: session: only call http_send_name_header() when changing the server
Till now we used to call the function until the connection established, which
means that the header rewriting was performed for nothing upon each even (eg:
uploaded contents) until the server responded or timed out.

Now we only call the function when we assign the server.
2013-04-11 18:18:01 +02:00
Willy Tarreau
9d9179b581 BUG/MAJOR: peers: fix an overflow when syncing strings larger than 16 bytes
When syncing data between two haproxy instances, the received keys were
allocated in the stack but no room was planned for type string. So in
practice all strings of 16 or less bytes were properly handled (due to
the union with in6_addr which reserves some room), but above this some
local variables were overwritten. Up to 8 additional bytes could be
written without impact, but random behaviours are expected above, including
crashes and memory corruption.

If large enough strings are allowed in the configuration, it is possible that
code execution could be triggered when the function's return pointer is
overwritten.

A quick workaround consists in ensuring that no stick-table uses a string
larger than 16 bytes (default is 32). Another workaround is to disable peer
sync when strings are in use.

Thanks to Will Glass-Husain for bringing up this issue with a backtrace to
understand the issue.

The bug only affects 1.5-dev3 and above. No backport is needed.
2013-04-11 17:24:54 +02:00
Willy Tarreau
a7b46b50d9 MINOR: stick-table: allow to allocate an entry without filling it
By passing a NULL key to stksess_new(), we allocate it but do not yet
fill it. That way the caller can do that.
2013-04-11 17:24:53 +02:00
Willy Tarreau
72d6c16df4 CLEANUP: peers: remove a bit of spaghetti to prepare for the next bugfix
We'll need to centralize some pool_alloc()/pool_free() calls in the
upcoming fix so before that we need to reduce the number of points
by which we leave the critical code.
2013-04-11 17:24:53 +02:00
Willy Tarreau
deaec2fda3 BUG/MINOR: tcp: fix error reporting for TCP rules
tcp-request swapped two output words in the error message, making it meaningless.
2013-04-11 17:24:53 +02:00
Hiroaki Nakamura
e3cf2229ad BUG: regex: fix pcre compile error when using JIT
According to "man pcreapi", pcre_compile() does not accept being passed
a NULL pointer in errptr or erroffset. It immediately returns NULL, causing
any expression to fail. So let's pass real variables and make use of them
to improve error reporting.
2013-04-11 08:17:37 +02:00
Willy Tarreau
f75d008c45 BUG/MAJOR: acl: add implicit arguments to the resolve list
When an ACL keyword needs a mandatory argument and this argument is of
type proxy or table, it is allowed not to specify it so that current
proxy is used by default.

In order to achieve this, the ACL expression parser builds a dummy
argument from scratch and marks it unresolved.

However, since recent changes on the ACL and samples, an unresolved
argument needs to be added to the unresolved list. This specific code
did not do it, resulting in random data being used as a proxy pointer
if no argument was passed for a proxy name, possibly even causing a
crash.

A quick workaround consists explicitly naming proxies in ACLs.
2013-04-07 21:20:44 +02:00