Commit Graph

4659 Commits

Author SHA1 Message Date
Willy Tarreau
34dfc60571 BUG/MEDIUM: http: incorrect transfer-coding in the request is a bad request
The rules related to how to handle a bad transfer-encoding header (one
where "chunked" is not at the final place) have evolved to mandate an
abort when this happens in the request. Previously it was only a close
(which is still valid for the server side).

This must be backported to 1.5 and 1.4.
2015-05-01 13:56:10 +02:00
Willy Tarreau
4979d5c5d1 BUG/MEDIUM: http: do not restrict parsing of transfer-encoding to HTTP/1.1
While Transfer-Encoding is HTTP/1.1, we must still parse it in HTTP/1.0
in case an agent sends it, because it's likely that the other side might
use it as well, causing confusion. This will also result in getting rid
of the Content-Length header in such abnormal situations and in having
a clean connection.

This must be backported to 1.5 and 1.4.
2015-05-01 13:56:10 +02:00
Willy Tarreau
557f199fb7 DOC: http: update the comments about the rules for determining transfer-length
Let's now use the text from RFC7230 which is stricter and more precise.

This must be backported to 1.5 and 1.4.
2015-05-01 13:56:10 +02:00
Willy Tarreau
1c91391df4 BUG/MEDIUM: http: remove content-length from chunked messages
RFC7230 clarified the behaviour to adopt when facing both a
content-length and a transfer-encoding: chunked in a message. While
haproxy already complied with the method for getting the message
length right, and used to detect improper content-length duplicates,
it still did not remove the content-length header when facing a
transfer-encoding: chunked. Usually it is not a problem since other
agents (clients and servers) are required to parse the message
according to the rules that have been in place since RFC2616 in
1999.

However Régis Leroy reported the existence of at least one such
non-compliant agent so haproxy could be abused to get out of sync
with it on pipelined requests (HTTP request smuggling attack),
it consider part of a payload as a subsequent request.

The best thing to do is then to remove the content-length according
to RFC7230. It used to be in the todo list with a fixme in the code
while waiting for the standard to stabilize, let's apply it now that
it's published.

Thanks to Régis for bringing that subject to our attention.

This fix must be backported to 1.5 and 1.4.
2015-05-01 13:56:10 +02:00
Simon Horman
1421e21fe4 MEDIUM: Document when email-alerts are sent
Document the influence of email-alert level and other configuration
parameters on when email-alerts are sent.

Signed-off-by: Simon Horman <horms@verge.net.au>
2015-04-30 07:30:51 +02:00
Simon Horman
4cd477f372 MEDIUM: Send email alerts when servers are marked as UP or enter the drain state
This is similar to the way email alerts are sent when servers are marked as
DOWN.

Like the log messages corresponding to these state changes the messages
have log level notice. Thus they are suppressed by the default email-alert
level of 'alert'. To allow these messages the email-alert level should
be set to 'notice', 'info' or 'debug'. e.g:

email-alert level notice

"email-alert mailers" and "email-alert to" settings are also required in
order for any email alerts to be sent.

A follow-up patch will document the above.

Signed-off-by: Simon Horman <horms@verge.net.au>
2015-04-30 07:30:50 +02:00
Simon Horman
7ea9be012d MEDIUM: Lower priority of email alerts for log-health-checks messages
Lower the priority of email alerts for log-health-checks messages from
LOG_NOTICE to LOG_INFO.

This is to allow set-ups with log-health-checks enabled to disable email
for health check state changes while leaving other email alerts enabled.

In order for email alerts to be sent for health check state changes
"log-health-checks" needs to be set and "email-alert level" needs to be 'info'
or lower. "email-alert mailers" and "email-alert to" settings are also
required in order for any email alerts to be sent.

A follow-up patch will document the above.

Signed-off-by: Simon Horman <horms@verge.net.au>
2015-04-30 07:30:50 +02:00
Willy Tarreau
f3045d2a06 MAJOR: pattern: add LRU-based cache on pattern matching
The principle of this cache is to have a global cache for all pattern
matching operations which rely on lists (reg, sub, dir, dom, ...). The
input data, the expression and a random seed are used as a hashing key.
The cached entries contains a pointer to the expression and a revision
number for that expression so that we don't accidently used obsolete
data after a pattern update or a very unlikely hash collision.

Regarding the risk of collisions, 10k entries at 10k req/s mean 1% risk
of a collision after 60 years, that's already much less than the memory's
reliability in most machines and more durable than most admin's life
expectancy. A collision will result in a valid result to be returned
for a different entry from the same list. If this is not acceptable,
the cache can be disabled using tune.pattern.cache-size.

A test on a file containing 10k small regex showed that the regex
matching was limited to 6k/s instead of 70k with regular strings.
When enabling the LRU cache, the performance was back to 70k/s.
2015-04-29 19:15:24 +02:00
Willy Tarreau
72f073b6c7 MEDIUM: pattern: add a revision to all pattern expressions
This will be used to detect any change on the pattern list between
two operations, ultimately making it possible to implement a cache
which immediately invalidates obsolete keys after an update. The
revision is simply taken from the timestamp counter to ensure that
even upon a pointer reuse we cannot accidently come back to the
same (expr,revision) tuple.
2015-04-29 19:15:24 +02:00
Willy Tarreau
b5684e0081 IMPORT: hash: import xxhash-r39
The xxhash library provides a very fast and excellent hash algorithm
suitable for many purposes. It excels at hashing large blocks but is
also extremely fast on small ones. It's distributed under a 2-clause
BSD license (GPL-compatible) so it can be included here. Updates are
distributed here :

      https://github.com/Cyan4973/xxHash
2015-04-29 19:15:21 +02:00
Willy Tarreau
69c696c138 IMPORT: lru: import simple ebtree-based LRU functions
This will be usable to implement some maps/acl caches for heavy datasets
loaded from files (mostly regex-based but in general anything that cannot
be indexed in a tree).
2015-04-29 19:14:43 +02:00
Willy Tarreau
e6e49cfa93 MINOR: tools: provide an rdtsc() function for time comparisons
This one returns a timestamp, either the one from the CPU or from
gettimeofday() in 64-bit format. The purpose is to be able to compare
timestamps on various entities to make it easier to detect updates.
It can also be used for benchmarking in certain situations during
development.
2015-04-29 19:14:03 +02:00
Baptiste Assmann
f95bc8e3e0 BUG/MEDIUM: check: tcpcheck regression introduced by e16c1b3f
The commit e16c1b3f changed the way the function tcpcheck_get_step_id is
now called (check instead of server).
This change introduced a regression since now this function would return
0 all the time because of:
 if (check->current_step)
   return 0;

This patch fixes this issue by inversing the test: you want to return 0
only if current_step is not yet set :)

No backport is needed.
2015-04-29 13:39:22 +02:00
Andrew Hayworth
0ebc55f6b4 MEDIUM: logs: Add HTTP request-line log format directives
This commit adds 4 new log format variables that parse the
HTTP Request-Line for more specific logging than "%r" provides.

For example, we can parse the following HTTP Request-Line with
these new variables:

  "GET /foo?bar=baz HTTP/1.1"

- %HM: HTTP Method ("GET")
- %HV: HTTP Version ("HTTP/1.1")
- %HU: HTTP Request-URI ("/foo?bar=baz")
- %HP: HTTP Request-URI without query string ("/foo")
2015-04-28 21:03:05 +02:00
Willy Tarreau
e5843b383d BUG/MEDIUM: peers: recent applet changes broke peers updates scheduling
Since appctx are scheduled out of streams, it's pointless to wake up
the task managing the stream to push updates, they won't be seen. In
fact unit tests work because silent sessions are restarted after 5s of
idle and the exchange is correctly scheduled during startup!

So we need to notify the appctx instead. For this we add a pointer to
the appctx in the peer session.

No backport is needed of course.
2015-04-27 18:42:17 +02:00
Willy Tarreau
6e2979ca31 BUG/MEDIUM: peers: fix applet scheduling
Consecutive to the recent changes brought to applets, peers properly
connect but do not exchange data anymore because the stream interface
is not marked as waiting for data.

No backport is needed.
2015-04-27 13:21:15 +02:00
Thierry FOURNIER
7f6192c0d3 BUG/MEDIUM: http: functions set-{path,query,method,uri} breaks the HTTP parser
When one of these functions replaces a part of the query string by
a shorter or longer new one, the header parsing is broken. This is
because the start of the first header is not updated.

In the same way, the total length of the request line is not updated.
I dont see any bug caused by this miss, but I guess than it is better
to store the good length.

This bug is only in the development version.
2015-04-27 11:56:52 +02:00
Willy Tarreau
e91ffd093e BUG/MAJOR: tcp: only call registered actions when they're registered
Commit cc87a11 ("MEDIUM: tcp: add register keyword system.") introduced
the registration of new keywords for TCP rulesets. Unfortunately it
replaced the "accept" action with an unconditionnal call to the rule's
action function, resulting in an immediate segfault when using the
"accept" action in a TCP ruleset.

This bug reported by Baptiste Assmann was introduced in 1.6-dev1, no
backport is needed.
2015-04-24 10:13:18 +02:00
Willy Tarreau
0b1a4541dc MEDIUM: stream-int: pause the appctx if the task is woken up
If we're going to call the task we don't need to call the appctx anymore
since the task may decide differently in the end and will do the proper
thing using ->update(). This reduces one wake up call per session and
may go down to half in case of high concurrency (scheduling races).
2015-04-23 17:56:17 +02:00
Willy Tarreau
fe127937a8 MEDIUM: applet: make the applets only use si_applet_{cant|want|stop}_{get|put}
The applets don't fiddle with SI_FL_WAIT_ROOM anymore, instead they indicate
what they want, possibly that they failed (eg: WAIT_ROOM), and it's done() /
update() which finally updates the WAIT_* flags according to the channels'
and stream interface's states. This solves the issue of the pauses during a
"show sess" without creating busy loops.
2015-04-23 17:56:17 +02:00
Willy Tarreau
eb406dc73c MINOR: stream-int: add two flags to indicate an applet's wishes regarding I/O
Currently we have a problem. There are some cases where a sleeping applet
is not woken up (eg: show sess during an injection). The reason is that
the applet is marked WAIT_DATA and is not woken up when WAIT_ROOM leaves,
because we wait for both flags to be cleared in order to call it.

And if we wait for either flag, then we have the opposite situation, which
is that we're not waiting for room in the output buffer so we're spinning
calling the applet to do nothing.

What is missing is an indication of what the applet needs. Since it only
manipulates the WAIT_ROOM/WAIT_DATA which are overwritten later, that cannot
work. In the case of connections, the problem doesn't happen because the
connection maintains these extra states. Ideally we'd need to have similar
states for each appctx and to store those information there. But it would
be overcomplicated given that an applet doesn't exist alone without a
stream-int, so we can safely put these information into the stream int and
make the code simpler.

With this patch we introduce two new flags in the stream interface :
  - SI_FL_WANT_PUT : the applet wants to put something into the buffer
  - SI_FL_WANT_GET : the applet wants to get something from the buffer

We also have the new functions si_applet_{stop|want|cant}_{get|put}
to make the code look similar to the connection code.

For now these flags are not used yet.
2015-04-23 17:56:17 +02:00
Willy Tarreau
bc39a5d8c8 MAJOR: stream: do not allocate request buffers anymore when the left side is an applet
We used to allocate a request buffer so that we could process applets
from process_stream(), and this was causing some trouble because it was
not possible for an analyzer to return an error to an applet, which
we'll need for HTTP/2. Now that we don't call applets anymore from
process_stream() we can simplify this and ensure that a response is
always allocated to process a stream.
2015-04-23 17:56:17 +02:00
Willy Tarreau
d4da196546 MEDIUM: applet: centralize the call to si_applet_done() in the I/O handler
It's much easier to centralize this call into the I/O handler than to
do it everywhere with the risk to miss it. Applets are not allowed to
unregister themselves anyway so their SI is still present and it is
possible to update all the context.
2015-04-23 17:56:17 +02:00
Willy Tarreau
b9c89111ab MEDIUM: dumpstats: don't unregister the applet anymore
Let the session do the job, the applet I/O handler doesn't have to unregister
itself.
2015-04-23 17:56:16 +02:00
Willy Tarreau
563cc37609 MAJOR: stream: use a regular ->update for all stream interfaces
Now si->update() is used to update any type of stream interface, whether
it's an applet, a connection or even nothing. We don't call si_applet_call()
anymore at the end of the resync and we don't have the risk that the
stream's task is reinserted into the run queue, which makes the code
a bit simpler.

The stream_int_update_applet() function was simplified to ensure that
it remained compatible with this standardized calling convention. It
was almost copy-pasted from the update code dedicated to connections.
Just like for si_applet_done(), it seems that it should be possible to
merge the two functions except that it would require some slow operations,
except maybe if the type of end point is tested inside the update function
itself.
2015-04-23 17:56:16 +02:00
Willy Tarreau
828824af05 MAJOR: applet: now call si_applet_done() instead of si_update() in I/O handlers
The applet I/O handlers now rely on si_applet_done() which itself decides
to wake up or sleep the appctx. Now it becomes critical that applte handlers
properly call this on every exit path so that the appctx is removed from the
active list after I/O have been handled. One such call was added to the Lua
socket handler. It used to work without it probably because the main task is
woken up by the parent task but now it's needed.
2015-04-23 17:56:16 +02:00
Willy Tarreau
e5f8649102 MEDIUM: stream-int: add a new function si_applet_done()
This is the equivalent of si_conn_wake() but for applets. It will be
called after changes to the stream interface are brought by the applet
I/O handler. Ultimately it will release buffers and may be even wake
the stream's task up if some important changes are detected.

It would be nice to be able to merge it with the connection's wake
function since it mostly manipulates the stream interface, but there
are minor differences (such as how to enable/disable polling on a fd
vs applet) and some specificities to applets (eg: don't wake the
applet up until the output is empty) which would require abstract
functions which would slow down everything.
2015-04-23 17:56:16 +02:00
Willy Tarreau
3c595ac3ad MEDIUM: applet: implement a run queue for active appctx
The new function is called for each round of polling in order to call any
active appctx. For now we pick the stream interface from the appctx's
owner. At the moment there's no appctx queued yet, but we have everything
needed to queue them and remove them.
2015-04-23 17:56:16 +02:00
Willy Tarreau
81f38d6f57 MEDIUM: applet: add basic support for an applet run queue
This will be needed so that we can schedule applets out of the streams.
For now nothing calls the queue yet.
2015-04-23 17:56:16 +02:00
Willy Tarreau
d45b9f8991 REORG: stream-int: create si_applet_ops dedicated to applets
These functions are dedicated to applets so that we don't use the default
ones anymore in this case.
2015-04-23 17:56:16 +02:00
Willy Tarreau
3057645b37 CLEANUP: applet: rename struct si_applet to applet
Since this one does not depend on stream_interface anymore, remove the
"si_" prefix.
2015-04-23 17:56:16 +02:00
Willy Tarreau
8a8d83b85c REORG: applet: move the applet definitions out of stream_interface
We're tidying the definitions so that appctx lives on its own. A new
set of applet.h files has been added for this purpose.
2015-04-23 17:56:16 +02:00
Willy Tarreau
00a37f0029 MEDIUM: applet: make the applet not depend on a stream interface anymore
Now that applet's functions only take an appctx in argument, not a
stream interface. This slightly simplifies the code and will be needed
to take the appctx out of the stream interface.
2015-04-23 17:56:16 +02:00
Willy Tarreau
19c8161b3d MINOR: applet: add a new "owner" pointer in the appctx
This pointer indicates what stream-interface the appctx belongs to, just
like we have for the connections.
2015-04-23 17:56:16 +02:00
Simon Horman
b167b6bff9 MEDIUM: stats: Differentiate between DRAIN and DRAIN (agent)
Differentiate between DRAIN and DRAIN (agent) when reporting stats.
This is consistent with the distinction made between DOWN and DOWN (agent).

Signed-off-by: Simon Horman <horms@verge.net.au>
2015-04-23 09:57:56 +02:00
Simon Horman
4463d19d48 MEDIUM: stats: Only report drain state in stats if server has SRV_ADMF_DRAIN set
There are some similarities between a weight of zero and the
administratively set drain state: both allow existing connections
to continue while not accepting any new ones.

However, when reporting a server state generally a distinction is made
between state=UP,weight=0 and state=DRAIN,weight=*. This patch makes
stats reporting consistent in this regard.

This patch does not alter the behaviour that if a server's weight
is zero then its stats row is blue when accessed via HTML. This remains
the case regardless of if the state is UP or DRAIN.

Signed-off-by: Simon Horman <horms@verge.net.au>
2015-04-23 09:57:53 +02:00
Simon Horman
837bfa74db MEDIUM: stats: Separate server state and colour in stats
There is a relationship between the state and colour of a server in
stats, however, it is not a one-to-one relationship and the current
implementation has proved fragile.

This patch attempts to address that problem by clearly separating
state and colour.

A follow-up patch will further distinguish between DRAIN states
and DRAINING colours.

Signed-off-by: Simon Horman <horms@verge.net.au>
2015-04-23 09:57:51 +02:00
Simon Horman
4d2eab61d4 MEDIUM: stats: Add enum srv_stats_state
Add an enumeration to make the handling of the states of servers
in status messages somewhat clearer.

This is the first of a two-step attempt to disentangle the state and
colour of status information. A subsequent patch will separate state
colours from the states themselves.

This patch should not make any functional changes.

Signed-off-by: Simon Horman <horms@verge.net.au>
2015-04-23 09:57:49 +02:00
Jason Harvey
8310480499 DOC: Fix L4TOUT typo in documentation
Fix documentation typo. L4TMOUT->L4TOUT.
2015-04-21 18:20:06 +02:00
Willy Tarreau
ee335e65dc BUG/MEDIUM: http: properly retrieve the front connection
Commit 350f487 ("CLEANUP: session: simplify references to chn_{prod,cons}(&s->{req,res})")
introduced a regression causing the cli_conn to be picked from the server
side instead of the client side, so the XFF header is not appended anymore
since the connection is NULL.

Thanks to Reinis Rozitis for reporting this bug. No backport is needed
as it's 1.6-specific.
2015-04-21 18:15:13 +02:00
Willy Tarreau
e3a71ffc54 DOC: update the entities diagrams
The recent changes were significant enough to warrant an update to the
entities diagram. It tries to be accurate, though it doesn't represent
applets.
2015-04-21 14:15:40 +02:00
Willy Tarreau
7365dad40f BUG/MEDIUM: stream-int: always reset si->ops when si->end is nullified
It happened after changing the stream interface deinitialization
sequence that we got random crashes with si_shutw() being called
on NULL si->end. The reason was that si->ops was not reset after
a call to si_release_endpoint() which is sometimes called directly.

Thus we now move the resetting of si->ops just after any si->end
assignment. It happens that si_detach() is now just the same as
si_release_endpoint() and stream_int_unregister_handler(). Some
cleanup will have to be performed there.

It's not sure whether this problem can impact 1.5 since in 1.5
applets are part of the default embedded stream handler. The only
way it could cause some trouble is if it's used with a connection,
which doesn't seem possible at first glance.
2015-04-21 14:15:22 +02:00
Willy Tarreau
152b81e7b2 BUG/MAJOR: tcp/http: fix current_rule assignment when restarting over a ruleset
Commit bc4c1ac ("MEDIUM: http/tcp: permit to resume http and tcp custom
actions") introduced the ability to interrupt and restart processing in
the middle of a TCP/HTTP ruleset. But it doesn't do it in a consistent
way : it checks current_rule_list, immediately dereferences current_rule,
which is only set in certain cases and never cleared. So that broke the
tcp-request content rules when the processing was interrupted due to
missing data, because current_rule was not yet set (segfault) or could
have been inherited from another ruleset if it was used in a backend
(random behaviour).

The proper way to do it is to always set current_rule before dereferencing
it. But we don't want to set it for all rules because we don't want any
action to provide a checkpointing mechanism. So current_rule is set to NULL
before entering the loop, and only used if not NULL and if current_rule_list
matches the current list. This way they both serve as a guard for the other
one. This fix also makes the current rule point to the rule instead of its
list element, as it's much easier to manipulate.

No backport is needed, this is 1.6-specific.
2015-04-20 13:46:20 +02:00
Willy Tarreau
e759749b50 BUG/MEDIUM: init: don't limit cpu-map to the first 32 processes only
We have to allow 32 or 64 processes depending on the machine's word
size, and on 64-bit machines only the first 32 processes were properly
bound.

This fix should be backported to 1.5.
2015-04-20 11:36:57 +02:00
Willy Tarreau
af2fd584f3 BUG/MEDIUM: listener: don't report an error when resuming unbound listeners
Pavlos Parissis reported that a sequence of disable/enable on a frontend
performed on the CLI can result in an error if the frontend has several
"bind" lines each bound to different processes. This is because the
resume_listener() function returns a failure for frontends not part of
the current process instead of returning a success to pretend there was
no failure.

This fix should be backported to 1.5.
2015-04-14 12:10:06 +02:00
Willy Tarreau
10146c9c51 CLEANUP: poll: move the conditions for waiting out of the poll functions
The poll() functions have become a bit dirty because they now check the
size of the signal queue, the FD cache and the number of tasks. It's not
their job, this must be moved to the caller. In the end it simplifies the
code because the expiration date is now set to now_ms if we must not wait,
and this achieves in exactly the same result and is cleaner. The change
looks large due to the change of indent for blocks which were inside an
"if" block.
2015-04-13 20:47:51 +02:00
CJ Ess
108b1dd69d MEDIUM: http: configurable http result codes for http-request deny
This patch adds support for error codes 429 and 405 to Haproxy and a
"deny_status XXX" option to "http-request deny" where you can specify which
code is returned with 403 being the default. We really want to do this the
"haproxy way" and hope to have this patch included in the mainline. We'll
be happy address any feedback on how this is implemented.
2015-04-11 10:34:54 +02:00
Alexander Rigbo
fc65af0c61 BUG/MINOR: ssl: Display correct filename in error message
This patch should be backported to 1.5.
2015-04-11 10:28:59 +02:00
Willy Tarreau
73b65acd46 MINOR: stream: pass the pointer to the origin explicitly to stream_new()
We don't pass sess->origin anymore but the pointer to the previous step. Now
it should be much easier to chain elements together once applets are moved out
of streams. Indeed, the session is only used for configuration and not for the
dynamic chaining anymore.
2015-04-08 18:26:29 +02:00
Willy Tarreau
678be62981 MEDIUM: session: adjust the connection flags before stream_new()
It's not the stream's job to manipulate the connection's flags, it's
more related to the session that accepted the new connection. And the
only case where we have to do it conditionally is based on the frontend
which is known from the session, thus it makes sense to do it there.
2015-04-08 18:18:15 +02:00