1383 Commits

Author SHA1 Message Date
William Lallemand
b2f07451e5 MEDIUM: cfgparse: expand environment variables
Environment variables were expandables only in adresses.
Now there are expandables everywhere in the configuration file within
double quotes.

This patch breaks compatibility with the previous behavior of
environment variables in adresses, you must enclose adresses with double
quotes to make it work.
2015-05-12 15:28:20 +02:00
William Lallemand
64e84516c4 MINOR: cfgparse: remove line size limitation
Remove the line size limitation of the configuration parser.  The buffer
is now allocated dynamically and grows when the line is too long.
2015-05-12 15:28:07 +02:00
William Lallemand
3f41560f61 BUG/MEDIUM: cfgparse: incorrect memmove in quotes management
The size of the memmove was incorrect (one byte too far) in the quotes
parser and can lead to segfault during configuration parsing.
2015-05-12 15:27:45 +02:00
Baptiste Assmann
22b09d2393 MINOR: include comment in tcpcheck error log
tcpcheck error messages include the step id where the error occurs.
In some cases, this is not enough. Now, HAProxy also use the comment
field of the latest tcpcheck rule which has been run.
This commit allows HAProxy to parse a new directive in the tcpcheck
ruleset: 'comment'.
It is used to setup comments on the current tcpcheck rules.
2015-05-12 11:04:39 +02:00
William Lallemand
f9873ba63a MEDIUM: cfgparse: introduce weak and strong quoting
This patch introduces quoting which allows to write configuration string
including spaces without escaping them.

Strong (with single quotes) and weak (with double quotes) quoting are
supported. Weak quoting supports escaping and special characters when
strong quoting does not interpret anything.

This patch could break configuration files where ' and " where used.
2015-05-05 21:05:44 +02:00
Willy Tarreau
e428b08ee7 BUG/MEDIUM: config: properly compute the default number of processes for a proxy
Chad Lavoie reported an interesting regression caused by the latest
updates to automatically detect the processes a peers section runs on.
It turns out that if a config has neither nbproc nor a bind-process
statement and depending on the frontend->backend chaining, it is possible
to evade all bind_proc propagations, resulting in assigning only ~0UL (all
processes, which is 32 or 64) without ever restricting it to nbproc. It
was not visible in backends until they started to reference peers sections
which saw themselves with 64 processes at once.

This patch addresses this by replacing all those ~0UL with nbits(nbproc).
That way all "bind-process" settings *default* to the number of processes
defined in nbproc instead of 32 or 64.

This fix could possibly be backported into 1.5, though there is no indication
that this bug could have any effect there.
2015-05-04 21:57:58 +02:00
Willy Tarreau
64c5722e05 MINOR: config: report the number of processes using a peers section in the error case
It can be helpful to know how many different processes try to use the
same peers section when trying to find the culprits.
2015-05-04 21:48:51 +02:00
Willy Tarreau
0334ffc65d CLEANUP: config: fix misleading information in error message.
The parameter name is "bind-process", not "bind_proc" which is the
internal variable name.
2015-05-04 21:46:08 +02:00
Willy Tarreau
9fbe18e174 MEDIUM: http: add a new option http-buffer-request
It is sometimes desirable to wait for the body of an HTTP request before
taking a decision. This is what is being done by "balance url_param" for
example. The first use case is to buffer requests from slow clients before
connecting to the server. Another use case consists in taking the routing
decision based on the request body's contents. This option placed in a
frontend or backend forces the HTTP processing to wait until either the whole
body is received, or the request buffer is full, or the first chunk is
complete in case of chunked encoding. It can have undesired side effects with
some applications abusing HTTP by expecting unbufferred transmissions between
the frontend and the backend, so this should definitely not be used by
default.

Note that it would not work for the response because we don't reset the
message state before starting to forward. For the response we need to
1) reset the message state to MSG_100_SENT or BODY , and 2) to reset
body_len in case of chunked encoding to avoid counting it twice.
2015-05-02 00:10:44 +02:00
Willy Tarreau
bf59807a13 MAJOR: peers: allow peers section to be used with nbproc > 1
This only works when the peers are bound to exactly one process.
2015-05-01 20:16:31 +02:00
Willy Tarreau
1e27301866 MEDIUM: config: validate that peers sections are bound to exactly one process
If a peers section is bound to no process, it's silently discarded. If its
bound to multiple processes, an error is emitted and the process will not
start.
2015-05-01 20:16:31 +02:00
Willy Tarreau
0fca4835b2 MEDIUM: config: propagate the table's process list to the peers sections
Now a peers section has its bind_proc set to the union of all those of
its users.
2015-05-01 20:16:31 +02:00
Willy Tarreau
77e4bd1497 MEDIUM: peers: add the ability to disable a peers section
Sometimes it's very hard to disable the use of peers because an empty
section is not valid, so it is necessary to comment out all references
to the section, and not to forget to restore them in the same state
after the operation.

Let's add a "disabled" keyword just like for proxies. A ->state member
in the peers struct is even present for this purpose but was never used
at all.

Maybe it would make sense to backport this to 1.5 as it's really cumbersome
there.
2015-05-01 20:16:31 +02:00
Willy Tarreau
6866f3f33f MEDIUM: config: initialize stick-tables after peers, not before
It's dangerous to initialize stick-tables before peers because they
start a task that cannot be stopped before we know if the peers need
to be disabled and destroyed. Move this after.
2015-05-01 20:16:31 +02:00
Willy Tarreau
02df7740fb BUG/MINOR: config: clear proxy->table.peers.p for disabled proxies
If a table in a disabled proxy references a peers section, the peers
name is not resolved to a pointer to a table, but since it belongs to
a union, it can later be dereferenced. Right now it seems it cannot
happen, but it definitely will after the pending changes.

It doesn't cost anything to backport this into 1.5, it will make gdb
sessions less head-scratching.
2015-05-01 20:05:25 +02:00
Willy Tarreau
0f228a037a MEDIUM: http: add option-ignore-probes to get rid of the floods of 408
Recently some browsers started to implement a "pre-connect" feature
consisting in speculatively connecting to some recently visited web sites
just in case the user would like to visit them. This results in many
connections being established to web sites, which end up in 408 Request
Timeout if the timeout strikes first, or 400 Bad Request when the browser
decides to close them first. These ones pollute the log and feed the error
counters. There was already "option dontlognull" but it's insufficient in
this case. Instead, this option does the following things :
   - prevent any 400/408 message from being sent to the client if nothing
     was received over a connection before it was closed ;
   - prevent any log from being emitted in this situation ;
   - prevent any error counter from being incremented

That way the empty connection is silently ignored. Note that it is better
not to use this unless it is clear that it is needed, because it will hide
real problems. The most common reason for not receiving a request and seeing
a 408 is due to an MTU inconsistency between the client and an intermediary
element such as a VPN, which blocks too large packets. These issues are
generally seen with POST requests as well as GET with large cookies. The logs
are often the only way to detect them.

This patch should be backported to 1.5 since it avoids false alerts and
makes it easier to monitor haproxy's status.
2015-05-01 15:39:23 +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
9903f0e1a2 REORG: session: move the session parts out of stream.c
This concerns everythins related to accepting a new session and
expiring the embryonic session. There's still a hard-coded call
to stream_accept_session() which could be set somewhere in the
frontend, but for now it's not a problem.
2015-04-06 11:37:32 +02:00
Willy Tarreau
87b09668be REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.

In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.

The files stream.{c,h} were added and session.{c,h} removed.

The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.

Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.

Once all changes are completed, we should see approximately this :

   L7 - http_txn
   L6 - stream
   L5 - session
   L4 - connection | applet

There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.

Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-06 11:23:56 +02:00
Willy Tarreau
10b688f2b4 MEDIUM: listener: store the default target per listener
This will be useful later to state that some listeners have to use
certain decoders (typically an HTTP/2 decoder) regardless of the
regular processing applied to other listeners. For now it simply
defaults to the frontend's default target, and it is used by the
session.
2015-03-13 16:45:37 +01:00
Willy Tarreau
512fd00296 CLEANUP: listeners: remove unused timeout
Listerner->timeout is a vestigal thing going back to 2007 or so. It
used to only be used by stats and peers frontends to hold a pointer
to the proxy's client timeout. Now that we use regular frontends, we
don't use it anymore.
2015-03-13 16:25:15 +01:00
Willy Tarreau
91d9628a51 MINOR: peers: centralize configuration of the peers frontend
This is in order to stop exporting the peer_accept() function.
2015-03-13 16:23:00 +01:00
Willy Tarreau
9ff95bb18c BUG/MEDIUM: peers: correctly configure the client timeout
The peers frontend timeout was mistakenly set on timeout.connect instead
of timeout.client, resulting in no timeout being applied to the peers
connections. The impact is just that peers can establish connections and
remain connected until they speak. Once they start speaking, only one of
them will still be accepted, and old sessions will be killed, so the
problem is limited. This fix should however be backported to 1.5 since
it was introduced in 1.5-dev3 with peers.
2015-03-13 16:21:28 +01:00
Willy Tarreau
e7acee70a3 BUILD/CLEANUP: config: silent 3 warnings about mixed declarations with code
These ones were present in the tcp-check parser.
2015-02-28 23:12:30 +01:00
Nenad Merdanovic
05552d4b98 MEDIUM: Add support for configurable TLS ticket keys
Until now, the TLS ticket keys couldn't have been configured and
shared between multiple instances or multiple servers running HAproxy.
The result was that if a request got a TLS ticket from one instance/server
and it hits another one afterwards, it will have to go through the full
SSL handshake and negotation.

This patch enables adding a ticket file to the bind line, which will be
used for all SSL contexts created from that bind line. We can use the
same file on all instances or servers to mitigate this issue and have
consistent TLS tickets assigned. Clients will no longer have to negotiate
every time they change the handling process.

Signed-off-by: Nenad Merdanovic <nmerdan@anine.io>
2015-02-28 23:10:22 +01:00
Simon Horman
64e3416662 MEDIUM: Allow suppression of email alerts by log level
This patch adds a new option which allows configuration of the maximum
log level of messages for which email alerts will be sent.

The default is alert which is more restrictive than
the current code which sends email alerts for all priorities.
That behaviour may be configured using the new configuration
option to set the maximum level to notice or greater.

	email-alert level notice

Signed-off-by: Simon Horman <horms@verge.net.au>
2015-02-06 07:59:58 +01:00
Simon Horman
0ba0e4ac07 MEDIUM: Support sending email alerts
Signed-off-by: Simon Horman <horms@verge.net.au>
2015-02-03 00:24:16 +01:00
Simon Horman
9dc4996344 MEDIUM: Allow configuration of email alerts
This currently does nothing beyond parsing the configuration
and storing in the proxy as there is no implementation of email alerts.

Signed-off-by: Simon Horman <horms@verge.net.au>
2015-02-03 00:24:16 +01:00
Simon Horman
0d16a4011e MEDIUM: Add parsing of mailers section
As mailer and mailers structures and allow parsing of
a mailers section into those structures.

These structures will subsequently be freed as it is
not yet possible to use reference them in the configuration.

Signed-off-by: Simon Horman <horms@verge.net.au>
2015-02-03 00:24:16 +01:00
Simon Horman
1a23cf0dfb BUG/MEDIUM: Do not set agent health to zero if server is disabled in config
disable starts a server in the disabled state, however setting the health
of an agent implies that the agent is disabled as well as the server.

This is a problem because the state of the agent is not restored if
the state of the server is subsequently updated leading to an
unexpected state.

For example, if a server is started disabled and then the server
state is set to ready then without this change show stat indicates
that the server is "DOWN (agent)" when it is expected that the server
would be UP if its (non-agent) health check passes.

Reported-by: Mark Brooks <mark@loadbalancer.org>
Signed-off-by: Simon Horman <horms@verge.net.au>
2015-01-23 16:47:41 +01:00
Willy Tarreau
324f07f6dd MEDIUM: backend: add the crc32 hash algorithm for load balancing
Since we have it available, let's make it usable for load balancing,
it comes at no cost except 3 lines of documentation.
2015-01-20 19:48:14 +01:00
Willy Tarreau
094af4e16e MINOR: logs: add a new per-proxy "log-tag" directive
This is equivalent to what was done in commit 48936af ("[MINOR] log:
ability to override the syslog tag") but this time instead of doing
this globally, it does it per proxy. The purpose is to be able to use
a separate log tag for various proxies (eg: make it easier to route
log messages depending on the customer).
2015-01-07 15:03:42 +01:00
Willy Tarreau
33cb065348 MINOR: config: implement global setting tune.buffers.limit
This setting is used to limit memory usage without causing the alloc
failures caused by "-m". Unexpectedly, tests have shown a performance
boost of up to about 18% on HTTP traffic when limiting the number of
buffers to about 10% of the amount of concurrent connections.

tune.buffers.limit <number>
  Sets a hard limit on the number of buffers which may be allocated per process.
  The default value is zero which means unlimited. The minimum non-zero value
  will always be greater than "tune.buffers.reserve" and should ideally always
  be about twice as large. Forcing this value can be particularly useful to
  limit the amount of memory a process may take, while retaining a sane
  behaviour. When this limit is reached, sessions which need a buffer wait for
  another one to be released by another session. Since buffers are dynamically
  allocated and released, the waiting time is very short and not perceptible
  provided that limits remain reasonable. In fact sometimes reducing the limit
  may even increase performance by increasing the CPU cache's efficiency. Tests
  have shown good results on average HTTP traffic with a limit to 1/10 of the
  expected global maxconn setting, which also significantly reduces memory
  usage. The memory savings come from the fact that a number of connections
  will not allocate 2*tune.bufsize. It is best not to touch this value unless
  advised to do so by an haproxy core developer.
2014-12-24 23:47:33 +01:00
Willy Tarreau
1058ae73f1 MINOR: config: implement global setting tune.buffers.reserve
Used in conjunction with the dynamic buffer allocator.

tune.buffers.reserve <number>
  Sets the number of buffers which are pre-allocated and reserved for use only
  during memory shortage conditions resulting in failed memory allocations. The
  minimum value is 2 and is also the default. There is no reason a user would
  want to change this value, it's mostly aimed at haproxy core developers.
2014-12-24 23:47:33 +01:00
Willy Tarreau
f6b7001338 BUG/MEDIUM: config: do not propagate processes between stopped processes
Immo Goltz reported a case of segfault while parsing the config where
we try to propagate processes across stopped frontends (those with a
"disabled" statement). The fix is trivial. The workaround consists in
commenting out these frontends, although not always easy.

This fix must be backported to 1.5.
2014-12-18 14:03:31 +01:00
Willy Tarreau
8a95d8cd61 BUG/MINOR: config: fix typo in condition when propagating process binding
propagate_processes() has a typo in a condition :

	if (!from->cap & PR_CAP_FE)
		return;

The return is never taken because each proxy has at least one capability
so !from->cap always evaluates to zero. Most of the time the caller already
checks that <from> is a frontend. In the cases where it's not tested
(use_backend, reqsetbe), the rules have been checked for the context to
be a frontend as well, so in the end it had no nasty side effect.

This should be backported to 1.5.
2014-12-18 14:03:31 +01:00
Godbach
d972203fbc BUG/MINOR: parse: refer curproxy instead of proxy
Since during parsing stage, curproxy always represents a proxy to be operated,
it should be a mistake by referring proxy.

Signed-off-by: Godbach <nylzhaowei@gmail.com>
2014-12-18 11:01:51 +01:00
KOVACS Krisztian
b3e54fe387 MAJOR: namespace: add Linux network namespace support
This patch makes it possible to create binds and servers in separate
namespaces.  This can be used to proxy between multiple completely independent
virtual networks (with possibly overlapping IP addresses) and a
non-namespace-aware proxy implementation that supports the proxy protocol (v2).

The setup is something like this:

net1 on VLAN 1 (namespace 1) -\
net2 on VLAN 2 (namespace 2) -- haproxy ==== proxy (namespace 0)
net3 on VLAN 3 (namespace 3) -/

The proxy is configured to make server connections through haproxy and sending
the expected source/target addresses to haproxy using the proxy protocol.

The network namespace setup on the haproxy node is something like this:

= 8< =
$ cat setup.sh
ip netns add 1
ip link add link eth1 type vlan id 1
ip link set eth1.1 netns 1
ip netns exec 1 ip addr add 192.168.91.2/24 dev eth1.1
ip netns exec 1 ip link set eth1.$id up
...
= 8< =

= 8< =
$ cat haproxy.cfg
frontend clients
  bind 127.0.0.1:50022 namespace 1 transparent
  default_backend scb

backend server
  mode tcp
  server server1 192.168.122.4:2222 namespace 2 send-proxy-v2
= 8< =

A bind line creates the listener in the specified namespace, and connections
originating from that listener also have their network namespace set to
that of the listener.

A server line either forces the connection to be made in a specified
namespace or may use the namespace from the client-side connection if that
was set.

For more documentation please read the documentation included in the patch
itself.

Signed-off-by: KOVACS Tamas <ktamas@balabit.com>
Signed-off-by: Sarkozi Laszlo <laszlo.sarkozi@balabit.com>
Signed-off-by: KOVACS Krisztian <hidden@balabit.com>
2014-11-21 07:51:57 +01:00
Willy Tarreau
743c128580 BUG/MINOR: config: don't inherit the default balance algorithm in frontends
Tom Limoncelli from Stack Exchange reported a minor bug : the frontend
inherits the LB parameters from the defaults sections. The impact is
that if a "balance" directive uses any L7 parameter in the defaults
sections and the frontend is in TCP mode, a warning is emitted about
their incompatibility. The warning is harmless but a valid, sane config
should never cause any warning to be reported.

This fix should be backported into 1.5 and possibly 1.4.
2014-11-18 15:04:29 +01:00
Willy Tarreau
06cc905813 BUG/MEDIUM: config: avoid skipping disabled proxies
Paul Taylor and Bryan Talbot found that after commit 419ead8 ("MEDIUM:
config: compute the exact bind-process before listener's maxaccept"),
a backend marked "disabled" would cause the next backend to be skipped
and if it was the last one it would cause a segfault.

The reason is that the commit above changed the "while" loop for a "for"
loop but a "continue" statement still incrementing the current proxy was
left in the code for disabled proxies, causing the next one to be skipped
as well and the last one to try to dereference NULL when seeking ->next.

The quick workaround consists in not disabling backends, or adding an
empty dummy one after a disabled section.

This fix must be backported to 1.5.
2014-10-10 14:58:52 +02:00
Cyril Bonté
51639696e0 BUG/MINOR: config: don't propagate process binding for dynamic use_backend
A segfault was reported with the introduction of the propagate_processes()
function. It was caused when a use_backend rule was declared with a dynamic
name, using a log-format string. The backend is not resolved during the
configuration, which lead to the segfault.

The patch prevents the process binding propagation for such dynamic rules, it
should also be backported to 1.5.
2014-10-02 21:17:11 +02:00
Willy Tarreau
acbe8ab38a BUG/MINOR: config: don't propagate process binding on fatal errors.
propagate_processes() must not be called with unresolved proxies, but
nothing prevents it from being called in check_config_validity(). The
resulting effect is that an unresolved proxy can cause a recursion
loop if called in such a situation, ending with a segfault after the
fatal error report. There's no side effect beyond this.

This patch refrains from calling the function when any error was met.

This bug also affects 1.5, it should be backported.
2014-10-01 20:50:17 +02:00
Willy Tarreau
e42bd96d0a MINOR: config: detect the case where a tcp-request content rule has no inspect-delay
If a frontend has any tcp-request content rule relying on request contents
without any inspect delay, we now emit a warning as this will randomly match.

This can be backported to 1.5 as it reduces the support effort.
2014-09-16 17:00:05 +02:00
Willy Tarreau
3986b9c140 MEDIUM: config: report it when tcp-request rules are misplaced
A config where a tcp-request rule appears after an http-request rule
might seem valid but it is not. So let's report a warning about this
since this case is hard to detect by the naked eye.
2014-09-16 15:43:24 +02:00
Willy Tarreau
eb791e03b5 MEDIUM: config: only warn if stats are attached to multi-process bind directives
Some users want to have a stats frontend with one line per process, but while
100% valid and safe, the config parser emits a warning. Relax this check to
ensure that the warning is only emitted if at least one of the listeners is
bound to multiple processes, or if the directive is placed in a backend called
from multiple processes (since in this case we don't know if it's safe).
2014-09-16 15:43:24 +02:00
Willy Tarreau
419ead8eca MEDIUM: config: compute the exact bind-process before listener's maxaccept
This is a continuation of previous patch, the listener's maxaccept is divided
by the number of processes, so it's best if we can swap the two blocks so that
the number of processes is already known when computing the maxaccept value.
2014-09-16 15:43:24 +02:00
Willy Tarreau
b369a045d5 MEDIUM: config: make the frontends automatically bind to the listeners' processes
When a frontend does not have any bind-process directive, make it
automatically bind to the union of all of its listeners' processes
instead of binding to all processes. That will make it possible to
have the expected behaviour without having to explicitly specify a
bind-process directive.

Note that if the listeners are not bound to a specific process, the
default is still to bind to all processes.

This change could be backported to 1.5 as it simplifies process
management, and was planned to be done during the 1.5 development phase.
2014-09-16 15:43:24 +02:00
Willy Tarreau
64ab6077b7 MEDIUM: config: properly propagate process binding between proxies
We now recursively propagate the bind-process values between frontends
and backends instead of doing it during name resolving. This ensures
that we're able to properly propagate all the bind-process directives
even across "listen" instances, which are not perfectly covered at the
moment, depending on the declaration order.
2014-09-16 12:17:36 +02:00
Willy Tarreau
8a3478ed31 BUG/MEDIUM: config: propagate frontend to backend process binding again.
This basically reverts 3507d5d ("MEDIUM: proxy: only adjust the backend's
bind-process when already set"). It was needed during the transition to
the new process binding method but is causing trouble now because frontend
to backend binding is not properly propagated.

This fix should be backported to 1.5.
2014-09-16 12:14:49 +02:00
Cyril Bonté
1a0191d2ff BUG/MEDIUM: config: userlists should ensure that encrypted passwords are supported
When an unknown encryption algorithm is used in userlists or the password is
not pasted correctly in the configuration, http authentication silently fails.

An initial check is now performed during the configuration parsing, in order to
verify that the encrypted password is supported. An unsupported password will
fail with a fatal error.

This patch should be backported to 1.4 and 1.5.
2014-08-29 21:06:31 +02:00