Commit Graph

3227 Commits

Author SHA1 Message Date
Willy Tarreau
fae3a7eacd MINOR: stats: use the admin flags for soft enable/disable/stop/start on the web page
Instead of changing the weight to zero or enforcing maintenance mode, we
now make use of the new MAINT/DRAIN flags which are correctly propagated.
2014-05-23 14:29:11 +02:00
Willy Tarreau
bfc7b7acd8 MAJOR: checks: add support for a new "drain" administrative mode
This patch adds support for a new "drain" mode. So now we have 3 admin
modes for a server :
  - READY
  - DRAIN
  - MAINT

The drain mode disables load balancing but leaves the server up. It can
coexist with maint, except that maint has precedence. It is also inherited
from tracked servers, so just like maint, it's represented with 2 bits.

New functions were designed to set/clear each flag and to propagate the
changes to tracking servers when relevant, and to log the changes. Existing
functions srv_set_adm_maint() and srv_set_adm_ready() were replaced to make
use of the new functions.

Currently the drain mode is not yet used, however the whole logic was tested
with all combinations of set/clear of both flags in various orders to catch
all corner cases.
2014-05-23 14:29:11 +02:00
Willy Tarreau
9943d3117e MINOR: server: make use of srv_is_usable() instead of checking eweight
srv_is_usable() is broader than srv_is_usable() as it not only considers
the weight but the server's state as well. Future changes will allow a
server to be in drain mode with a non-zero weight, so we should migrate
to use that function instead.
2014-05-23 14:29:11 +02:00
Willy Tarreau
f4e38b36b8 MEDIUM: stats: report a server's own state instead of the tracked one's
Now that servers have their own states, let's report this one instead of
following the tracked server chain and reporting the tracked server's.
However the tracked server is still used to report x/y when a server is
going up or down. When the agent reports a down state, this one is still
enforced.
2014-05-23 14:29:11 +02:00
Willy Tarreau
db58b79ccd MEDIUM: checks: simplify stopping mode notification using srv_set_stopping()
Function check_set_server_drain() used to set a server into stopping state.
Now it first checks if all configured checks are UP, and if the possibly
tracked servers is not stopped, and only calls set_srv_stopping() after
that. That also simplified the conditions to call the function, and its
logic. The function was also renamed check_notify_stopping() to better
report this change.
2014-05-23 14:29:11 +02:00
Willy Tarreau
3e04838b8a MEDIUM: checks: simplify success notification using srv_set_running()
Function check_set_server_up() used to set a server up. Now it first
checks if all configured checks are UP, and if all tracked servers are
UP, and only calls set_srv_running() after that. That also simplified
the conditions to call the function, and its logic. The function was
also renamed check_notify_success() to better report this change.
2014-05-23 14:29:11 +02:00
Willy Tarreau
4eec547f32 MEDIUM: checks: simplify failure notification using srv_set_stopped()
Function check_set_server_down() used to set a server down. Now it first
checks if the health check's result differs from the server's state, and
only calls srv_set_stopped() if the check reports a failure while the
server is not down. Thanks to this, the conditions that were present
around its call could be removed. The function was also renamed
check_notify_failure() to better report this change.
2014-05-23 14:29:11 +02:00
Willy Tarreau
8eb7784634 MINOR: server: implement srv_set_stopping()
This function was taken from check_set_server_drain(). It does not
consider health checks at all and only sets a server to stopping
provided it's not in maintenance and is not currently stopped. The
resulting state will be STOPPING. The state change is propagated
to tracked servers.

For now the function is not used, but the goal is to split health
checks status from server status and to be able to change a server's
state regardless of health checks statuses.
2014-05-23 14:29:11 +02:00
Willy Tarreau
dbd5e78f5b MINOR: server: implement srv_set_running()
This function was taken from check_set_server_up(). It does not consider
health checks at all and only sets a server up provided it's not in
maintenance. The resulting state may be either RUNNING or STARTING
depending on the presence of a slowstart or not. The state change is
propagated to tracked servers.

For now the function is not used, but the goal is to split health
checks status from server status and to be able to change a server's
state regardless of health checks statuses.
2014-05-23 14:29:11 +02:00
Willy Tarreau
e7d1ef16bf MINOR: server: implement srv_set_stopped()
This function was extracted from check_set_server_down(). In only
manipulates the server state and does not consider the health checks
at all, nor does it modify their status. It takes a reason message to
report in logs, however it passes NULL when recursing through the
trackers chain.

For now the function is not used, but the goal is to split health
checks status from server status and to be able to change a server's
state regardless of health checks statuses.
2014-05-23 14:29:11 +02:00
Willy Tarreau
a150cf1a44 MINOR: checks: simplify health check reporting functions
check_report_srv_status() was removed in favor of check_reason_string()
combined with srv_report_status(). This way we have one function which
is dedicated to check decoding, and another one dedicated to server
status.
2014-05-23 14:29:11 +02:00
Willy Tarreau
bda92271e6 MINOR: server: make the status reporting function support a reason
srv_adm_append_status() was renamed srv_append_status() since it's no
more dedicated to maintenance mode. It now supports a reason which if
not null is appended to the output string.
2014-05-23 14:29:11 +02:00
Willy Tarreau
7b1d47ce1b MAJOR: checks: move health checks changes to set_server_check_status()
We don't want to manipulate check's statuses anymore in functions
which modify the server's state. So since any check is forced to
call set_server_check_status() exactly once to report the result
of the check, it's the best place to update the check's health.
2014-05-23 14:29:11 +02:00
Willy Tarreau
af54958d72 MEDIUM: checks: simplify server up/down/nolb transitions
We don't have to handle the maintenance transition here anymore so we
can simplify the functions and conditions. This also means that we don't
need the disable/enable functions but only a function to switch to each
new state.

It's worth mentionning that at this stage there are still confusions
between the server state and the checks states. For example, the health
check's state is adjusted from tracked servers changing state, while it
should not be.
2014-05-23 14:29:11 +02:00
Willy Tarreau
ddd329c059 CLEANUP: checks: rename the server_status_printf function
This function is poorly named since it's now used exclusively with checks
and cannot be moved to server.c. Call it check_report_srv_status() instead.
2014-05-23 14:29:11 +02:00
Willy Tarreau
3209123fe7 MEDIUM: server: allow multi-level server tracking
Now that it is possible to know whether a server is in forced maintenance
or inherits its maintenance status from another one, it is possible to
allow server tracking at more than one level. We still provide a loop
detection however.

Note that for the stats it's a bit trickier since we have to report the
check state which corresponds to the state of the server at the end of
the chain.
2014-05-23 14:29:11 +02:00
Willy Tarreau
a0066ddbda MEDIUM: server: properly support and propagate the maintenance status
This change now involves a new flag SRV_ADMF_IMAINT to note that the
maintenance status of a server is inherited from another server. Thus,
we know at each server level in the chain if it's running, in forced
maintenance or in a maintenance status because it tracks another server,
or even in both states.

Disabling a server propagates this flag down to other servers. Enabling
a server flushes the flag down. A server becomes up again once both of
its flags are cleared.

Two new functions "srv_adm_set_maint()" and "srv_adm_set_ready()" are used to
manipulate this maintenance status. They're used by the CLI and the stats
page.

Now the stats page always says "MAINT" instead of "MAINT(via)" and it's
only the chk/down field which reports "via x/y" when the status is
inherited from another server, but it doesn't say it when a server was
forced into maintenance. The CSV output indicates "MAINT (via x/y)"
instead of only "MAINT(via)". This is the most accurate representation.

One important thing is that now entering/leaving maintenance for a
tracking server correctly follows the state of the tracked server.
2014-05-22 11:27:00 +02:00
Willy Tarreau
4aac7db940 REORG: checks: put the functions in the appropriate files !
Checks.c has become a total mess. A number of proxy or server maintenance
and queue management functions were put there probably because they were
used there, but that makes the code untouchable. And that's without saying
that their names does not always relate to what they really do!

So let's do a first pass by moving these ones :
  - set_backend_down()       => backend.c
  - redistribute_pending()   => queue.c:pendconn_redistribute()
  - check_for_pending()      => queue.c:pendconn_grab_from_px()
  - shutdown_sessions        => server.c:srv_shutdown_sessions()
  - shutdown_backup_sessions => server.c:srv_shutdown_backup_sessions()

All of them were moved at once.
2014-05-22 11:27:00 +02:00
Willy Tarreau
892337c8e1 MAJOR: server: use states instead of flags to store the server state
Servers used to have 3 flags to store a state, now they have 4 states
instead. This avoids lots of confusion for the 4 remaining undefined
states.

The encoding from the previous to the new states can be represented
this way :

  SRV_STF_RUNNING
   |  SRV_STF_GOINGDOWN
   |   |  SRV_STF_WARMINGUP
   |   |   |
   0   x   x     SRV_ST_STOPPED
   1   0   0     SRV_ST_RUNNING
   1   0   1     SRV_ST_STARTING
   1   1   x     SRV_ST_STOPPING

Note that the case where all bits were set used to exist and was randomly
dealt with. For example, the task was not stopped, the throttle value was
still updated and reported in the stats and in the http_server_state header.
It was the same if the server was stopped by the agent or for maintenance.

It's worth noting that the internal function names are still quite confusing.
2014-05-22 11:27:00 +02:00
Willy Tarreau
2012521d7b REORG/MEDIUM: server: move the maintenance bits out of the server state
Now we introduce srv->admin and srv->prev_admin which are bitfields
containing one bit per source of administrative status (maintenance only
for now). For the sake of backwards compatibility we implement a single
source (ADMF_FMAINT) but the code already checks any source (ADMF_MAINT)
where the STF_MAINTAIN bit was previously checked. This will later allow
us to add ADMF_IMAINT for maintenance mode inherited from tracked servers.

Along doing these changes, it appeared that some places will need to be
revisited when implementing the inherited bit, this concerns all those
modifying the ADMF_FMAINT bit (enable/disable actions on the CLI or stats
page), and the checks to report "via" on the stats page. But currently
the code is harmless.
2014-05-22 11:27:00 +02:00
Willy Tarreau
c93cd16b6c REORG/MEDIUM: server: split server state and flags in two different variables
Till now, the server's state and flags were all saved as a single bit
field. It causes some difficulties because we'd like to have an enum
for the state and separate flags.

This commit starts by splitting them in two distinct fields. The first
one is srv->state (with its counter-part srv->prev_state) which are now
enums, but which still contain bits (SRV_STF_*).

The flags now lie in their own field (srv->flags).

The function srv_is_usable() was updated to use the enum as input, since
it already used to deal only with the state.

Note that currently, the maintenance mode is still in the state for
simplicity, but it must move as well.
2014-05-22 11:27:00 +02:00
Willy Tarreau
fac5b5956b MEDIUM: proxy: make timeout parser a bit stricter
Twice in a week I found people were surprized by a "conditional timeout" not
being respected, because they add "if <cond>" after a timeout, and since
they don't see any error nor read the doc, the expect it to work. Let's
make the timeout parser reject extra arguments to avoid these situations.
2014-05-22 08:26:41 +02:00
Willy Tarreau
efe282260e BUG/MINOR: stats: tracking servers may incorrectly report an inherited DRAIN status
The DRAIN status is not inherited between tracked servers, so the stats
page must only use the reported server's status and not the tracked
server's status, otherwise it misleadingly indicates a DRAIN state when
a server tracks a draining server, while this is wrong.
2014-05-21 17:13:13 +02:00
Willy Tarreau
0943757a21 BUG/MEDIUM: session: don't clear CF_READ_NOEXP if analysers are not called
As more or less suspected, commit b1982e2 ("BUG/MEDIUM: http/session:
disable client-side expiration only after body") was hazardous. It
introduced a regression causing client side timeout to expire during
connection retries if it's lower than the time needed to cover the
amount of retries, so clients get a 408 when the connection to the
server fails to establish fast enough.

The reason is that the CF_READ_NOEXP flag is set after the MSG_DONE state
is reached, which protects the timeout from being re-armed, then during
the retries, process_session() clears the flag without calling the analyser
(since there's no activity for it), so the timeouts are rearmed.

Ideally, these one-shot flags should be per-analyser, and the analyser
which sets them would be responsible for clearing them, or they would
automatically be cleared when switching to another analyser. Unfortunately
this is not really possible currently.

What can be done however is to only clear them in the following situations :
  - we're going to call analysers
  - analysers have all been unsubscribed

This method seems reliable enough and approaches the ideal case well enough.

No backport is needed, this bug was introduced in 1.5-dev25.
2014-05-21 16:58:17 +02:00
Conrad Hoffmann
041751c13a BUG/MEDIUM: polling: fix possible CPU hogging of worker processes after receiving SIGUSR1.
When run in daemon mode (i.e. with at least one forked process) and using
the epoll poller, sending USR1 (graceful shutdown) to the worker processes
can cause some workers to start running at 100% CPU. Precondition is having
an established HTTP keep-alive connection when the signal is received.

The cloned (during fork) listening sockets do not get closed in the parent
process, thus they do not get removed from the epoll set automatically
(see man 7 epoll). This can lead to the process receiving epoll events
that it doesn't feel responsible for, resulting in an endless loop around
epoll_wait() delivering these events.

The solution is to explicitly remove these file descriptors from the epoll
set. To not degrade performance, care was taken to only do this when
neccessary, i.e. when the file descriptor was cloned during fork.

Signed-off-by: Conrad Hoffmann <conrad@soundcloud.com>
[wt: a backport to 1.4 could be studied though chances to catch the bug are low]
2014-05-20 14:57:36 +02:00
Remi Gacogne
af5c3da89e MINOR: ssl: SSL_CTX_set_options() and SSL_CTX_set_mode() take a long, not an int
This is a minor fix, but the SSL_CTX_set_options() and
SSL_CTX_set_mode() functions take a long, not an int parameter. As
SSL_OP_ALL is now (since OpenSSL 1.0.0) defined as 0x80000BFFL, I think
it is worth fixing.
2014-05-19 11:20:23 +02:00
Willy Tarreau
63af98d0dd BUG/MAJOR: config: don't free valid regex memory
Thomas Heil reported that previous commit 07fcaaa ("MINOR: fix a few
memory usage errors") make haproxy crash when req* rules are used. As
diagnosed by Cyril Bonté, this commit introduced a regression which
makes haproxy free the memory areas allocated for regex even when
they're going to be used, resulting in the crashes.

This patch does three things :
  - undo the free() on the valid path
  - add regfree() on the error path but only when regcomp() succeeds
  - rename err_code to ret_code to avoid confusing the valid return
    path with an error path.
2014-05-18 08:11:41 +02:00
Dirkjan Bussink
07fcaaa4cd MINOR: fix a few memory usage errors
These are either use after free errors or small leaks where memory
is not free'd after some error state is detected.
2014-05-15 08:06:57 +02:00
Willy Tarreau
e21f84903e BUG/MINOR: stats: do not report "100%" in the thottle column when server is draining
A condition was missing and we used to have "throttle 100%" even when
the server was draining connections, which is misleading but harmless.
2014-05-14 00:09:59 +02:00
Willy Tarreau
87eb1d6994 MINOR: server: create srv_was_usable() from srv_is_usable() and use a pointer
We used to call srv_is_usable() with either the current state and weights
or the previous ones. This causes trouble for future changes, so let's first
split it in two variants :
  - srv_is_usable(srv) considers the current status
  - srv_was_usable(srv) considers the previous status
2014-05-13 22:34:55 +02:00
Willy Tarreau
c5150dafd8 MINOR: server: use functions to detect state changes and to update them
Detecting that a server's status has changed is a bit messy, as well
as it is to commit the status changes. We'll have to add new conditions
soon and we'd better avoid to multiply the number of touched locations
with the high risk of forgetting them.

This commit introduces :
  - srv_lb_status_changed() to report if the status changed from the
    previously committed one ;
  - svr_lb_commit_status() to commit the current status

The function is now used by all load-balancing algorithms.
2014-05-13 22:18:22 +02:00
Willy Tarreau
02615f9b16 MINOR: server: remove the SRV_DRAIN flag which can always be deduced
This flag is only a copy of (srv->uweight == 0), so better get rid of
it to reduce some of the confusion that remains in the code, and use
a simple function to return this state based on this weight instead.
2014-05-13 22:18:13 +02:00
Willy Tarreau
bef1b32c4e MINOR: checks: simplify and improve reporting of state changes when using log-health-checks
Function set_server_check_status() is very weird. It is called at the
end of a check to update the server's state before the new state is even
calculated, and possibly to log status changes, only if the proxy has
"option log-health-checks" set.

In order to do so, it employs an exhaustive list of the combinations
which can lead to a state change, while in practice almost all of
them may simply be deduced from the change of check status. Better,
some changes of check status are currently not detected while they
can be very valuable (eg: changes between L4/L6/TOUT/HTTP 500 for
example).

The doc was updated to reflect this.

Also, a minor change was made to consider s->uweight and not s->eweight
as meaning "DRAIN" since eweight can be null without the DRAIN mode (eg:
throttle, NOLB, ...).
2014-05-13 22:01:28 +02:00
Willy Tarreau
d03fdf41ec MINOR: stats: improve alignment of color codes to save one line of header
Having both "active or backup DOWN" and "not checked" on the left side of
the color caption inflates the whole header block for no reason. Simply
move them both on the same line and reduce the header height.
2014-05-13 22:01:21 +02:00
Willy Tarreau
ec6b012bf4 BUG/MINOR: checks: tcp-check must not stop on '\0' for binary checks
Abuse of copy-paste has made "tcp-check expect binary" to consider a
buffer starting with \0 as empty! Thanks to Lukas Benes for reporting
this problem and confirming the fix.

This is 1.5-only, no backport is needed.
2014-05-13 18:02:04 +02:00
Willy Tarreau
4e5ed29668 BUG/MEDIUM: config: a stats-less config crashes in 1.5-dev25
John-Paul Bader reported a stupid regression in 1.5-dev25, we
forget to check that global.stats_fe is initialized before visiting
its sockets, resulting in a crash.

No backport is needed.
2014-05-13 13:53:27 +02:00
Thierry FOURNIER
9fefbd5926 MINOR: acl: set "str" as default match for strings
It appears than many people considers that the default match for a fetch
returning string is "exact match string" aka "str". This patch set this
match as default for strings.
2014-05-12 15:19:15 +02:00
Cyril Bonté
c7fa7db7ce OPTIM: stats: avoid the calculation of a useless link on tracking servers in maintenance
Commit f465994198 removed the "via" link when a tracking server is in maintenance, but
still calculated an empty link that no one can use. We can safely remove it.
2014-05-12 01:02:46 +02:00
Cyril Bonté
d5de76a25b BUG/MINOR: stats: fix a typo on a closing tag for a server tracking another one
The "via" column includes a link to the tracked server but instead of closing
the link with a </a> tag, a new tag is opened.

This typo should also be backported to 1.4
2014-05-12 01:02:45 +02:00
Willy Tarreau
2039bba41b MEDIUM: acl: strenghten the option parser to report invalid options
Whatever ACL option beginning with a '-' is considered as a pattern
if it does not match a known option. This is a big problem because
typos are silently ignored, such as "-" or "-mi".

Better clearly check the complete option name and report a parsing
error if the option is unknown.
2014-05-11 09:43:46 +02:00
Willy Tarreau
05cdd9655d MEDIUM: session: implement half-closed timeouts (client-fin and server-fin)
Long-lived sessions are often subject to half-closed sessions resulting in
a lot of sessions appearing in FIN_WAIT state in the system tables, and no
way for haproxy to get rid of them. This typically happens because clients
suddenly disconnect without sending any packet (eg: FIN or RST was lost in
the path), and while the server detects this using an applicative heart
beat, haproxy does not close the connection.

This patch adds two new timeouts : "timeout client-fin" and
"timeout server-fin". The former allows one to override the client-facing
timeout when a FIN has been received or sent. The latter does the same for
server-facing connections, which is less useful.
2014-05-10 15:14:05 +02:00
Willy Tarreau
7bb21532f4 MEDIUM: unix: avoid a double connect probe when no data are sent
Plain "tcp" health checks sent to a unix socket cause two connect()
calls to be made, one to connect, and a second one to verify that the
connection properly established. But with unix sockets, we get
immediate notification of success, so we can avoid this second
attempt. However we need to ensure that we'll visit the connection
handler even if there's no remaining handshake pending, so for this
we claim we have some data to send in order to enable polling for
writes if there's no more handshake.
2014-05-10 09:48:28 +02:00
Willy Tarreau
b1dd9bf308 MEDIUM: pattern: use ebtree's longest match to index/lookup string beginning
Being able to map prefixes to values is already used for IPv4/IPv6
but was not yet used with strings. It can be very convenient to map
directories to server farms but large lists may be slow.

By using ebmb_insert_prefix() and ebmb_lookup_longest(), we can
insert strings with their own length as a prefix, and lookup
candidate strings and ensure that the longest matching one will
be returned, which is the longest string matching the entry.
2014-05-10 08:53:48 +02:00
Willy Tarreau
ccfccefb80 MEDIUM: unix: implement support for Linux abstract namespace sockets
These sockets are the same as Unix sockets except that there's no need
for any filesystem access. The address may be whatever string both sides
agree upon. This can be really convenient for inter-process communications
as well as for chaining backends to frontends.

These addresses are forced by prepending their address with "abns@" for
"abstract namespace".
2014-05-10 01:53:58 +02:00
Willy Tarreau
5cf0b52d29 MEDIUM: checks: only complain about the missing port when the check uses TCP
For UNIX socket addresses, we don't need any port, so let's disable the
check under this condition.
2014-05-10 01:26:38 +02:00
Willy Tarreau
47f48c4247 MEDIUM: unix: add preliminary support for connecting to servers over UNIX sockets
We've had everything in place for this for a while now, we just missed
the connect function for UNIX sockets. Note that in order to connect to
a UNIX socket inside a chroot, the path will have to be relative to the
chroot.

UNIX sockets connect about twice as fast as TCP sockets (or consume
about half of the CPU at the same rate). This is interesting for
internal communications between SSL processes and HTTP processes
for example, or simply to avoid allocating source ports on the
loopback.

The tcp_connect_probe() function is still used to probe a dataless
connection, but it is compatible so that's not an issue for now.

Health checks are not yet fully supported since they require a port.
2014-05-10 01:26:38 +02:00
Willy Tarreau
9cf8d3f46b MINOR: protocols: use is_inet_addr() when only INET addresses are desired
We used to have is_addr() in place to validate sometimes the existence
of an address, sometimes a valid IPv4 or IPv6 address. Replace them
carefully so that is_inet_addr() is used wherever we can only use an
IPv4/IPv6 address.
2014-05-10 01:26:37 +02:00
Willy Tarreau
640556c692 BUG/MINOR: checks: correctly configure the address family and protocol
Currently, mixing an IPv4 and an IPv6 address in checks happens to
work by pure luck because the two protocols use the same functions
at the socket level and both use IPPROTO_TCP. However, they're
definitely wrong as the protocol for the check address is retrieved
from the server's address.

Now the protocol assigned to the connection is the same as the one
the address in use belongs to (eg: the server's address or the
explicit check address).
2014-05-10 01:26:37 +02:00
Willy Tarreau
28e9d06201 BUG/MINOR: backend: only match IPv4 addresses with RDP cookies
The RDP cookie extractor compares the 32-bit address from the request
to the address of each server in the farm without first checking that
the server's address is IPv4. This is a leftover from the IPv4 to IPv6
conversion. It's harmless as it's unlikely that IPv4 and IPv6 servers
will be mixed in an RDP farm, but better fix it.

This patch does not need to be backported.
2014-05-10 01:26:37 +02:00
Willy Tarreau
acf3bf94d0 CLEANUP: config: set the maxaccept value for peers listeners earlier
Since we introduced bind_conf in peers, we can set maxaccept in a cleaner
way at the proper time, let's do this to make the code more readable.
2014-05-09 22:12:24 +02:00
Willy Tarreau
67c2abc2f3 MINOR: config: only report a warning when stats sockets are bound to more than 1 process
Till now a warning was emitted if the "stats bind-process" was not
specified when nbproc was greater than 1. Now we can be much finer
and only emit a warning when at least of the stats socket is bound
to more than one process at a time.
2014-05-09 19:16:26 +02:00
Willy Tarreau
ae30253c27 MAJOR: listener: only start listeners bound to the same processes
Now that we know what processes a "bind" statement is attached to, we
have the ability to avoid starting some of them when they're not on the
proper process. This feature is disabled when running in foreground
however, so that debug mode continues to work with everything bound to
the first and only process.

The main purpose of this change is to finally allow the global stats
sockets to be each bound to a different process.

It can also be used to force haproxy to use different sockets in different
processes for the same IP:port. The purpose is that under Linux 3.9 and
above (and possibly other OSes), when multiple processes are bound to the
same IP:port via different sockets, the system is capable of performing
a perfect round-robin between the socket queues instead of letting any
process pick all the connections from a queue. This results in a smoother
load balancing and may achieve a higher performance with a large enough
maxaccept setting.
2014-05-09 19:16:26 +02:00
Willy Tarreau
3d20958190 MEDIUM: listener: inherit the process mask from the proxy
When a process list is specified on either the proxy or the bind lines,
the latter is refined to the intersection of the two. A warning is emitted
if no intersection is found, and the situation is fixed by either falling
back to the first process of the proxy or to all processes.
2014-05-09 19:16:26 +02:00
Willy Tarreau
6ae1ba6f29 MEDIUM: listener: parse the new "process" bind keyword
This sets the bind_proc entry in the bind_conf config block. For now it's
still unused, but the doc was updated.
2014-05-09 19:16:26 +02:00
Willy Tarreau
102df613a9 MEDIUM: config: check the bind-process settings according to nbproc
When a bind-process setting is present in a frontend or backend, we
now verify that the specified process range at least shares one common
process with those defined globally by nbproc. Then if the value is
set, it is reduced to the one enforced by nbproc.

A warning is emitted if process count does not match, and the fix is
done the following way :
  - if a single process was specified in the range, it's remapped to
    process #1
  - if more than one process was specified, the binding is removed
    and all processes are usable.

Note that since backends may inherit their settings from frontends,
depending on the declaration order, they may or may not be reported
as warnings.
2014-05-09 19:16:26 +02:00
Willy Tarreau
a9db57ec5c MEDIUM: config: limit nbproc to the machine's word size
Some consistency checks cannot be performed between frontends, backends
and peers at the moment because there is no way to check for intersection
between processes bound to some processes when the number of processes is
higher than the number of bits in a word.

So first, let's limit the number of processes to the machine's word size.
This means nbproc will be limited to 32 on 32-bit machines and 64 on 64-bit
machines. This is far more than enough considering that configs rarely go
above 16 processes due to scalability and management issues, so 32 or 64
should be fine.

This way we'll ensure we can always build a mask of all the processes a
section is bound to.
2014-05-09 19:16:26 +02:00
Willy Tarreau
3507d5d096 MEDIUM: proxy: only adjust the backend's bind-process when already set
By default, a proxy's bind_proc is zero, meaning "bind to all processes".
It's only when not zero that its process list is restricted. So we don't
want the frontends to enforce the value on the backends when the backends
are still set to zero.
2014-05-09 19:16:26 +02:00
Emeric Brun
93ee249fd1 MINOR: ssl: remove fallback to SSL session private cache if lock init fails.
Now, haproxy exit an error saying:
Unable to initialize the lock for the shared SSL session cache. You can retry using
the global statement 'tune.ssl.force-private-cache' but it could increase the CPU
usage due to renegotiation if nbproc > 1.
2014-05-09 19:16:13 +02:00
Emeric Brun
8dc6039807 MINOR: ssl: add global statement tune.ssl.force-private-cache.
Boolean: used to force a private ssl session cache for each process in
case of nbproc > 1.
2014-05-09 19:16:13 +02:00
Emeric Brun
78bd4038d7 BUG/MINOR: chunk: Fix function chunk_strcmp and chunk_strcasecmp match a substring.
They could match different strings as equal if the chunk was shorter
than the string. Those functions are currently only used for SSL's
certificate DN entry extract.
2014-05-09 19:16:13 +02:00
David S
afb768340c MEDIUM: connection: Implement and extented PROXY Protocol V2
This commit modifies the PROXY protocol V2 specification to support headers
longer than 255 bytes allowing for optional extensions.  It implements the
PROXY protocol V2 which is a binary representation of V1. This will make
parsing more efficient for clients who will know in advance exactly how
many bytes to read.  Also, it defines and implements some optional PROXY
protocol V2 extensions to send information about downstream SSL/TLS
connections.  Support for PROXY protocol V1 remains unchanged.
2014-05-09 08:25:38 +02:00
Willy Tarreau
b4f98098aa BUG/MAJOR: session: recover the correct connection pointer in half-initialized sessions
John-Paul Bader reported a nasty segv which happens after a few hours
when SSL is enabled under a high load. Fortunately he could catch a
stack trace, systematically looking like this one :

(gdb) bt full
        level = 6
        conn = (struct connection *) 0x0
        err_msg = <value optimized out>
        s = (struct session *) 0x80337f800
        conn = <value optimized out>
        flags = 41997063
        new_updt = <value optimized out>
        old_updt = 1
        e = <value optimized out>
        status = 0
        fd = 53999616
        nbfd = 279
        wait_time = <value optimized out>
        updt_idx = <value optimized out>
        en = <value optimized out>
        eo = <value optimized out>
        count = 78
        sr = <value optimized out>
        sw = <value optimized out>
        rn = <value optimized out>
        wn = <value optimized out>

The variable "flags" in conn_fd_handler() holds a copy of connection->flags
when entering the function. These flags indicate 41997063 = 0x0280d307 :
  - {SOCK,DATA,CURR}_RD_ENA=1       => it's a handshake, waiting for reading
  - {SOCK,DATA,CURR}_WR_ENA=0       => no need for writing
  - CTRL_READY=1                    => FD is still allocated
  - XPRT_READY=1                    => transport layer is initialized
  - ADDR_FROM_SET=1, ADDR_TO_SET=0  => clearly it's a frontend connection
  - INIT_DATA=1, WAKE_DATA=1        => processing a handshake (ssl I guess)
  - {DATA,SOCK}_{RD,WR}_SH=0        => no shutdown
  - ERROR=0, CONNECTED=0            => handshake not completed yet
  - WAIT_L4_CONN=0                  => normal
  - WAIT_L6_CONN=1                  => waiting for an L6 handshake to complete
  - SSL_WAIT_HS=1                   => the pending handshake is an SSL handshake

So this is a handshake is in progress. And the only way to reach line 88
is for the handshake to complete without error. So we know for sure that
ssl_sock_handshake() was called and completed the handshake then removed
the CO_FL_SSL_WAIT_HS flag from the connection. With these flags,
ssl_sock_handshake() does only call SSL_do_handshake() and retruns. So
that means that the problem is necessarily in data->init().

The fd is wrong as reported but is simply mis-decoded as it's the lower
half of the last function pointer.

What happens in practice is that there's an issue with the way we deal
with embryonic sessions during their conversion to regular sessions.
Since they have no stream interface at the beginning, the pointer to
the connection is temporarily stored into s->target. Then during their
conversion, the first stream interface is properly initialized and the
connection is attached to it, then s->target is set to NULL.

The problem is that if anything fails in session_complete(), the
session is left in this intermediate state where s->target is NULL,
and kill_mini_session() is called afterwards to perform the cleanup.
It needs the connection, that it finds in s->target which is NULL,
dereferences it and dies. The only reasons for dying here are a problem
on the TCP connection when doing the setsockopt(TCP_NODELAY) or a
memory allocation issue.

This patch implements a solution consisting in restoring s->target in
session_complete() on the error path. That way embryonic sessions that
were valid before calling it are still valid after.

The bug was introduced in 1.5-dev20 by commit f8a49ea ("MEDIUM: session:
attach incoming connection to target on embryonic sessions"). No backport
is needed.

Special thanks to John for his numerous tests and traces.
2014-05-08 22:46:32 +02:00
Emeric Brun
cd1a526a90 MAJOR: ssl: Change default locks on ssl session cache.
Prevously pthread process shared lock were used by default,
if USE_SYSCALL_FUTEX is not specified.

This patch implements an OS independant kind of lock:
An active spinlock is usedf if USE_SYSCALL_FUTEX is not specified.

The old behavior is still available if USE_PTHREAD_PSHARED=1.
2014-05-08 22:46:32 +02:00
Emeric Brun
caa19cc867 BUG/MAJOR: ssl: Fallback to private session cache if current lock mode is not supported.
Process shared mutex seems not supported on some OSs (FreeBSD).

This patch checks errors on mutex lock init to fallback
on a private session cache (per process cache) in error cases.
2014-05-08 22:46:32 +02:00
Willy Tarreau
5cbe4ef265 BUILD: ssl: SSL_CTX_set_msg_callback() needs openssl >= 0.9.7
1.5-dev24 introduced SSL_CTX_set_msg_callback(), which came with OpenSSL
0.9.7. A build attempt with an older one failed and we're still compatible
with 0.9.6 in 1.5.
2014-05-08 22:46:31 +02:00
Willy Tarreau
bb66030a30 MEDIUM: listener: make the accept function more robust against pauses
During some tests in multi-process mode under Linux, it appeared that
issuing "disable frontend foo" on the CLI to pause a listener would
make the shutdown(read) of certain processes disturb another process
listening on the same socket, resulting in a 100% CPU loop. What
happens is that accept() returns EAGAIN without accepting anything.
Fortunately, we see that epoll_wait() reports EPOLLIN+EPOLLRDHUP
(likely because the FD points to the same file in the kernel), so we
can use that to stop the other process from trying to accept connections
for a short time and try again later, hoping for the situation to change.
We must not disable the FD otherwise there's no way to re-enable it.

Additionally, during these tests, a loop was encountered on EINVAL which
was not caught. Now if we catch an EINVAL, we proceed the same way, in
case the socket is re-enabled later.
2014-05-07 23:13:08 +02:00
Willy Tarreau
3bed5e9337 BUG/MEDIUM: http: disable server-side expiration until client has sent the body
It's the final part of the 2 previous patches. We prevent the server from
timing out if we still have some data to pass to it. That way, even if the
server runs with a short timeout and the client with a large one, the server
side timeout will only start to count once the client sends everything. This
ensures we don't report a 504 before the server gets the whole request.

It is not certain whether the 1.4 state machine is fully compatible with
this change. Since the purpose is only to ensure that we never report a
server error before a client error if some data are missing from the client
and when the server-side timeout is smaller than or equal to the client's,
it's probably not worth attempting the backport.
2014-05-07 15:23:52 +02:00
Willy Tarreau
b9edf8fbec BUG/MEDIUM: http: correctly report request body timeouts
This is the continuation of previous patch "BUG/MEDIUM: http/session:
disable client-side expiration only after body".

This one takes care of properly reporting the client-side read timeout
when waiting for a body from the client. Since the timeout may happen
before or after the server starts to respond, we have to take care of
the situation in three different ways :
  - if the server does not read our data fast enough, we emit a 504
    if we're waiting for headers, or we simply break the connection
    if headers were already received. We report either sH or sD
    depending on whether we've seen headers or not.

  - if the server has not yet started to respond, but has read all of
    the client's data and we're still waiting for more data from the
    client, we can safely emit a 408 and abort the request ;

  - if the server has already started to respond (thus it's a transfer
    timeout during a bidirectional exchange), then we silently break
    the connection, and only the session flags will indicate in the
    logs that something went wrong with client or server side.

This bug is tagged MEDIUM because it touches very sensible areas, however
its impact is very low. It might be worth performing a careful backport
to 1.4 once it has been confirmed that everything is correct and that it
does not introduce any regression.
2014-05-07 15:22:27 +02:00
Willy Tarreau
b1982e27aa BUG/MEDIUM: http/session: disable client-side expiration only after body
For a very long time, back in the v1.3 days, we used to rely on a trick
to avoid expiring the client side while transferring a payload to the
server. The problem was that if a client was able to quickly fill the
buffers, and these buffers took some time to reach the server, the
client should not expire while not sending anything.

In order to cover this situation, the client-side timeout was disabled
once the connection to the server was OK, since it implied that we would
at least expire on the server if required.

But there is a drawback to this : if a client stops uploading data before
the end, its timeout is not enforced and we only expire on the server's
timeout, so the logs report a 504.

Since 1.4, we have message body analysers which ensure that we know whether
all the expected data was received or not (HTTP_MSG_DATA or HTTP_MSG_DONE).
So we can fix this problem by disabling the client-side or server-side
timeout at the end of the transfer for the respective side instead of
having it unconditionally in session.c during all the transfer.

With this, the logs now report the correct side for the timeout. Note that
this patch is not enough, because another issue remains : the HTTP body
forwarders do not abort upon timeout, they simply rely on the generic
handling from session.c. So for now, the session is still aborted when
reaching the server timeout, but the culprit is properly reported. A
subsequent patch will address this specific point.

This bug was tagged MEDIUM because of the changes performed. The issue
it fixes is minor however. After some cooling down, it may be backported
to 1.4.

It was reported by and discussed with Rachel Chavez and Patrick Hemmer
on the mailing list.
2014-05-07 14:21:47 +02:00
William Lallemand
07c8b24edb MINOR: http: export the smp_fetch_cookie function
Remove the static attribute of smp_fetch_cookie, and declare the
function in proto/proto_http.h for future use.
2014-05-02 18:05:15 +02:00
Emeric Brun
b73a9b039c MINOR: ssl: convert to binary ssl_fc_unique_id and ssl_bc_unique_id.
Previously ssl_fc_unique_id and ssl_bc_unique_id return a string encoded
in base64 of the RFC 5929 TLS unique identifier. This patch modify those fetches
to return directly the ID in the original binary format. The user can make the
choice to encode in base64 using the converter.

i.e. : ssl_fc_unique_id,base64
2014-04-30 22:31:11 +02:00
Emeric Brun
53d1a98270 MINOR: ssl: adds sample converter base64 for binary type.
The new converter encode binary type sample to base64 string.

i.e. : ssl_c_serial,base64
2014-04-30 22:31:11 +02:00
Emeric Brun
55f4fa8825 MINOR: ssl: adds ssl_f_sha1 fetch to return frontend's certificate fingerprint
ssl_f_sha1 is a binary binary fetch used to returns the SHA-1 fingerprint of
the certificate presented by the frontend when the incoming connection was
made over an SSL/TLS transport layer. This can be used to know which
certificate was chosen using SNI.
2014-04-30 22:31:11 +02:00
Emeric Brun
ba841a1da1 MINOR: ssl: merge client's and frontend's certificate functions. 2014-04-30 22:31:11 +02:00
Emeric Brun
645ae79b40 MINOR: ssl: adds fetchs and ACLs for ssl back connection.
Adds ssl fetchs and ACLs for outgoinf SSL/Transport layer connection with their
docs:
ssl_bc, ssl_bc_alg_keysize, ssl_bc_cipher, ssl_bc_protocol, ssl_bc_unique_id,
ssl_bc_session_id and ssl_bc_use_keysize.
2014-04-30 22:31:11 +02:00
Emeric Brun
5bd99b4bd6 MINOR: ssl: clean unused ACLs declarations
Now those ACLs are automatically created from pattern fetch declare.
2014-04-30 22:16:39 +02:00
Willy Tarreau
644c101e2d BUG/MAJOR: http: connection setup may stall on balance url_param
On the mailing list, seri0528@naver.com reported an issue when
using balance url_param or balance uri. The request would sometimes
stall forever.

Cyril Bonté managed to reproduce it with the configuration below :

  listen test :80
    mode http
    balance url_param q
    hash-type consistent
    server s demo.1wt.eu:80

and found it appeared with this commit : 80a92c0 ("BUG/MEDIUM: http:
don't start to forward request data before the connect").

The bug is subtle but real. The problem is that the HTTP request
forwarding analyzer refrains from starting to parse the request
body when some LB algorithms might need the body contents, in order
to preserve the data pointer and avoid moving things around during
analysis in case a redispatch is later needed. And in order to detect
that the connection establishes, it watches the response channel's
CF_READ_ATTACHED flag.

The problem is that a request analyzer is not subscribed to a response
channel, so it will only see changes when woken for other (generally
correlated) reasons, such as the fact that part of the request could
be sent. And since the CF_READ_ATTACHED flag is cleared once leaving
process_session(), it is important not to miss it. It simply happens
that sometimes the server starts to respond in a sequence that validates
the connection in the middle of process_session(), that it is detected
after the analysers, and that the newly assigned CF_READ_ATTACHED is
not used to detect that the request analysers need to be called again,
then the flag is lost.

The CF_WAKE_WRITE flag doesn't work either because it's cleared upon
entry into process_session(), ie if we spend more than one call not
connecting.

Thus we need a new flag to tell the connection initiator that we are
specifically interested in being notified about connection establishment.
This new flag is CF_WAKE_CONNECT. It is set by the requester, and is
cleared once the connection succeeds, where CF_WAKE_ONCE is set instead,
causing the request analysers to be scanned again.

For future versions, some better options will have to be considered :
  - let all analysers subscribe to both request and response events ;
  - let analysers subscribe to stream interface events (reduces number
    of useless calls)
  - change CF_WAKE_WRITE's semantics to persist across calls to
    process_session(), but that is different from validating a
    connection establishment (eg: no data sent, or no data to send)

The bug was introduced in 1.5-dev23, no backport is needed.
2014-04-30 20:02:02 +02:00
Willy Tarreau
7c29f1edca BUILD: config: remove a warning with clang
Commit fc6c032 ("MEDIUM: global: add support for CPU binding on Linux ("cpu-map")")
merged into 1.5-dev13 involves a useless test that clang reports as a warning. The
"low" variable cannot be negative here. Issue reported by Charles Carter.
2014-04-29 19:55:25 +02:00
Willy Tarreau
86e0fc1739 BUG/MINOR: auth: fix wrong return type in pat_match_auth()
Commit 5338eea ("MEDIUM: pattern: The match function browse itself the
list or the tree") changed the return type of pattern matching functions.
One enum was left over in pat_match_auth(). Fortunately, this one equals
zero where a null pointer is expected, so it's cast correctly.

This detected and reported by Charles Carter was introduced in 1.5-dev23,
no backport is needed.
2014-04-29 19:52:16 +02:00
Willy Tarreau
ed44649eb7 MEDIUM: config: warn that '{cli,con,srv}timeout' are deprecated
It's been like this since version 1.3 in 2007. It's time to clean
up configurations. The warning explains what to use depending on
the timeout name.
2014-04-29 01:09:56 +02:00
Willy Tarreau
a3c504c032 MEDIUM: config: inform the user only once that "redispatch" is deprecated
It may go away in 1.6, but there's no point reporting it for each and
every occurrence.
2014-04-29 01:09:40 +02:00
Willy Tarreau
40bac83734 MEDIUM: config: inform the user that "reqsetbe" is deprecated
It will go away in 1.6.
2014-04-29 00:46:01 +02:00
Willy Tarreau
de9d2d7b86 MEDIUM: config: inform the user about the deprecatedness of "block" rules
It's just a warning emitted once.
2014-04-29 00:46:01 +02:00
Willy Tarreau
ff05550b5d MINOR: config: add minimum support for emitting warnings only once
This is useful to explain to users what to do during a migration.
2014-04-29 00:46:01 +02:00
Willy Tarreau
0b7483385e MEDIUM: http: make http-request rules processing return a verdict instead of a rule
Till now we used to return a pointer to a rule, but that makes it
complicated to later add support for registering new actions which
may fail. For example, the redirect may fail if the response is too
large to fit into the buffer.

So instead let's return a verdict. But we needed the pointer to the
last rule to get the address of a redirect and to get the realm used
by the auth page. So these pieces of code have moved into the function
and they produce a verdict.
2014-04-29 00:46:01 +02:00
Willy Tarreau
ae3c010226 MEDIUM: http: factorize the "auth" action of http-request and stats
Both use exactly the same mechanism, except for the choice of the
default realm to be emitted when none is selected. It can be achieved
by simply comparing the ruleset with the stats' for now. This achieves
a significant code reduction and further, removes the dependence on
the pointer to the final rule in the caller.
2014-04-29 00:46:01 +02:00
Willy Tarreau
f75e5c3d84 MINOR: http: remove the now unused loop over "block" rules
This ruleset is now always empty, simply remove it.
2014-04-28 22:15:00 +02:00
Willy Tarreau
b3dc39dfe1 MEDIUM: http: emulate "block" rules using "http-request" rules
The "block" rules are redundant with http-request rules because they
are performed immediately before and do exactly the same thing as
"http-request deny". Moreover, this duplication has led to a few
minor stats accounting issues fixed lately.

Instead of keeping the two rule sets, we now build a list of "block"
rules that we compile as "http-request block" and that we later insert
at the beginning of the "http-request" rules.

The only user-visible change is that in case of a parsing error, the
config parser will now report "http-request block rule" instead of
"blocking condition".
2014-04-28 22:06:57 +02:00
Willy Tarreau
353bc9f43f CLEANUP: proxy: rename "block_cond" to "block_rules"
Next patch will make them real rules, not only conditions. This separate
patch makes the next one more readable.
2014-04-28 22:05:31 +02:00
Willy Tarreau
5bd6759a19 MINOR: http: silently support the "block" action for http-request
This one will be used to convert "block" rules into "http-request block".
2014-04-28 22:00:46 +02:00
Willy Tarreau
5254259609 MEDIUM: http: remove even more of the spaghetti in the request path
Some of the remaining interleaving of request processing after the
http-request rules can now safely be removed, because all remaining
actions are mutually exclusive.

So we can move together all those related to an intercepting rule,
then proceed with stats, then with req*.

We still keep an issue with stats vs reqrep which forces us to
keep the stats split in two (detection and action). Indeed, from the
beginning, stats are detected before rewriting and not after. But a
reqdeny rule would stop stats, so in practice we have to first detect,
then perform the action. Maybe we'll be able to kill this in version
1.6.
2014-04-28 21:35:30 +02:00
Willy Tarreau
179085ccac MEDIUM: http: move Connection header processing earlier
Till now the Connection header was processed in the middle of the http-request
rules and some reqadd rules. It used to force some http-request actions to be
cut in two parts.

Now with keep-alive, not only that doesn't make any sense anymore, but it's
becoming a total mess, especially since we need to know the headers contents
before proceeding with most actions.

The real reason it was not moved earlier is that the "block" or "http-request"
rules can see a different version if some fields are changed there. But that
is already not reliable anymore since the values observed by the frontend
differ from those in the backend.

This patch is the equivalent of commit f118d9f ("REORG: http: move HTTP
Connection response header parsing earlier") but for the request side. It
has been tagged MEDIUM as it could theorically slightly affect some setups
relying on corner cases or invalid setups, though this does not make real
sense and is highly unlikely.
2014-04-28 21:35:29 +02:00
Willy Tarreau
65410831a1 BUG/MINOR: http: block rules forgot to increment the session's request counter
The session's backend request counters were incremented after the block
rules while these rules could increment the session's error counters,
meaning that we could have more errors than requests reported in a stick
table! Commit 5d5b5d8 ("MEDIUM: proto_tcp: add support for tracking L7
information") is the most responsible for this.

This bug is 1.5-specific and does not need any backport.
2014-04-28 21:34:43 +02:00
Willy Tarreau
5fa7082911 BUG/MINOR: http: block rules forgot to increment the denied_req counter
"block" rules used to build the whole response and forgot to increment
the denied_req counters. By jumping to the general "deny" label created
in previous patch, it's easier to fix this.

The issue was already present in 1.3 and remained unnoticed, in part
because few people use "block" nowadays.
2014-04-28 18:46:40 +02:00
Willy Tarreau
bbba2a8ecc MEDIUM: http: jump to dedicated labels after http-request processing
Continue the cleanup of http-request post-processing to remove some
of the interleaved tests. Here we set up a few labels to deal with
the deny and tarpit actions and avoid interleaved ifs.
2014-04-28 18:46:20 +02:00
Willy Tarreau
5e9edce0f0 MEDIUM: http: move reqadd after execution of http_request redirect
We still have a plate of spaghetti in the request processing rules.
All http-request rules are executed at once, then some responses are
built interlaced with other rules that used to be there in the past.
Here, reqadd is executed after an http-req redirect rule is *decided*,
but before it is *executed*.

So let's match the doc and config checks, to put the redirect actually
before the reqadd completely.
2014-04-28 17:25:40 +02:00
Willy Tarreau
cfe7fdd02d MINOR: http: rely on the message body parser to send 100-continue
There's no point in open-coding the sending of 100-continue in
the stats initialization code, better simply rely on the function
designed to process the message body which already does it.
2014-04-28 17:25:40 +02:00
Willy Tarreau
e6d24163e5 BUG/MINOR: http: log 407 in case of proxy auth
Commit 844a7e7 ("[MEDIUM] http: add support for proxy authentication")
merged in v1.4-rc1 added the ability to emit a status code 407 in auth
responses, but forgot to set the same status in the logs, which still
contain 401.

The bug is harmless, no backport is needed.
2014-04-28 17:24:42 +02:00
Willy Tarreau
f767ac55a2 BUG/MINOR: proxy: unsafe initialization of HTTP transaction when switching from TCP frontend
A switch from a TCP frontend to an HTTP backend initializes the HTTP
transaction. txn->hdr_idx.size is used by hdr_idx_init() but not
necessarily initialized yet here, because the first call to hdr_idx_init()
is in fact placed in http_init_txn(). Moving it before the call is
enough to fix it. We also remove the useless extra confusing call
to hdr_idx_init().

The bug was introduced in 1.5-dev8 with commit ac1932d ("MEDIUM:
tune.http.maxhdr makes it possible to configure the maximum number
of HTTP headers"). No backport to stable is needed.
2014-04-28 17:24:39 +02:00
Thierry FOURNIER
e47e4e2385 BUG/MEDIUM: patterns: last fix was still not enough
Last fix did address the issue for inlined patterns, but it was not
enough because the flags are lost as well when updating patterns
dynamically over the CLI.

Also if the same file was used once with -i and another time without
-i, their references would have been merged and both would have used
the same matching method.

It's appear that the patterns have two types of flags. The first
ones are relative to the pattern matching, and the second are
relative to the pattern storage. The pattern matching flags are
the same for all the patterns of one expression. Now they are
stored in the expression. The storage flags are information
returned by the pattern mathing function. This information is
relative to each entry and is stored in the "struct pattern".

Now, the expression matching flags are forwarded to the parse
and index functions. These flags are stored during the
configuration parsing, and they are used during the parse and
index actions.

This issue was introduced in dev23 with the major pattern rework,
and is a continuation of commit a631fc8 ("BUG/MAJOR: patterns: -i
and -n are ignored for inlined patterns"). No backport is needed.
2014-04-28 14:19:17 +02:00
Willy Tarreau
a631fc8de8 BUG/MAJOR: patterns: -i and -n are ignored for inlined patterns
These flags are only passed to pattern_read_from_file() which
loads the patterns from a file. The functions used to parse the
patterns from the current line do not provide the means to pass
the pattern flags so they're lost.

This issue was introduced in dev23 with the major pattern rework,
and was reported by Graham Morley. No backport is needed.
2014-04-27 09:21:08 +02:00
Willy Tarreau
3b78696858 BUG/MEDIUM: pattern: a typo breaks automatic acl/map numbering
Dmitry Sivachenko reported that nice warning :
src/pattern.c:2243:43: warning: if statement has empty body [-Wempty-body]
                                if (&ref2->list == &pattern_reference);
                                                                      ^
src/pattern.c:2243:43: note: put the semicolon on a separate line to silence
      this warning

It was merged as is with the code from commit af5a29d ("MINOR: pattern:
Each pattern is identified by unique id").

So it looks like we can reassign an ID which is still in use because of
this.
2014-04-26 12:41:32 +02:00
Willy Tarreau
aeed672a6d MINOR: ssl: finally catch the heartbeats missing the padding
Previous patch only focused on parsing the packet right and blocking
it, so it relaxed one test on the packet length. The difference is
not usable for attacking but the logs will not report an attack for
such cases, which is probably bad. Better report all known invalid
packets cases.
2014-04-26 00:03:48 +02:00
Willy Tarreau
3b2fdb6f55 BUG/MINOR: ssl: really block OpenSSL's response to heartbleed attack
Recent commit f51c698 ("MEDIUM: ssl: implement a workaround for the
OpenSSL heartbleed attack") did not always work well, because OpenSSL
is fun enough for not testing errors before sending data... So the
output sometimes contained some data.

The OpenSSL code relies on the max_send_segment value to limit the
packet length. The code ensures that a value of zero will result in
no single byte leaking. So we're forcing this instead and that
definitely fixes the issue. Note that we need to set it the hard
way since the regular API checks for valid values.
2014-04-25 23:48:21 +02:00
Willy Tarreau
84815006a0 BUILD: ssl: avoid a warning about conn not used with OpenSSL < 1.0.1
Building with a version of openssl without heartbeat gives this since
latest 29f037d ("MEDIUM: ssl: explicitly log failed handshakes after a
heartbeat") :

src/ssl_sock.c: In function 'ssl_sock_msgcbk':
src/ssl_sock.c:188: warning: unused variable 'conn'

Simply declare conn inside the ifdef. No backport is needed.
2014-04-25 21:40:27 +02:00
Willy Tarreau
6c09c2ceae BUILD: http: remove a warning on strndup
The latest commit about set-map/add-acl/... causes this warning for
me :

src/proto_http.c: In function 'parse_http_req_cond':
src/proto_http.c:8863: warning: implicit declaration of function 'strndup'
src/proto_http.c:8863: warning: incompatible implicit declaration of built-in function 'strndup'
src/proto_http.c:8890: warning: incompatible implicit declaration of built-in function 'strndup'
src/proto_http.c:8917: warning: incompatible implicit declaration of built-in function 'strndup'
src/proto_http.c:8944: warning: incompatible implicit declaration of built-in function 'strndup'

Use my_strndup() instead of strndup() which is not portable. No backport
needed.
2014-04-25 21:39:17 +02:00
Willy Tarreau
6e774b455f BUG/MEDIUM: Revert "MEDIUM: ssl: Add standardized DH parameters >= 1024 bits"
This reverts commit 9ece05f590.

Sander Klein reported an important performance regression with this
patch applied. It is not yet certain what is exactly the cause but
let's not break other setups now and sort this out after dev24.

The commit was merged into dev23, no need to backport.
2014-04-25 21:35:23 +02:00
Willy Tarreau
f51c6989b0 MEDIUM: ssl: implement a workaround for the OpenSSL heartbleed attack
Using the previous callback, it's trivial to block the heartbeat attack,
first we control the message length, then we emit an SSL error if it is
out of bounds. A special log is emitted, indicating that a heartbleed
attack was stopped so that they are not confused with other failures.

That way, haproxy can protect itself even when running on an unpatched
SSL stack. Tests performed with openssl-1.0.1c indicate a total success.
2014-04-25 20:06:33 +02:00
Emeric Brun
29f037d872 MEDIUM: ssl: explicitly log failed handshakes after a heartbeat
Add a callback to receive the heartbeat notification. There, we add
SSL_SOCK_RECV_HEARTBEAT flag on the ssl session if a heartbeat is seen.

If a handshake fails, we log a different message to mention the fact that
a heartbeat was seen. The test is only performed on the frontend side.
2014-04-25 19:25:33 +02:00
William Lallemand
73025dd7e2 MEDIUM: http: register http-request and http-response keywords
The http_(res|req)_keywords_register() functions allow to register
new keywords.

You need to declare a keyword list:

struct http_req_action_kw_list test_kws = {
	.scope = "testscope",
	.kw = {
		{ "test", parse_test },
		{ NULL, NULL },
	}
};

and a parsing function:

int parse_test(const char **args, int *cur_arg, struct proxy *px, struct http_req_rule *rule, char **err)
{
	rule->action = HTTP_REQ_ACT_CUSTOM_STOP;
	rule->action_ptr = action_function;

	return 0;
}

http_req_keywords_register(&test_kws);

The HTTP_REQ_ACT_CUSTOM_STOP action stops evaluation of rules after
your rule, HTTP_REQ_ACT_CUSTOM_CONT permits the evaluation of rules
after your rule.
2014-04-25 18:48:35 +02:00
Baptiste Assmann
fabcbe0de6 MEDIUM: http: ACL and MAP updates through http-(request|response) rules
This patch allows manipulation of ACL and MAP content thanks to any
information available in a session: source IP address, HTTP request or
response header, etc...

It's an update "on the fly" of the content  of the map/acls. This means
it does not resist to reload or restart of HAProxy.
2014-04-25 18:48:35 +02:00
Baptiste Assmann
953f74d1b3 MINOR: pattern: find element in a reference
This function can be used to look for an entry in either an ACL or a
MAP.
2014-04-25 17:31:13 +02:00
Willy Tarreau
c35362a94a MINOR: http: implement the max-keep-alive-queue setting
Finn Arne Gangstad suggested that we should have the ability to break
keep-alive when the target server has reached its maxconn and that a
number of connections are present in the queue. After some discussion
around his proposed patch, the following solution was suggested : have
a per-proxy setting to fix a limit to the number of queued connections
on a server after which we break keep-alive. This ensures that even in
high latency networks where keep-alive is beneficial, we try to find a
different server.

This patch is partially based on his original proposal and implements
this configurable threshold.
2014-04-25 14:14:41 +02:00
Willy Tarreau
6d8bac7ddc BUG/MAJOR: http: fix the 'next' pointer when performing a redirect
Commit bed410e ("MAJOR: http: centralize data forwarding in the request path")
has woken up an issue in redirects, where msg->next is not reset when flushing
the input buffer. The result is an attempt to forward a negative amount of
data, making haproxy crash.

This bug does not seem to affect versions prior to dev23, so no backport is
needed.
2014-04-25 12:21:09 +02:00
Willy Tarreau
1746eecc52 MINOR: checks: add a new global max-spread-checks directive
This directive ensures that checks with a huge interval do not start
too far apart at the beginning.
2014-04-25 10:52:25 +02:00
Willy Tarreau
3c1b5ec29c MINOR: http: add capture.req.ver and capture.res.ver
These ones report a string as "HTTP/1.0" or "HTTP/1.1" depending on the
version of the request message or the response message, respectively.
The purpose is to be able to emit custom log lines reporting this version
in a persistent way.
2014-04-24 23:41:57 +02:00
Willy Tarreau
8b8995f0f4 MINOR: stats: always emit HTTP/1.1 in responses
We used to emit either 1.0 or 1.1 depending on whether we were sending
chunks or not. This condition is useless, better always send 1.1. Also
that way at least clients and intermediary proxies know we speak 1.1.
The "Connection: close" header is still set anyway.
2014-04-24 22:53:43 +02:00
Willy Tarreau
f118d9f507 REORG: http: move HTTP Connection response header parsing earlier
Currently, the parsing of the HTTP Connection header for the response
is performed at the same place as the rule sets, which means that after
parsing the beginning of the response, we still have no information on
whether the response is keep-alive compatible or not. Let's do that
earlier.

Note that this is the same code that was moved in the previous function,
both of them are always called in a row so no change of behaviour is
expected.

A future change might consist in having a late analyser to perform the
late header changes such as mangling the connection header. It's quite
painful that currently this is mixed with the rest of the processing
such as filters.
2014-04-24 22:34:30 +02:00
Willy Tarreau
70730dddbd MEDIUM: http: enable analysers to have keep-alive on stats
This allows the stats page to work in keep-alive mode and to be
compressed. At compression ratios up to 80%, it's quite interesting
for large pages.

We ensure to skip filters because we don't want to unexpectedly block
a response nor to mangle response headers.
2014-04-24 22:32:12 +02:00
Willy Tarreau
ed2119c2fc BUG/MEDIUM: stats: mismatch between behaviour and doc about front/back
In version 1.3.4, we got the ability to split configuration parts between
frontends and backends. The stats was attached to the backend and a control
was made to ensure that it was used only in a listen or backend section, but
not in a frontend.

The documentation clearly says that the statement may only be used in the
backend.

But since that same version above, the defaults stats configuration is
only filled in the frontend part of the proxy and not in the backend's.
So a backend will not get stats which are enabled in a defaults section,
despite what the doc says. However, a frontend configured after a defaults
section will get stats and will not emit the warning!

There were many technical limitations in 1.3.4 making it impossible to
have the stats working both in the frontend and backend, but now this has
become a total mess.

It's common however to see people create a frontend with a perfectly
working stats configuration which only emits a warning stating that it
might not work, adding to the confusion. Most people workaround the tricky
behaviour by declaring a "listen" section with no server, which was the
recommended solution in 1.3 where it was even suggested to add a dispatch
address to avoid a warning.

So the right solution seems to do the following :

  - ensure that the defaults section's settings apply to the backends,
    as documented ;

  - let the frontends work in order not to break existing setups relying
    on the defaults section ;

  - officially allow stats to be declared in frontends and remove the
    warninng

This patch should probably not be backported since it's not certain that
1.4 is fully compatible with having stats in frontends and backends (which
was really made possible thanks to applets).
2014-04-24 22:10:39 +02:00
Willy Tarreau
5897567273 CLEANUP: http: remove the useless "if (1)" inherited from version 1.4
This block has been enclosed inside an "if (1)" statement when migrating
1.3 to 1.4 to avoid a massive reindent. Let's get rid of it now.
2014-04-24 21:26:23 +02:00
Willy Tarreau
f1fd9dc8fb CLEANUP: general: get rid of all old occurrences of "session *t"
All the code inherited from version 1.1 still holds a lot ot sessions
called "t" because in 1.1 they were tasks. This naming is very annoying
and sometimes even confusing, for example in code involving tables.
Let's get rid of this once for all and before 1.5-final.

Nothing changed beyond just carefully renaming these variables.
2014-04-24 21:25:50 +02:00
Willy Tarreau
cce3648e89 BUILD: stats: let gcc know that last_fwd cannot be used uninitialized...
OK, for once it cannot easily know this one, and certain versions are
emitting this harmless warning :

  src/dumpstats.c: In function 'http_stats_io_handler':
  src/dumpstats.c:4507:19: warning: 'last_fwd' may be used uninitialized in this function [-Wmaybe-uninitialized]
2014-04-24 20:26:41 +02:00
Willy Tarreau
628c40cd96 MEDIUM: http: move skipping of 100-continue earlier
It's useless to process 100-continue in the middle of response filters
because there's no info in the 100 response itself, and it could even
make things worse. So better use it as it is, an interim response
waiting for the next response, thus we just have to put it into
http_wait_for_response(). That way we ensure to have a valid response
in this function.
2014-04-24 20:21:56 +02:00
Willy Tarreau
4d1f128a18 BUG/MEDIUM: http: 100-continue responses must process the next part immediately
Since commit d7ad9f5 ("MAJOR: channel: add a new flag CF_WAKE_WRITE to
notify the task of writes"), we got another bug with 100-continue responses.
If the final response comes in the same packet as the 100, then the rest of
the buffer is not processed since there is no wake-up event.

In fact the change above uncoverred the real culprit which is more
likely session.c which should detect that an earlier analyser was set
and should loop back to it.

A cleaner fix would be better, but setting the flag works fine.
This issue was introduced in 1.5-dev22, no backport is needed.
2014-04-24 20:21:56 +02:00
Willy Tarreau
efdf094df2 BUG/MAJOR: http: fix timeouts during data forwarding
Patches c623c17 ("MEDIUM: http: start to centralize the forwarding code")
and bed410e ("MAJOR: http: centralize data forwarding in the request path")
merged into 1.5-dev23 cause transfers to be silently aborted after the
server timeout due to the fact that the analysers are woken up when the
timeout strikes and they believe they have nothing more to do, so they're
terminating the transfer.

No backport is needed.
2014-04-24 20:21:56 +02:00
Willy Tarreau
af3cf70d7c MEDIUM: stats: reimplement HTTP keep-alive on the stats page
This basically reimplements commit f3221f9 ("MEDIUM: stats: add support
for HTTP keep-alive on the stats page") which was reverted by commit
51437d2 after Igor Chan reported a broken stats page caused by the bug
fix by previous commit.
2014-04-24 17:24:56 +02:00
Willy Tarreau
285ff0f25a BUG/MEDIUM: channel: bi_putblk() must not wrap before the end of buffer
The errors reported by Igor Chan on the stats interface in chunked mode
were caused by data wrapping at the wrong place in the buffer. It could
be reliably reproduced by picking random buffer sizes until the issue
appeared (for a given conf, 5300 with 1024 maxrewrite was OK).

The issue is that the stats interface uses bi_putchk() to emit data,
which relies on bi_putblk(). This code checks the largest part that can
be emitted while preserving the rewrite reserve, but uses that result to
compute the wrapping offset, which is wrong. If some data remain present
in the buffer, the wrapping may be allowed and will happen before the
end of the buffer, leaving some old data in the buffer.

The reason it did not happen before keep-alive is simply that the buffer
was much less likely to contain older data. It also used to happen only
for certain configs after a certain amount of time because the size of
the counters used to inflate the output till the point wrapping started
to happen.

The fix is trivial, buffer_contig_space_with_res() simply needs to be
replaced by buffer_contig_space().

Note that peers were using the same function so it is possible that they
were affected as well.

This issue was introduced in 1.5-dev8. No backport to stable is needed.
2014-04-24 17:19:21 +02:00
Willy Tarreau
b2c6a786f7 BUG/MINOR: http: don't report server aborts as client aborts
Commit f003d37 ("BUG/MINOR: http: don't report client aborts as server errors")
attempted to fix a longstanding issue by which some client aborts could be
logged as server errors. Unfortunately, one of the tests involved there also
catches truncated server responses, which are reported as client aborts.

Instead, only check that the client has really closed using the abortonclose
option, just as in done in the request path (which means that the close was
propagated to the server).

The faulty fix above was introduced in 1.5-dev15, and was backported into
1.4.23.

Thanks to Patrick Hemmer for reporting this issue with traces showing the
root cause of the problem.
2014-04-23 20:29:01 +02:00
Willy Tarreau
3ca5448828 BUG/MINOR: compression: correctly report incoming byte count
The fixes merged into 1.5-dev23 on compression resulted in the input
byte count not being correctly computed and always reported as zero.
2014-04-23 19:31:17 +02:00
Willy Tarreau
ee445d99ff MEDIUM: config: report misplaced use-server rules
Till now there was no check against misplaced use-server rules, and
no warning was emitted, adding to the confusion. They're processed
just after the use_backend rules, or more exactly at the same level
but for the backend.
2014-04-23 01:39:04 +02:00
Willy Tarreau
5002f57186 MEDIUM: config: report misplaced http-request rules
Recently, the http-request ruleset started to be used a lot and some
bug reports were caused by misplaced http-request rules because there
was no warning if they're after a redirect or use_backend rule. Let's
fix this now. http-request rules are just after the block rules.
2014-04-23 01:32:02 +02:00
Willy Tarreau
f51658dac4 MEDIUM: config: relax use_backend check to make the condition optional
Since it became possible to use log-format expressions in use_backend,
having a mandatory condition becomes annoying because configurations
are full of "if TRUE". Let's relax the check to accept no condition
like many other keywords (eg: redirect).
2014-04-23 01:21:56 +02:00
Willy Tarreau
b9a551e6aa BUG/MINOR: stats: last session was not always set
Cyril Bonté reported that the "lastsess" field of a stats-only backend
was never updated. In fact the same is true for any applet and anything
not a server. Also, lastsess was not updated for a server reusing its
connection for a new request.

Since the goal of this field is to report recent activity, it's better
to ensure that all accesses are reported. The call has been moved to
the code validating the session establishment instead, since everything
passes there.
2014-04-23 00:35:17 +02:00
Willy Tarreau
38b3aa5646 BUG/MAJOR: http: fix bug in parse_qvalue() when selecting compression algo
Commit ad90351 ("MINOR: http: Add the "language" converter to for use with accept-language")
introduced a typo in parse_qvalue :

	if (*end)
		*end = qvalue;

while it should be :

	if (end)
		*end = qvalue;

Since end is tested for being NULL. This crashes when selecting the
compression algorithm since end is NULL here. No backport is needed,
this is just in latest 1.5-dev.
2014-04-22 23:32:05 +02:00
Willy Tarreau
3ce10ff9f0 CLEANUP: http: remove all calls to http_silent_debug()
This macro has long remained unused and calls are unevenly spread over
the code, so it's totally useless and pollutes the code. Remove it now.
2014-04-22 23:15:29 +02:00
Willy Tarreau
d351021860 CLEANUP: http: document the response forwarding states
The forwarding code is never obvious to enter into for newcomers, so
better improve the documentation about how states are chained and what
happens for each of them.
2014-04-22 23:15:29 +02:00
Willy Tarreau
bed410e0e8 MAJOR: http: centralize data forwarding in the request path
It is the same principle as what was just done for the response.
It makes the code cleaner, faster, and more maintainable.
2014-04-22 23:15:29 +02:00
Willy Tarreau
32b5ab2a28 MEDIUM: http: only allocate the temporary compression buffer when needed
Since we know when the buffer is needed, only check for its allocation
at the same place in order to avoid useless tests on the normal path.
2014-04-22 23:15:29 +02:00
Willy Tarreau
d5a6783ac9 MINOR: http: further cleanups of response forwarding function
There is no reason for mixing compressing and non-compressing
code in the DATA state, they don't share anything. Better make
this clearer.
2014-04-22 23:15:28 +02:00
Willy Tarreau
c623c17b13 MEDIUM: http: start to centralize the forwarding code
Doing so avoids calling channel_forward() for each part of the chunk
parsing and lowers the number of calls to channel_forward() to only
one per buffer, resulting in about 11% performance increase on small
chunks forwarding rate.
2014-04-22 23:15:28 +02:00
Willy Tarreau
168ebc5e2b MEDIUM: http: cleanup: centralize a little bit HTTP compression end
The call to flush the compression buffers only needs to be done when
entering the final states or when leaving with missing data. After
that, if trailers are present, they have to be forwarded.
2014-04-22 23:15:28 +02:00
Willy Tarreau
7f2f8d5cc3 MAJOR: http/compression: fix chunked-encoded response processing
Now we have valid buffer offsets, we can use them to safely parse the
input and only forward when needed. Thus we can get rid of the
consumed_data accumulator, and the code now works both for chunked and
content-length, even with a server feeding one byte at a time (which
systematically broke the previous one).

It's worth noting that 0<CRLF> must always be sent after end of data
(ie: chunk_len==0), and that the trailing CRLF is sent only content
length mode, because in chunked we'll have to pass trailers.
2014-04-22 23:15:28 +02:00
Willy Tarreau
5fb0abd9a1 MAJOR: http: re-enable compression on chunked encoding
This is basically a revert of commit 667c2a3 ("BUG/MAJOR: http: compression
still has defects on chunked responses").

The latest changes applied to message pointers should have got rid of all
the issues that were making the compression of partial chunks unreliable.
2014-04-22 23:15:28 +02:00
Willy Tarreau
b59c7bfc95 MEDIUM: http: headers must be forwarded even if data was already inspected
Currently, we forward headers only if the incoming message is still before
HTTP_MSG_CHUNK_SIZE, otherwise they'll be considered as data. In practice
this is always true for the response since there's no data inspection, and
for the request there is no compression so there's no problem with forwarding
them as data.

But the principle is incorrect and will make it difficult to later add data
processing features. So better fix it now.

The new principle is simple :
  - if headers were not yet forwarded, forward them now.
  - while doing so, check if we need to update the state
2014-04-22 23:15:28 +02:00
Willy Tarreau
6fef8ae047 BUG/MINOR: http: deinitialize compression after a compression error
If for some reason, the compression returns an error, the compression
is not deinitialized which also means that any pending data are not
flushed and could be lost, especially in the chunked-encoded case.
No backport is needed.
2014-04-22 23:15:28 +02:00
Willy Tarreau
d01f426e62 BUG/MINOR: http: deinitialize compression after a parsing error
When a parsing error was encountered in a chunked response, we failed
to properly deinitialize the compression context. There was no impact
till now since compression of chunked responses was disabled. No backport
is needed.
2014-04-22 23:15:28 +02:00
Willy Tarreau
7ba235466d MEDIUM: http: forward headers again while waiting for connection to complete
Thanks to the last updates on the message pointers, it is now safe again to
enable forwarding of the request headers while waiting for the connection to
complete because we know how to safely rewind this part.

So this patch slightly modifies what was done in commit 80a92c0 ("BUG/MEDIUM:
http: don't start to forward request data before the connect") to let up to
msg->sov bytes be forwarded when waiting for the connection. The resulting
effect is that a POST request may now be sent with the connect's ACK, which
still saves a packet and may even be useful later when TFO is supported.
2014-04-22 23:15:28 +02:00
Willy Tarreau
1234f4a210 MAJOR: http: reset msg->sov after headers are forwarded
In order to avoid abusively relying on buf->o to guess how many bytes to
rewind during a redispatch, we now clear msg->sov. Thus the meaning of this
field is exactly "how many bytes of headers are left to be forwarded". It
is still possible to rewind because msg->eoh + msg->eol equal that value
before scheduling the forwarding, so we can always subtract them.
2014-04-22 23:15:28 +02:00
Willy Tarreau
0d09050aa5 MEDIUM: http: small helpers to compute how far to rewind to find BODY and DATA
http_body_rewind() returns the number of bytes to rewind before buf->p to
find the message's body. It relies on http_hdr_rewind() to find the beginning
and adds msg->eoh + msg->eol which are always safe.

http_data_rewind() does the same to get the beginning of the data, which
differs from above when a chunk is present. It uses the function above and
adds msg->sol.

The purpose is to centralize further ->sov changes aiming at avoiding
to rely on buf->o.
2014-04-22 23:15:28 +02:00