mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 15:17:01 +02:00
* released 1.2.6
* clean-up patch from Alexander Lazic fixes build on Debian 3.1 (socklen_t).
This commit is contained in:
parent
0fe396592d
commit
c5f73ed21c
@ -1,7 +1,10 @@
|
||||
ChangeLog :
|
||||
===========
|
||||
|
||||
2005/07/06 : 1.2.6 (1.1.32)
|
||||
2005/08/07 : 1.2.6
|
||||
- clean-up patch from Alexander Lazic fixes build on Debian 3.1 (socklen_t).
|
||||
|
||||
2005/07/06 : 1.2.6-pre5 (1.1.32)
|
||||
- added the number of active sessions (proxy/process) in the logs
|
||||
|
||||
2005/07/06 : 1.2.6-pre4 (1.1.32-pre4)
|
||||
|
@ -2,9 +2,9 @@
|
||||
H A - P r o x y
|
||||
Architecture Guide
|
||||
-------------------
|
||||
version 1.1.30
|
||||
version 1.1.32
|
||||
willy tarreau
|
||||
2004/11/28
|
||||
2005/07/17
|
||||
|
||||
|
||||
This document provides real world examples with working configurations.
|
||||
@ -50,7 +50,7 @@ load across the new boxes.
|
||||
Config on haproxy (LB1) :
|
||||
-------------------------
|
||||
|
||||
listen 192.168.1.1:80
|
||||
listen webfarm 192.168.1.1:80
|
||||
mode http
|
||||
balance roundrobin
|
||||
cookie SERVERID insert indirect
|
||||
@ -143,7 +143,7 @@ Now you don't want to add more cookies, but rather use existing ones. The
|
||||
application already generates a "JSESSIONID" cookie which is enough to track
|
||||
sessions, so we'll prefix this cookie with the server name when we see it.
|
||||
Since the load-balancer becomes critical, it will be backed up with a second
|
||||
one in VRRP mode using keepalived.
|
||||
one in VRRP mode using keepalived under Linux.
|
||||
|
||||
Download the latest version of keepalived from this site and install it
|
||||
on each load-balancer LB1 and LB2 :
|
||||
@ -152,7 +152,7 @@ on each load-balancer LB1 and LB2 :
|
||||
|
||||
You then have a shared IP between the two load-balancers (we will still use the
|
||||
original IP). It is active only on one of them at any moment. To allow the
|
||||
proxy to bind to the shared IP, you must enable it in /proc :
|
||||
proxy to bind to the shared IP on Linux 2.4, you must enable it in /proc :
|
||||
|
||||
# echo 1 >/proc/sys/net/ipv4/ip_nonlocal_bind
|
||||
|
||||
@ -171,7 +171,7 @@ proxy to bind to the shared IP, you must enable it in /proc :
|
||||
Config on both proxies (LB1 and LB2) :
|
||||
--------------------------------------
|
||||
|
||||
listen 192.168.1.1:80
|
||||
listen webfarm 192.168.1.1:80
|
||||
mode http
|
||||
balance roundrobin
|
||||
cookie JSESSIONID prefix
|
||||
@ -188,7 +188,8 @@ Notes: the proxy will modify EVERY cookie sent by the client and the server,
|
||||
so it is important that it can access to ALL cookies in ALL requests for
|
||||
each session. This implies that there is no keep-alive (HTTP/1.1), thus the
|
||||
"httpclose" option. Only if you know for sure that the client(s) will never
|
||||
use keep-alive, you can remove this option.
|
||||
use keep-alive (eg: Apache 1.3 in reverse-proxy mode), you can remove this
|
||||
option.
|
||||
|
||||
|
||||
Description :
|
||||
@ -266,7 +267,7 @@ which will also check that the services run fine on both proxies :
|
||||
Config on both proxies (LB1 and LB2) :
|
||||
--------------------------------------
|
||||
|
||||
listen 0.0.0.0:80
|
||||
listen webfarm 0.0.0.0:80
|
||||
mode http
|
||||
balance roundrobin
|
||||
cookie JSESSIONID prefix
|
||||
@ -308,6 +309,89 @@ Config on the Alteon :
|
||||
group 10
|
||||
|
||||
|
||||
Note: the health-check on the Alteon is set to "tcp" to prevent the proxy from
|
||||
forwarding the connections. It can also be set to "http", but for this the
|
||||
proxy must specify a "monitor-net" with the Alteons' addresses, so that the
|
||||
Alteon can really check that the proxies can talk HTTP but without forwarding
|
||||
the connections to the end servers. Check next section for an example on how to
|
||||
use monitor-net.
|
||||
|
||||
|
||||
============================================================
|
||||
2.2 Generic TCP relaying and external layer 4 load-balancers
|
||||
============================================================
|
||||
|
||||
Sometimes it's useful to be able to relay generic TCP protocols (SMTP, TSE,
|
||||
VNC, etc...), for example to interconnect private networks. The problem comes
|
||||
when you use external load-balancers which need to send periodic health-checks
|
||||
to the proxies, because these health-checks get forwarded to the end servers.
|
||||
The solution is to specify a network which will be dedicated to monitoring
|
||||
systems and must not lead to a forwarding connection nor to any log, using the
|
||||
"monitor-net" keyword. Note: this feature expects a version of haproxy greater
|
||||
than or equal to 1.1.32 or 1.2.6.
|
||||
|
||||
|
||||
| VIP=172.16.1.1 |
|
||||
+----+----+ +----+----+
|
||||
| Alteon1 | | Alteon2 |
|
||||
+----+----+ +----+----+
|
||||
192.168.1.252 | GW=192.168.1.254 | 192.168.1.253
|
||||
| |
|
||||
------+---+------------+--+-----------------> TSE farm : 192.168.1.10
|
||||
192.168.1.1 | | 192.168.1.2
|
||||
+--+--+ +--+--+
|
||||
| LB1 | | LB2 |
|
||||
+-----+ +-----+
|
||||
haproxy haproxy
|
||||
|
||||
|
||||
Config on both proxies (LB1 and LB2) :
|
||||
--------------------------------------
|
||||
|
||||
listen tse-proxy
|
||||
bind :3389,:1494,:5900 # TSE, ICA and VNC at once.
|
||||
mode tcp
|
||||
balance roundrobin
|
||||
server tse-farm 192.168.1.10
|
||||
monitor-net 192.168.1.252/31
|
||||
|
||||
The "monitor-net" option instructs the proxies that any connection coming from
|
||||
192.168.1.252 or 192.168.1.253 will not be logged nor forwarded and will be
|
||||
closed immediately. The Alteon load-balancers will then see the proxies alive
|
||||
without perturbating the service.
|
||||
|
||||
Config on the Alteon :
|
||||
----------------------
|
||||
|
||||
/c/l3/if 1
|
||||
ena
|
||||
addr 192.168.1.252
|
||||
mask 255.255.255.0
|
||||
/c/slb/real 11
|
||||
ena
|
||||
name "LB1"
|
||||
rip 192.168.1.1
|
||||
/c/slb/real 12
|
||||
ena
|
||||
name "LB2"
|
||||
rip 192.168.1.2
|
||||
/c/slb/group 10
|
||||
name "LB1-2"
|
||||
metric roundrobin
|
||||
health tcp
|
||||
add 11
|
||||
add 12
|
||||
/c/slb/virt 10
|
||||
ena
|
||||
vip 172.16.1.1
|
||||
/c/slb/virt 10/service 1494
|
||||
group 10
|
||||
/c/slb/virt 10/service 3389
|
||||
group 10
|
||||
/c/slb/virt 10/service 5900
|
||||
group 10
|
||||
|
||||
|
||||
=========================================================
|
||||
3. Simple HTTP/HTTPS load-balancing with cookie insertion
|
||||
=========================================================
|
||||
@ -422,7 +506,7 @@ When an application is spread across several severs, the time to update all
|
||||
instances increases, so the application seems jerky for a longer period.
|
||||
|
||||
HAproxy offers several solutions for this. Although it cannot be reconfigured
|
||||
without being stopped, not does it offer any external command, there are other
|
||||
without being stopped, nor does it offer any external command, there are other
|
||||
working solutions.
|
||||
|
||||
|
||||
@ -588,13 +672,13 @@ To soft-stop the service :
|
||||
|
||||
# kill $(</var/run/haproxy-checks.pid)
|
||||
|
||||
The port 81 will stop to respond and the load-balancer will notice the failure.
|
||||
The port 81 will stop responding and the load-balancer will notice the failure.
|
||||
|
||||
|
||||
4.2.2 Centralizing the server management
|
||||
----------------------------------------
|
||||
|
||||
If one find it preferable to manage the servers from the load-balancer itself,
|
||||
If one finds it preferable to manage the servers from the load-balancer itself,
|
||||
the port redirector can be installed on the load-balancer itself. See the
|
||||
example with iptables below.
|
||||
|
||||
@ -621,8 +705,8 @@ which is available for download here :
|
||||
|
||||
- health-checks will be sent twice as often, once for each standard server,
|
||||
and once for reach backup server. All this will be multiplicated by the
|
||||
number of processes if you use multi-process mode. You will have to check
|
||||
that all the checks sent to the server do not load it.
|
||||
number of processes if you use multi-process mode. You will have to ensure
|
||||
that all the checks sent to the server do not overload it.
|
||||
|
||||
|
||||
==================================================
|
||||
|
@ -2,9 +2,9 @@
|
||||
H A - P r o x y
|
||||
Reference Manual
|
||||
-------------------
|
||||
version 1.2.5
|
||||
version 1.2.6
|
||||
willy tarreau
|
||||
2005/04/30
|
||||
2005/08/07
|
||||
|
||||
============
|
||||
| Abstract |
|
||||
@ -104,8 +104,10 @@ the following ones :
|
||||
- nopoll
|
||||
- quiet
|
||||
- pidfile <file>
|
||||
- ulimit-n <number>
|
||||
- stats
|
||||
|
||||
|
||||
1.1) Event logging
|
||||
------------------
|
||||
Most events are logged : start, stop, servers going up and down, connections and
|
||||
@ -138,14 +140,15 @@ Example :
|
||||
log 192.168.2.200 local3
|
||||
log 127.0.0.1 local4 notice
|
||||
|
||||
|
||||
1.2) limiting the number of connections
|
||||
---------------------------------------
|
||||
It is possible and recommended to limit the global number of per-process
|
||||
connections. Since one connection includes both a client and a server, it
|
||||
means that the max number of TCP sessions will be about the double of this
|
||||
number. It's important to understand this when trying to find best values
|
||||
for 'ulimit -n' before starting the proxy. To anticipate the number of
|
||||
sockets needed, all these parameters must be counted :
|
||||
connections using the 'maxconn' global keyword. Since one connection includes
|
||||
both a client and a server, it means that the max number of TCP sessions will
|
||||
be about the double of this number. It's important to understand this when
|
||||
trying to find best values for 'ulimit -n' before starting the proxy. To
|
||||
anticipate the number of sockets needed, all these parameters must be counted :
|
||||
|
||||
- 1 socket per incoming connection
|
||||
- 1 socket per outgoing connection
|
||||
@ -155,8 +158,18 @@ sockets needed, all these parameters must be counted :
|
||||
|
||||
In simple configurations where each proxy only listens one one address/port,
|
||||
set the limit of file descriptors (ulimit -n) to
|
||||
(2 * maxconn + nbproxies + nbservers + 1). In a future release, haproxy may
|
||||
be able to set this value itself.
|
||||
(2 * maxconn + nbproxies + nbservers + 1). Starting with versions 1.1.32/1.2.6,
|
||||
it is now possible to set the limit in the configuration using the 'ulimit-n'
|
||||
global keyword, provided the proxy is started as root. This puts an end to the
|
||||
recurrent problem of ensuring that the system limits are adapted to the proxy
|
||||
values. Note that these limits are per-process.
|
||||
|
||||
Example :
|
||||
---------
|
||||
global
|
||||
maxconn 32000
|
||||
ulimit-n 65536
|
||||
|
||||
|
||||
1.3) Drop of priviledges
|
||||
------------------------
|
||||
@ -203,6 +216,7 @@ Example :
|
||||
gid 30000
|
||||
chroot /var/chroot/haproxy
|
||||
|
||||
|
||||
1.4) Startup modes
|
||||
------------------
|
||||
The service can start in several different :
|
||||
@ -226,6 +240,7 @@ timestamped display of each connection, disconnection, and HTTP headers for both
|
||||
ways. This mode is incompatible with 'daemon' and 'quiet' modes for obvious
|
||||
reasons.
|
||||
|
||||
|
||||
1.5) Increasing the overall processing power
|
||||
--------------------------------------------
|
||||
On multi-processor systems, it may seem to be a shame to use only one processor,
|
||||
@ -358,6 +373,7 @@ Examples :
|
||||
bind :80,:443
|
||||
bind 10.0.0.1:10080,10.0.0.1:10443
|
||||
|
||||
|
||||
2.1) Inhibiting a service
|
||||
-------------------------
|
||||
A service may be disabled for maintenance reasons, without needing to comment
|
||||
@ -370,6 +386,7 @@ section to be disabled :
|
||||
Note: the 'enabled' keyword allows to enable a service which has been disabled
|
||||
previously by a default configuration.
|
||||
|
||||
|
||||
2.2) Modes of operation
|
||||
-----------------------
|
||||
A service can work in 3 different distinct modes :
|
||||
@ -422,6 +439,38 @@ Example :
|
||||
mode health
|
||||
option httpchk
|
||||
|
||||
Monitoring
|
||||
----------
|
||||
Versions 1.1.32 and 1.2.6 provide a new solution to check the proxy's
|
||||
availability without perturbating the service. The 'monitor-net' keyword was
|
||||
created to specify a network of equipments which CANNOT use the service for
|
||||
anything but health-checks. This is particularly suited to TCP proxies, because
|
||||
it prevents the proxy from relaying the monitor's connection to the remote
|
||||
server.
|
||||
|
||||
When used with TCP, the connection is accepted then closed and nothing is
|
||||
logged. This is enough for a front-end load-balancer to detect the service as
|
||||
available.
|
||||
|
||||
When used with HTTP, the connection is accepted, nothing is logged, the
|
||||
following response is sent, then the session is closed : "HTTP/1.0 200 OK".
|
||||
This is normally enough for any front-end HTTP load-balancer to detect the
|
||||
service as available too, both with TCP and HTTP checks.
|
||||
|
||||
Proxies using the "monitor-net" keyword can remove the "option dontlognull", as
|
||||
it will make them log empty connections from hosts outside the monitoring
|
||||
network.
|
||||
|
||||
Example :
|
||||
---------
|
||||
|
||||
listen tse-proxy
|
||||
bind :3389,:1494,:5900 # TSE, ICA and VNC at once.
|
||||
mode tcp
|
||||
balance roundrobin
|
||||
server tse-farm 192.168.1.10
|
||||
monitor-net 192.168.1.252/31 # L4 load-balancers on .252 and .253
|
||||
|
||||
|
||||
2.3) Limiting the number of simultaneous connections
|
||||
----------------------------------------------------
|
||||
@ -500,6 +549,7 @@ Notes :
|
||||
compensate for a packet loss. A 4 seconds time-out seems a reasonable
|
||||
minimum which will considerably reduce connection failures.
|
||||
|
||||
|
||||
2.6) Attempts to reconnect
|
||||
--------------------------
|
||||
After a connection failure to a server, it is possible to retry, potentially
|
||||
@ -641,6 +691,7 @@ Notes :
|
||||
application to select which page it wants the upstream servers to cache. In
|
||||
this case, you would use 'insert postonly indirect'.
|
||||
|
||||
|
||||
2.10) Associating a cookie value with a server
|
||||
----------------------------------------------
|
||||
In HTTP mode, it's possible to associate a cookie value to each server. This
|
||||
@ -665,6 +716,7 @@ Example : the 'SERVERID' cookie can be either 'server01' or 'server02'
|
||||
Warning : the syntax has changed since version 1.0 !
|
||||
---------
|
||||
|
||||
|
||||
2.11) Application Cookies
|
||||
-------------------------
|
||||
Since 1.2.4 it is possible to catch the cookie that comes from an
|
||||
@ -692,6 +744,7 @@ Example :
|
||||
.
|
||||
.
|
||||
|
||||
|
||||
3) Autonomous load balancer
|
||||
===========================
|
||||
|
||||
@ -765,7 +818,6 @@ Examples :
|
||||
|
||||
3.1) Server monitoring
|
||||
----------------------
|
||||
|
||||
It is possible to check the servers status by trying to establish TCP
|
||||
connections or even sending HTTP requests to them. A server which fails to
|
||||
reply to health checks as expected will not be used by the load balancing
|
||||
@ -905,7 +957,7 @@ Examples :
|
||||
server web-backup 192.168.2.1:80 cookie server03 check backup
|
||||
server web-excuse 192.168.3.1:80 check backup
|
||||
|
||||
# SMTP+TLS relaying with heakth-checks and backup servers
|
||||
# SMTP+TLS relaying with health-checks and backup servers
|
||||
|
||||
listen http_proxy :25,:587
|
||||
mode tcp
|
||||
@ -955,6 +1007,7 @@ option :
|
||||
Other features are available. They are transparent mode, event logging and
|
||||
header rewriting/filtering.
|
||||
|
||||
|
||||
4.1) Network features
|
||||
---------------------
|
||||
4.1.1) Transparent mode
|
||||
@ -1043,6 +1096,32 @@ Example :
|
||||
|
||||
4.2) Event logging
|
||||
------------------
|
||||
|
||||
HAProxy's strength certainly lies in its precise logs. It probably provides the
|
||||
finest level of information available for such a product, which is very
|
||||
important for troubleshooting complex environments. Standard log information
|
||||
include client ports, TCP/HTTP state timers, precise session state at
|
||||
termination and precise termination cause, information about decisions to
|
||||
direct trafic to a server, and of course the ability to capture arbitrary
|
||||
headers.
|
||||
|
||||
In order to improve administrators reactivity, it offers a great transparency
|
||||
about encountered problems, both internal and external, and it is possible to
|
||||
send logs to different sources at the same time with different level filters :
|
||||
|
||||
- global process-level logs (system errors, start/stop, etc..)
|
||||
- per-listener system and internal errors (lack of resource, bugs, ...)
|
||||
- per-listener external troubles (servers up/down, max connections)
|
||||
- per-listener activity (client connections), either at the establishment or
|
||||
at the termination.
|
||||
|
||||
The ability to distribute different levels of logs to different log servers
|
||||
allow several production teams to interact and to fix their problems as soon
|
||||
as possible. For example, the system team might monitor system-wide errors,
|
||||
while the application team might be monitoring the up/down for their servers in
|
||||
real time, and the security team might analyze the activity logs with one hour
|
||||
delay.
|
||||
|
||||
4.2.1) Log levels
|
||||
-----------------
|
||||
TCP and HTTP connections can be logged with informations such as date, time,
|
||||
@ -1078,14 +1157,27 @@ the proxy will wait until the session ends to generate an enhanced log
|
||||
containing more information such as session duration and its state during the
|
||||
disconnection.
|
||||
|
||||
Example :
|
||||
---------
|
||||
Example of TCP logging :
|
||||
------------------------
|
||||
listen relais-tcp 0.0.0.0:8000
|
||||
mode tcp
|
||||
option tcplog
|
||||
log 192.168.2.200 local3
|
||||
|
||||
>>> haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28] relais-tcp Srv1 0/5007 0 --
|
||||
>>> haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28] relais-tcp Srv1 0/5007 0 -- 1/1
|
||||
|
||||
Field Format Example
|
||||
|
||||
1 process_name '[' pid ']:' haproxy[18989]:
|
||||
2 client_ip ':' client_port 127.0.0.1:34550
|
||||
3 '[' date ']' [15/Oct/2003:15:24:28]
|
||||
4 listener_name relais-tcp
|
||||
5 server_name Srv1
|
||||
6 connect_time '/' total_time 0/5007
|
||||
7 bytes_read 0
|
||||
8 termination_state --
|
||||
9 listener_conns '/' process_conns 1/1
|
||||
|
||||
|
||||
Another option, 'httplog', provides more detailed information about HTTP
|
||||
contents, such as the request and some cookies. In the event where an external
|
||||
@ -1094,15 +1186,39 @@ full of useless lines. So it is possible not to log any session which didn't
|
||||
transfer any data, by the setting of the 'dontlognull' option. This only has
|
||||
effect on sessions which are established then closed.
|
||||
|
||||
Example :
|
||||
---------
|
||||
Example of HTTP logging :
|
||||
-------------------------
|
||||
listen http_proxy 0.0.0.0:80
|
||||
mode http
|
||||
option httplog
|
||||
option dontlognull
|
||||
log 192.168.2.200 local3
|
||||
|
||||
>>> haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57] relais-http Srv1 9/7/147/723 200 243 - - ---- "HEAD / HTTP/1.0"
|
||||
>>> haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57] relais-http Srv1 9/7/147/723 200 243 - - ---- 3/3 "HEAD / HTTP/1.0"
|
||||
|
||||
More complete example
|
||||
haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31] relais-http Srv1 3183/-1/-1/11215 503 0 - - SC-- 202/205 {w.ods.org|Mozilla} {} "HEAD / HTTP/1.0"
|
||||
|
||||
Field Format Example
|
||||
|
||||
1 process_name '[' pid ']:' haproxy[18989]:
|
||||
2 client_ip ':' client_port 10.0.0.1:34552
|
||||
3 '[' date ']' [15/Oct/2003:15:26:31]
|
||||
4 listener_name relais-http
|
||||
5 server_name Srv1
|
||||
6 Tq '/' Tc '/' Tr '/' Tt 3183/-1/-1/11215
|
||||
7 HTTP_return_code 503
|
||||
8 bytes_read 0
|
||||
9 captured_request_cookie -
|
||||
10 captured_response_cookie -
|
||||
11 termination_state SC--
|
||||
12 listener_conns '/' process_conns 202/205
|
||||
13 '{' captured_request_headers '}' {w.ods.org|Mozilla}
|
||||
14 '{' captured_response_headers '}' {}
|
||||
15 '"' HTTP_request '"' "HEAD / HTTP/1.0"
|
||||
|
||||
Note for log parsers: the URI is ALWAYS the end of the line starting with the
|
||||
first double quote '"'.
|
||||
|
||||
The problem when logging at end of connection is that you have no clue about
|
||||
what is happening during very long sessions. To workaround this problem, a
|
||||
@ -1127,8 +1243,7 @@ Example :
|
||||
option logasap
|
||||
log 192.168.2.200 local3
|
||||
|
||||
>>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/+30 200 +243 - - ---- "GET /image.iso HTTP/1.0"
|
||||
|
||||
>>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/+30 200 +243 - - ---- 3/3 "GET /image.iso HTTP/1.0"
|
||||
|
||||
4.2.3) Timing events
|
||||
--------------------
|
||||
@ -1197,61 +1312,177 @@ Other cases ('xx' means any value to be ignored) :
|
||||
|
||||
4.2.4) Session state at disconnection
|
||||
-------------------------------------
|
||||
TCP and HTTP logs provide a session completion indicator. It's a 4-characters
|
||||
(2 in TCP) field preceeding the HTTP request, and indicating :
|
||||
TCP and HTTP logs provide a session completion indicator in the
|
||||
<termination_state> field, just before the number of active
|
||||
connections. It is 2-characters long in TCP, and 4-characters long in
|
||||
HTTP, each of which has a special meaning :
|
||||
|
||||
- On the first character, a code reporting the first event which caused the
|
||||
session to terminate :
|
||||
|
||||
C : the TCP session was aborted by the client.
|
||||
S : the TCP session was aborted by the server, or the server refused it.
|
||||
P : the session was abordted prematurely by the proxy, either because of
|
||||
an internal error, because a DENY filter was matched, or because of
|
||||
a security check which detected a dangerous error in server
|
||||
response.
|
||||
c : the client time-out expired first.
|
||||
s : the server time-out expired first.
|
||||
C : the TCP session was unexpectedly aborted by the client.
|
||||
|
||||
S : the TCP session was unexpectedly aborted by the server, or the
|
||||
server explicitly refused it.
|
||||
|
||||
P : the session was prematurely aborted by the proxy, because of a
|
||||
connection limit enforcement, because a DENY filter was matched,
|
||||
or because of a security check which detected and blocked a
|
||||
dangerous error in server response which might have caused
|
||||
information leak (eg: cacheable cookie).
|
||||
|
||||
R : a resource on the proxy has been exhausted (memory, sockets, source
|
||||
ports, ...). Usually, this appears during the connection phase, and
|
||||
system logs should contain a copy of the precise error.
|
||||
|
||||
I : an internal error was identified by the proxy during a self-check.
|
||||
This should NEVER happen, and you are encouraged to report any log
|
||||
containing this, because this is a bug.
|
||||
|
||||
c : the client-side time-out expired first.
|
||||
|
||||
s : the server-side time-out expired first.
|
||||
|
||||
- : normal session completion.
|
||||
|
||||
- on the second character, the HTTP session state when it was closed :
|
||||
- on the second character, the TCP/HTTP session state when it was closed :
|
||||
|
||||
R : waiting for complete REQUEST from the client (HTTP only). Nothing
|
||||
was sent to any server.
|
||||
|
||||
C : waiting for CONNECTION to establish on the server. The server might
|
||||
at most have noticed a connection attempt.
|
||||
|
||||
H : waiting for, receiving and processing server HEADERS (HTTP only).
|
||||
|
||||
D : the session was in the DATA phase.
|
||||
|
||||
R : waiting for complete REQUEST from the client
|
||||
C : waiting for CONNECTION to establish on the server
|
||||
H : processing server HEADERS
|
||||
D : the session was in the DATA phase
|
||||
L : the proxy was still transmitting LAST data to the client while the
|
||||
server had already finished.
|
||||
|
||||
- : normal session completion after end of data transfer.
|
||||
|
||||
- the third character tells whether the persistence cookie was provided by
|
||||
the client (only in HTTP mode) :
|
||||
|
||||
N : the client provided NO cookie.
|
||||
I : the client provided an INVALID cookie matching no known server.
|
||||
N : the client provided NO cookie. This is usually the case on new
|
||||
connections.
|
||||
|
||||
I : the client provided an INVALID cookie matching no known
|
||||
server. This might be caused by a recent configuration change,
|
||||
mixed cookies between HTTP/HTTPS sites, or an attack.
|
||||
|
||||
D : the client provided a cookie designating a server which was DOWN,
|
||||
so either the 'persist' option was used and the client was sent to
|
||||
this server, or it was not set and the client was redispatched to
|
||||
another server.
|
||||
|
||||
V : the client provided a valid cookie, and was sent to the associated
|
||||
server.
|
||||
|
||||
- : does not apply (no cookie set in configuration).
|
||||
|
||||
- the last character reports what operations were performed on the persistence
|
||||
cookie returned by the server (only in HTTP mode) :
|
||||
|
||||
N : NO cookie was provided by the server.
|
||||
N : NO cookie was provided by the server, and none was inserted either.
|
||||
|
||||
I : no cookie was provided by the server, and the proxy INSERTED one.
|
||||
|
||||
P : a cookie was PROVIDED by the server and transmitted as-is.
|
||||
I : no cookie was provided by the server, and one was INSERTED by the
|
||||
proxy.
|
||||
D : the cookie provided by the server was DELETED by the proxy.
|
||||
|
||||
R : the cookie provided by the server was REWRITTEN by the proxy.
|
||||
|
||||
D : the cookie provided by the server was DELETED by the proxy.
|
||||
|
||||
- : does not apply (no cookie set in configuration).
|
||||
|
||||
The 'capture' keyword allows to capture and log informations exchanged between
|
||||
clients and servers. As of version 1.1.23, only cookies can be captured, which
|
||||
makes it easy to track a complete user session. The syntax is :
|
||||
The combination of the two first flags give a lot of information about what was
|
||||
happening when the session terminated. It can be helpful to detect server
|
||||
saturation, network troubles, local system resource starvation, attacks, etc...
|
||||
|
||||
The most common termination flags combinations are indicated here.
|
||||
|
||||
Flags Reason
|
||||
CR The client aborted before sending a full request. Most probably the
|
||||
request was done by hand using a telnet client, and aborted early.
|
||||
|
||||
cR The client timed out before sending a full request. This is sometimes
|
||||
caused by too large TCP MSS values on the client side for PPPoE
|
||||
networks which cannot transport full-sized packets, or by clients
|
||||
sending requests by hand and not typing fast enough.
|
||||
|
||||
SC The server explicitly refused the connection (the proxy received a
|
||||
TCP RST or an ICMP in return). Under some circumstances, it can
|
||||
also be the network stack telling the proxy that the server is
|
||||
unreachable (eg: no route, or no ARP response on local network).
|
||||
|
||||
sC The connection to the server did not complete during contimeout.
|
||||
|
||||
PC The proxy refused to establish a connection to the server because the
|
||||
maxconn limit has been reached. The listener's maxconn parameter may
|
||||
be increased in the proxy configuration, as well as the global
|
||||
maxconn parameter.
|
||||
|
||||
RC A local resource has been exhausted (memory, sockets, source ports)
|
||||
preventing the connection to the server from establishing. The error
|
||||
logs will tell precisely what was missing. Anyway, this can only be
|
||||
solved by system tuning.
|
||||
|
||||
cH The client timed out during a POST request. This is sometimes caused
|
||||
by too large TCP MSS values for PPPoE networks which cannot transport
|
||||
full-sized packets.
|
||||
|
||||
SH The server aborted before sending its full headers, or it crashed.
|
||||
|
||||
sH The server failed to reply during the srvtimeout delay, which
|
||||
indicates too long transactions, probably caused by back-end
|
||||
saturation. The only solutions are to fix the problem on the
|
||||
application or to increase the 'srvtimeout' parameter to support
|
||||
longer delays (at the risk of the client giving up anyway).
|
||||
|
||||
PR The proxy blocked the client's request, either because of an invalid
|
||||
HTTP syntax, in which case it returned an HTTP 400 error to the
|
||||
client, or because a deny filter matched, in which case it returned
|
||||
an HTTP 403 error.
|
||||
|
||||
PH The proxy blocked the server's response, because it was invalid,
|
||||
incomplete, dangerous (cache control), or matched a security filter.
|
||||
In any case, an HTTP 502 error is sent to the client.
|
||||
|
||||
cD The client did not read any data for as long as the clitimeout delay.
|
||||
This is often caused by network failures on the client side.
|
||||
|
||||
CD The client unexpectedly aborted during data transfer. This is either
|
||||
caused by a browser crash, or by a keep-alive session between the
|
||||
server and the client terminated first by the client.
|
||||
|
||||
sD The server did nothing during the srvtimeout delay. This is often
|
||||
caused by too short timeouts on L4 equipements before the server
|
||||
(firewalls, load-balancers, ...).
|
||||
|
||||
4.2.5) Non-printable characters
|
||||
-------------------------------
|
||||
As of version 1.1.29, non-printable characters are not sent as-is into log
|
||||
files, but are converted to their two-digits hexadecimal representation,
|
||||
prefixed by the character '#'. The only characters that can now be logged
|
||||
without being escaped are between 32 and 126 (inclusive). Obviously, the
|
||||
escape character '#' is also encoded to avoid any ambiguity. It is the same for
|
||||
the character '"', as well as '{', '|' and '}' when logging headers.
|
||||
|
||||
4.2.6) Capturing HTTP headers and cookies
|
||||
-----------------------------------------
|
||||
Version 1.1.23 brought cookie capture, and 1.1.29 the header capture. All this
|
||||
is performed using the 'capture' keyword.
|
||||
|
||||
Cookie capture makes it easy to track a complete user session. The syntax is :
|
||||
|
||||
capture cookie <cookie_prefix> len <capture_length>
|
||||
|
||||
This will enable cookie capture from both requests and responses. This way,
|
||||
it's easy to detect when a user switches to a new session for example, because
|
||||
the server will reassign it a new cookie.
|
||||
|
||||
The FIRST cookie whose name starts with <cookie_prefix> will be captured, and
|
||||
logged as 'NAME=value', without exceeding <capture_length> characters (64 max).
|
||||
When the cookie name is fixed and known, it's preferable to suffix '=' to it to
|
||||
@ -1267,63 +1498,16 @@ Examples :
|
||||
|
||||
In the logs, the field preceeding the completion indicator contains the cookie
|
||||
value as sent by the server, preceeded by the cookie value as sent by the
|
||||
client. Each of these field is replaced with '-' when no cookie was seen.
|
||||
client. Each of these field is replaced with '-' when no cookie was seen or
|
||||
when the option is disabled.
|
||||
|
||||
4.2.5) Examples of logs
|
||||
-----------------------
|
||||
- haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57] relais-http Srv1 6559/7/147/6723 200 243 - - ---- "HEAD / HTTP/1.0"
|
||||
=> long request (6.5s) entered by hand through 'telnet'. The server replied
|
||||
in 147 ms, and the session ended normally ('----')
|
||||
|
||||
- haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/+30 200 +243 - - ---- "GET /image.iso HTTP/1.0"
|
||||
=> request for a long data transfer. The 'logasap' option was specified, so
|
||||
the log was produced just before transfering data. The server replied in
|
||||
14 ms, 243 bytes of headers were sent to the client, and total time from
|
||||
accept to first data byte is 30 ms.
|
||||
|
||||
- haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/30 502 243 - - PH-- "GET /cgi-bin/bug.cgi? HTTP/1.0"
|
||||
=> the proxy blocked a server response either because of an 'rspdeny' or
|
||||
'rspideny' filter, or because it blocked sensible information which risked
|
||||
being cached. In this case, the response is replaced with a '502 bad
|
||||
gateway'.
|
||||
|
||||
- haproxy[18113]: 127.0.0.1:34548 [15/Oct/2003:15:18:55] relais-http <NOSRV> -1/-1/-1/8490 -1 0 - - CR-- ""
|
||||
=> the client never completed its request and aborted itself ('C---') after
|
||||
8.5s, while the proxy was waiting for the request headers ('-R--').
|
||||
Nothing was sent to the server.
|
||||
|
||||
- haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06] relais-http <NOSRV> -1/-1/-1/50001 408 0 - - cR-- ""
|
||||
=> The client never completed its request, which was aborted by the time-out
|
||||
('c---') after 50s, while the proxy was waiting for the request headers ('-R--').
|
||||
Nothing was sent to the server, but the proxy could send a 408 return code
|
||||
to the client.
|
||||
|
||||
- haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28] relais-tcp Srv1 0/5007 0 cD
|
||||
=> This is a 'tcplog' entry. Client-side time-out ('c----') occured after 5s.
|
||||
|
||||
- haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31] relais-http Srv1 3183/-1/-1/11215 503 0 - - SC-- "HEAD / HTTP/1.0"
|
||||
=> The request took 3s to complete (probably a network problem), and the
|
||||
connection to the server failed ('SC--') after 4 attemps of 2 seconds
|
||||
(config says 'retries 3'), then a 503 error code was sent to the client.
|
||||
|
||||
4.2.6) Non-printable characters
|
||||
-------------------------------
|
||||
As of version 1.1.29, non-printable characters are not sent as-is into log
|
||||
files, but are converted to their two-digits hexadecimal representation,
|
||||
prefixed by the character '#'. The only characters that can now be logged
|
||||
without being escaped are between 32 and 126 (inclusive). Obviously, the
|
||||
escape character '#' is also encoded to avoid any ambiguity. It is the same for
|
||||
the character '"', as well as '{', '|' and '}' when logging headers.
|
||||
|
||||
4.2.7) Logging HTTP headers
|
||||
---------------------------
|
||||
As of version 1.1.29, it is now possible to log HTTP headers extracts. It is
|
||||
both possible to include request headers and response headers. It is
|
||||
particularly useful to know what virtual server the client requested, to know
|
||||
the content length during a POST request, or a unique request ID set on a
|
||||
previous proxy. In the response, one can search for information about the
|
||||
response length, how the server asked the cache to behave, or an object location
|
||||
during a redirection. The syntax is :
|
||||
Header captures have a different goal. They are useful to track unique request
|
||||
identifiers set by a previous proxy, virtual host names, user-agents, POST
|
||||
content-length, referrers, etc. In the response, one can search for information
|
||||
about the response length, how the server asked the cache to behave, or an
|
||||
object location during a redirection. As for cookie captures, it is both
|
||||
possible to include request headers and response headers at the same time. The
|
||||
syntax is :
|
||||
|
||||
capture request header <name> len <max length>
|
||||
capture response header <name> len <max length>
|
||||
@ -1348,6 +1532,7 @@ within braces '{' and '}' in the same order as they were declared, and delimited
|
||||
with a vertical bar '|' without any space. Response headers follow the same
|
||||
representation, but are displayed after a space following the request headers
|
||||
block. These blocks are displayed just before the HTTP request in the logs.
|
||||
|
||||
Example :
|
||||
|
||||
Config:
|
||||
@ -1367,6 +1552,48 @@ Aug 9 20:26:09 localhost haproxy[2022]: 127.0.0.1:34014 [09/Aug/2004:20:26:09]
|
||||
Aug 9 20:30:46 localhost haproxy[2022]: 127.0.0.1:34020 [09/Aug/2004:20:30:46] relais-http netcache 0/0/182/+182 200 +279 - - ---- {w.ods.org||} {Formilux/0.1.8|3495|||} "GET http://w.ods.org/sytadin.html HTTP/1.1"
|
||||
Aug 9 20:30:46 localhost haproxy[2022]: 127.0.0.1:34028 [09/Aug/2004:20:30:46] relais-http netcache 0/2/126/+128 200 +223 - - ---- {www.infotrafic.com||http://w.ods.org/syt} {Apache/2.0.40 (Red H|9068|||} "GET http://www.infotrafic.com/images/live/cartesidf/grandes/idf_ne.png HTTP/1.1"
|
||||
|
||||
|
||||
4.2.7) Examples of logs
|
||||
-----------------------
|
||||
- haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57] relais-http Srv1 6559/7/147/6723 200 243 - - ---- 3/5 "HEAD / HTTP/1.0"
|
||||
=> long request (6.5s) entered by hand through 'telnet'. The server replied
|
||||
in 147 ms, and the session ended normally ('----')
|
||||
|
||||
- haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/+30 200 +243 - - ---- 3/3 "GET /image.iso HTTP/1.0"
|
||||
=> request for a long data transfer. The 'logasap' option was specified, so
|
||||
the log was produced just before transfering data. The server replied in
|
||||
14 ms, 243 bytes of headers were sent to the client, and total time from
|
||||
accept to first data byte is 30 ms.
|
||||
|
||||
- haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/30 502 243 - - PH-- 2/3 "GET /cgi-bin/bug.cgi? HTTP/1.0"
|
||||
=> the proxy blocked a server response either because of an 'rspdeny' or
|
||||
'rspideny' filter, or because it blocked sensible information which risked
|
||||
being cached. In this case, the response is replaced with a '502 bad
|
||||
gateway'.
|
||||
|
||||
- haproxy[18113]: 127.0.0.1:34548 [15/Oct/2003:15:18:55] relais-http <NOSRV> -1/-1/-1/8490 -1 0 - - CR-- 2/2 ""
|
||||
=> the client never completed its request and aborted itself ('C---') after
|
||||
8.5s, while the proxy was waiting for the request headers ('-R--').
|
||||
Nothing was sent to the server.
|
||||
|
||||
- haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06] relais-http <NOSRV> -1/-1/-1/50001 408 0 - - cR-- 2/2 ""
|
||||
=> The client never completed its request, which was aborted by the time-out
|
||||
('c---') after 50s, while the proxy was waiting for the request headers ('-R--').
|
||||
Nothing was sent to the server, but the proxy could send a 408 return code
|
||||
to the client.
|
||||
|
||||
- haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28] relais-tcp Srv1 0/5007 0 cD
|
||||
=> This is a 'tcplog' entry. Client-side time-out ('c----') occured after 5s.
|
||||
|
||||
- haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31] relais-http Srv1 3183/-1/-1/11215 503 0 - - SC-- 202/205 "HEAD / HTTP/1.0"
|
||||
=> The request took 3s to complete (probably a network problem), and the
|
||||
connection to the server failed ('SC--') after 4 attemps of 2 seconds
|
||||
(config says 'retries 3'), then a 503 error code was sent to the client.
|
||||
There were 202 connections on this proxy, and 205 on the global process.
|
||||
It is possible that the server refused the connection because of too many
|
||||
already established.
|
||||
|
||||
|
||||
4.3) HTTP header manipulation
|
||||
-----------------------------
|
||||
In HTTP mode, it is possible to rewrite, add or delete some of the request and
|
||||
@ -1500,6 +1727,7 @@ Example :
|
||||
option forwardfor
|
||||
option httpclose
|
||||
|
||||
|
||||
4.4) Load balancing with persistence
|
||||
------------------------------------
|
||||
Combining cookie insertion with internal load balancing allows to transparently
|
||||
@ -1561,6 +1789,7 @@ session state shows "PH--" meaning that the proxy blocked the response during
|
||||
headers processing. Additionnaly, an alert will be sent in the logs so that
|
||||
admins are told that there's something to be done.
|
||||
|
||||
|
||||
4.6) Customizing errors
|
||||
-----------------------
|
||||
Some situations can make haproxy return an HTTP error code to the client :
|
||||
@ -1601,8 +1830,8 @@ Location returned by a 302, which causes problems with the POST method.
|
||||
The return code 303 was designed explicitly to force the client to fetch the
|
||||
Location URL with the GET method, but there are some browsers pre-dating
|
||||
HTTP/1.1 which don't support it. Anyway, most browsers still behave with 302 as
|
||||
if it was a 303. In order to allow the user to chose, version 1.2.5 brings two
|
||||
new keywords to replace 'errorloc' : 'errorloc302' and 'errorloc303'.
|
||||
if it was a 303. In order to allow the user to chose, versions 1.1.31 and 1.2.5
|
||||
bring two new keywords to replace 'errorloc' : 'errorloc302' and 'errorloc303'.
|
||||
|
||||
They are preffered over errorloc (which still does 302). Consider using
|
||||
errorloc303 everytime you know that your clients support HTTP 303 responses..
|
||||
@ -1721,7 +1950,7 @@ echo 300 > /proc/sys/net/ipv4/tcp_keepalive_time
|
||||
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
|
||||
echo 0 > /proc/sys/net/ipv4/tcp_timestamps
|
||||
echo 0 > /proc/sys/net/ipv4/tcp_ecn
|
||||
echo 0 > /proc/sys/net/ipv4/tcp_sack
|
||||
echo 1 > /proc/sys/net/ipv4/tcp_sack
|
||||
echo 0 > /proc/sys/net/ipv4/tcp_dsack
|
||||
|
||||
# auto-tuned on 2.4
|
||||
|
@ -2,9 +2,9 @@
|
||||
H A - P r o x y
|
||||
Manuel de référence
|
||||
-------------------
|
||||
version 1.2.5
|
||||
version 1.2.6
|
||||
willy tarreau
|
||||
2005/04/30
|
||||
2005/08/07
|
||||
|
||||
================
|
||||
| Introduction |
|
||||
@ -17,7 +17,7 @@ environnement hautement disponible. En effet, il est capable de :
|
||||
la persistence de session ;
|
||||
- fournir une visibilité externe de son état de santé ;
|
||||
- s'arrêter en douceur sans perte brutale de service ;
|
||||
- modifier/ajouter/supprimer des entêtes dans la requête et la réponse ;
|
||||
- modifier/ajouter/supprimer des en-têtes dans la requête et la réponse ;
|
||||
- interdire des requêtes qui vérifient certaines conditions ;
|
||||
- utiliser des serveurs de secours lorsque les serveurs principaux sont hors
|
||||
d'usage.
|
||||
@ -61,7 +61,7 @@ connexions TCP utilisables
|
||||
confondus. Ce paramètre remplace le paramètre 'maxconn' de la section 'global'.
|
||||
|
||||
Le mode debug correspond à l'option 'debug' de la section 'global'. Dans ce
|
||||
mode, toutes les connexions, déconnexions, et tous les échanges d'entêtes HTTP
|
||||
mode, toutes les connexions, déconnexions, et tous les échanges d'en-têtes HTTP
|
||||
sont affichés.
|
||||
|
||||
Les statistiques ne sont disponibles que si le programme a été compilé avec
|
||||
@ -110,6 +110,8 @@ support
|
||||
- nopoll
|
||||
- quiet
|
||||
- pidfile <fichier>
|
||||
- ulimit-n <nombre>
|
||||
|
||||
|
||||
1.1) Journalisation des événements
|
||||
----------------------------------
|
||||
@ -146,11 +148,13 @@ Exemple :
|
||||
1.2) limitation du nombre de connexions
|
||||
---------------------------------------
|
||||
Il est possible et conseillé de limiter le nombre global de connexions par
|
||||
processus. Les connexions sont comprises au sens 'acceptation de connexion',
|
||||
donc il faut s'attendre en règle général à avoir un peu plus du double de
|
||||
sessions TCP que le maximum de connexions fixé. C'est important pour fixer le
|
||||
paramètre 'ulimit -n' avant de lancer le proxy. Pour comptabiliser le nombre
|
||||
de sockets nécessaires, il faut prendre en compte ces paramètres :
|
||||
processus à l'aide du mot clé global 'maxconn'. Les connexions sont comprises
|
||||
au sens 'acceptation de connexion', donc il faut s'attendre en règle général à
|
||||
avoir un peu plus du double de sessions TCP que le maximum de connexions fixé.
|
||||
C'est important pour fixer le paramètre 'ulimit -n' avant de lancer le proxy.
|
||||
Pour comptabiliser le nombre de sockets nécessaires, il faut prendre en compte
|
||||
ces paramètres :
|
||||
|
||||
- 1 socket par connexion entrante
|
||||
- 1 socket par connexion sortante
|
||||
- 1 socket par couple adresse/port d'écoute par proxy
|
||||
@ -159,8 +163,21 @@ de sockets n
|
||||
|
||||
Dans le cas où chaque proxy n'écoute que sur un couple adresse/port,
|
||||
positionner la limite du nombre de descripteurs de fichiers (ulimit -n) à
|
||||
(2 * maxconn + nbproxy + nbserveurs + 1). Dans une future version, haproxy sera
|
||||
capable de positionner lui-même cette limite.
|
||||
(2 * maxconn + nbproxy + nbserveurs + 1). A partir des versions 1.1.32/1.2.6,
|
||||
il est possible de spécifier cette limite dans la configuration à l'aide du
|
||||
mot-clé global 'ulimit-n', à condition bien entendu que le proxy ait été
|
||||
démarré sous le compte root (ou avec des droits suffisants pour élever le
|
||||
nombre de descripteurs de fichiers). Cette solution met un terme au problème
|
||||
récurrent d'incertitude de l'adéquation entre les limites systèmes lors de la
|
||||
dernière relance du proxessus et les limites en nombre de connexions. Noter que
|
||||
cette limite s'applique par processus.
|
||||
|
||||
Exemple :
|
||||
---------
|
||||
global
|
||||
maxconn 32000
|
||||
ulimit-n 65536
|
||||
|
||||
|
||||
1.3) Diminution des privilèges
|
||||
------------------------------
|
||||
@ -414,7 +431,7 @@ Mode HTTP
|
||||
---------
|
||||
Dans ce mode, le service relaye les connexions TCP vers un ou plusieurs
|
||||
serveurs, une fois qu'il dispose d'assez d'informations pour en prendre la
|
||||
décision. Les entêtes HTTP sont analysés pour y trouver un éventuel cookie, et
|
||||
décision. Les en-têtes HTTP sont analysés pour y trouver un éventuel cookie, et
|
||||
certains d'entre-eux peuvent être modifiés par le biais d'expressions
|
||||
régulières. Pour activer ce mode, préciser le mode HTTP sous la déclaration du
|
||||
relais.
|
||||
@ -446,6 +463,38 @@ Exemple :
|
||||
option httpchk
|
||||
|
||||
|
||||
Les versions 1.1.32 et 1.2.6 apportent une nouvelle solution pour valider le
|
||||
bon fonctionnement du proxy sans perturber le service. Le mot-clé 'monitor-net'
|
||||
a été créé dans le butd de spécifier un réseau d'équipements qui ne PEUVENT PAS
|
||||
utiliser le service pour autre chose que des tests de fonctionnement. C'est
|
||||
particulièrement adapté aux proxies TCP, car cela empêche le proxy de relayer
|
||||
des établissements de connexion émis par un outil de surveillance.
|
||||
|
||||
Lorsque c'est utilisé sur un proxy TCP, la connexion est acceptée puis refermée
|
||||
et rien n'est logué. C'est suffisant pour qu'un répartiteur de charge en amont
|
||||
détecte que le service est disponible.
|
||||
|
||||
Lorsque c'est utilisé sur un proxy HTTP, la connexion est acceptée, rien n'est
|
||||
logué, puis la réponse suivante est envoyée et la session refermée :
|
||||
"HTTP/1.0 200 OK". C'est normalement suffisant pour qu'un répartiteur de charge
|
||||
HTTP en amont détecte le service comme opérationnel, aussi bien à travers des
|
||||
tests TCP que HTTP.
|
||||
|
||||
Les proxies utilisant le mot-clé 'monitor-net' peuvent accessoirement se passer
|
||||
de l'option 'dontlognull', ce qui permettra de loguer les connexions vides
|
||||
émises depuis d'autres adresses que celles du réseau de tests.
|
||||
|
||||
Exemple :
|
||||
---------
|
||||
|
||||
listen tse-proxy
|
||||
bind :3389,:1494,:5900 # TSE, ICA and VNC at once.
|
||||
mode tcp
|
||||
balance roundrobin
|
||||
server tse-farm 192.168.1.10
|
||||
monitor-net 192.168.1.252/31 # L4 load-balancers on .252 and .253
|
||||
|
||||
|
||||
2.3) Limitation du nombre de connexions simultanées
|
||||
---------------------------------------------------
|
||||
Le paramètre "maxconn" permet de fixer la limite acceptable en nombre de
|
||||
@ -965,7 +1014,7 @@ tente de s'y connecter, il faut pr
|
||||
|
||||
D'autres fonctionnalités d'usage moins courant sont disponibles. Il s'agit
|
||||
principalement du mode transparent, de la journalisation des connexions, et de
|
||||
la réécriture des entêtes.
|
||||
la réécriture des en-têtes.
|
||||
|
||||
4.1) Fonctionnalités réseau
|
||||
---------------------------
|
||||
@ -1056,6 +1105,35 @@ Exemple :
|
||||
|
||||
4.2) Journalisation des connexions
|
||||
----------------------------------
|
||||
|
||||
L'un des points forts de HAProxy est indéniablement la précision de ses logs.
|
||||
Il fournit probablement le plus fin niveau d'information disponible pour un
|
||||
tel outil, ce qui est très important pour les diagnostics en environnements
|
||||
complexes. En standard, les informations journalisées incluent le port client,
|
||||
les chronométrages des états TCP/HTTP, des états de session précis au moment de
|
||||
la terminaison et sa cause, des informations sur les décisions d'aiguillage du
|
||||
trafic vers un serveur, et bien sûr la possibilité de capturer des en-têtes
|
||||
arbitraires.
|
||||
|
||||
Dans le but d'améliorer la réactivité des administrateurs, il offre une grande
|
||||
transparence sur les problèmes rencontrés, à la fois internes et externes, et
|
||||
il est possible d'envoyer les logs vers des serveurs différents en même temps
|
||||
avec des niveaux de filtrage différents :
|
||||
|
||||
- logs globaux au niveau processus (erreurs système, arrêts/démarrages, ...)
|
||||
- erreurs système et internes par instance (manque de ressources, bugs, ...)
|
||||
- problèmes externes par instance (arrêts/relance serveurs, limites, ...)
|
||||
- activité par instance (connexions clients), aussi bien lors de leur
|
||||
établissement qu'à leur terminaison.
|
||||
|
||||
La possibilité de distribuer différents niveaux de logs à différents serveurs
|
||||
permet à plusieurs équipes de production d'intéragir et de corriger leurs
|
||||
problèmes le plus tôt possible. Par exemple, l'équipe système peut surveiller
|
||||
occasionnellement les erreurs système, pendant que l'équipe application
|
||||
surveille les alertes d'arrêts/démarrages de ses serveurs en temps réel, et
|
||||
que l'équipe sécurité analyse l'activité en différé d'une heure.
|
||||
|
||||
|
||||
4.2.1) Niveaux de log
|
||||
---------------------
|
||||
Les connexions TCP et HTTP peuvent donner lieu à une journalisation sommaire ou
|
||||
@ -1092,14 +1170,26 @@ la connexion ne sera journalis
|
||||
sur son état lors de la déconnexion, ainsi que le temps de connexion et la
|
||||
durée totale de la session.
|
||||
|
||||
Exemple :
|
||||
---------
|
||||
Exemple de journalisation TCP :
|
||||
-------------------------------
|
||||
listen relais-tcp 0.0.0.0:8000
|
||||
mode tcp
|
||||
option tcplog
|
||||
log 192.168.2.200 local3
|
||||
|
||||
>>> haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28] relais-tcp Srv1 0/5007 0 --
|
||||
>>> haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28] relais-tcp Srv1 0/5007 0 -- 1/1
|
||||
|
||||
Champ Format / Description Exemple
|
||||
|
||||
1 nom_processus '[' pid ']:' haproxy[18989]:
|
||||
2 ip_client ':' port_client 127.0.0.1:34550
|
||||
3 '[' date ']' [15/Oct/2003:15:24:28]
|
||||
4 nom_instance relais-tcp
|
||||
5 nom_serveur Srv1
|
||||
6 temps_connect '/' temps_total 0/5007
|
||||
7 octets lus 0
|
||||
8 etat_terminaison --
|
||||
9 conns_instance '/' conns_processus 1/1
|
||||
|
||||
Une autre option, 'httplog', fournit plus de détails sur le protocole HTTP,
|
||||
notamment la requête et l'état des cookies. Dans les cas où un mécanisme de
|
||||
@ -1108,15 +1198,40 @@ les logs, il suffit d'ajouter l'option 'dontlognull', pour ne plus obtenir une
|
||||
ligne de log pour les sessions n'ayant pas donné lieu à un échange de données
|
||||
(requête ou réponse).
|
||||
|
||||
Exemple :
|
||||
---------
|
||||
Exemple de journalisation HTTP :
|
||||
--------------------------------
|
||||
listen http_proxy 0.0.0.0:80
|
||||
mode http
|
||||
option httplog
|
||||
option dontlognull
|
||||
log 192.168.2.200 local3
|
||||
|
||||
>>> haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57] relais-http Srv1 9/7/147/723 200 243 - - ---- "HEAD / HTTP/1.0"
|
||||
>>> haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57] relais-http Srv1 9/7/147/723 200 243 - - ---- 3/3 "HEAD / HTTP/1.0"
|
||||
|
||||
Exemple plus complet :
|
||||
|
||||
haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31] relais-http Srv1 3183/-1/-1/11215 503 0 - - SC-- 202/205 {w.ods.org|Mozilla} {} "HEAD / HTTP/1.0"
|
||||
|
||||
Champ Format / Description Exemple
|
||||
|
||||
1 nom_processus '[' pid ']:' haproxy[18989]:
|
||||
2 ip_client ':' port_client 10.0.0.1:34552
|
||||
3 '[' date ']' [15/Oct/2003:15:26:31]
|
||||
4 nom_instance relais-http
|
||||
5 nom_serveur Srv1
|
||||
6 Tq '/' Tc '/' Tr '/' Tt 3183/-1/-1/11215
|
||||
7 Code_retour_HTTP 503
|
||||
8 octets lus 0
|
||||
9 cookies_requête_capturés -
|
||||
10 cookies_reponse_capturés -
|
||||
11 etat_terminaison SC--
|
||||
12 conns_instance '/' conns_processus 202/205
|
||||
13 '{' entetes_requête_capturés '}' {w.ods.org|Mozilla}
|
||||
14 '{' entetes_reponse_capturés '}' {}
|
||||
15 '"' requête_HTTP '"' "HEAD / HTTP/1.0"
|
||||
|
||||
Note pour les analyseurs de logs : l'URI est TOUJOURS le dernier champ de la ligne, et
|
||||
commence par un guillemet '"'.
|
||||
|
||||
Le problème de loguer uniquement en fin de session, c'est qu'il est impossible
|
||||
de savoir ce qui se passe durant de gros transferts ou des sessions longues.
|
||||
@ -1125,12 +1240,12 @@ la version 1.1.28 (1.2.1). Lorsqu'elle est activ
|
||||
tôt possible, c'est à dire juste avant que ne débutent les transferts de
|
||||
données. Cela signifie, dans le cas du TCP, qu'il loguera toujours le résultat
|
||||
de la connexion vers le serveur, et dans le cas HTTP, qu'il loguera en fin de
|
||||
traitement des entêtes de la réponse du serveur, auquel cas le nombre d'octets
|
||||
représentera la taille des entêtes retournés au client.
|
||||
traitement des en-têtes de la réponse du serveur, auquel cas le nombre d'octets
|
||||
représentera la taille des en-têtes retournés au client.
|
||||
|
||||
Afin d'éviter toute confusion avec les logs normaux, le temps total de
|
||||
transfert et le nombre d'octets transférés sont préfixés d'un signe '+'
|
||||
rappeleant que les valeurs réelles sont certainement plus élevées.
|
||||
rappelant que les valeurs réelles sont certainement plus élevées.
|
||||
|
||||
Exemple :
|
||||
---------
|
||||
@ -1142,7 +1257,7 @@ Exemple :
|
||||
option logasap
|
||||
log 192.168.2.200 local3
|
||||
|
||||
>>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/+30 200 +243 - - ---- "GET /image.iso HTTP/1.0"
|
||||
>>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/+30 200 +243 - - ---- 3/3 "GET /image.iso HTTP/1.0"
|
||||
|
||||
|
||||
4.2.3) Chronométrage des événements
|
||||
@ -1166,10 +1281,10 @@ la forme Tq/Tc/Tr/Tt :
|
||||
vers le serveur.
|
||||
|
||||
- Tr: temps de réponse du serveur. C'est le temps que le serveur a mis pour
|
||||
renvoyer la totalité des entêtes HTTP à partir du moment où il a acquitté
|
||||
renvoyer la totalité des en-têtes HTTP à partir du moment où il a acquitté
|
||||
la connexion. Ca représente exactement le temps de traitement de la
|
||||
transaction sans le transfert des données associées. Une valeur '-1'
|
||||
indique que le serveur n'a pas envoyé la totalité de l'entête HTTP.
|
||||
indique que le serveur n'a pas envoyé la totalité de l'en-tête HTTP.
|
||||
|
||||
- Tt: durée de vie totale de la session, entre le moment où la demande de
|
||||
connexion du client a été acquittée et le moment où la connexion a été
|
||||
@ -1220,66 +1335,199 @@ Autres cas ('xx' repr
|
||||
|
||||
4.2.4) Conditions de déconnexion
|
||||
--------------------------------
|
||||
Les logs TCP et HTTP fournissent un indicateur de complétude de la session.
|
||||
C'est un champ de 4 caractères (2 en TCP) précédant la requête HTTP, indiquant:
|
||||
- sur le premier caractère, un code précisant le premier événement qui a
|
||||
causé la terminaison de la session :
|
||||
Les logs TCP et HTTP fournissent un indicateur de complétude de la session dans
|
||||
le champ 'etat_terminaison', juste avant le nombre de connexions actives. C'est
|
||||
un champ long de 2 caractères en TCP et de 4 caractères en HTTP, chacun ayant
|
||||
une signification précise :
|
||||
|
||||
C : fermeture de la session TCP de la part du client
|
||||
S : fermeture de la session TCP de la part du serveur, ou refus de connexion
|
||||
P : terminaison prématurée des sessions par le proxy, pour cas d'erreur
|
||||
interne, de configuration (ex: filtre d'URL), ou parce qu'un
|
||||
contrôle de sécurité a détecté une anomalie dans la réponse du
|
||||
serveur.
|
||||
c : expiration du délai d'attente côté client : clitimeout
|
||||
s : expiration du délai d'attente côté serveur: srvtimeout et contimeout
|
||||
- : terminaison normale.
|
||||
- sur le premier caractère, un code précisant le premier événement qui a causé
|
||||
la terminaison de la session :
|
||||
|
||||
- sur le second caractère, l'état d'avancement de la session HTTP lors de la
|
||||
fermeture :
|
||||
C : fermeture inattendue de la session TCP de la part du client.
|
||||
|
||||
R : terminaison en attendant la réception totale de la requête du client
|
||||
C : terminaison en attendant la connexion vers le serveur
|
||||
H : terminaison en traitant les entêtes du serveur
|
||||
D : terminaison durant le transfert des données du serveur vers le client
|
||||
L : terminaison durant le transfert des dernières données du proxy vers
|
||||
le client, alors que le serveur a déjà fini.
|
||||
- : terminaison normale, après fin de transfert des données
|
||||
S : fermeture inattendue de la session TCP de la part du serveur, ou
|
||||
refus explicite de connexion de la part de ce dernier.
|
||||
|
||||
P : terminaison prématurée des sessions par le proxy, pour cause
|
||||
d'imposition d'une limite sur le nombre de connexions, pour cause
|
||||
de configuration (ex: filtre d'URL), ou parce qu'un contrôle de
|
||||
sécurité a détecté et bloqué une anomalie dans la réponse du
|
||||
serveur qui aurait pu causer une fuite d'informations (par exemple,
|
||||
un cookie cachable).
|
||||
|
||||
R : une ressource sur le proxy a été épuisée (mémoire, sockets, ports
|
||||
source, ...). Généralement, cela arrive au cours de l'établissement
|
||||
d'une connexion, et les logs système doivent contenir une copie de
|
||||
l'érreur précise.
|
||||
|
||||
I : une erreur interne a été identifiée par le proxy à la suite d'un
|
||||
auto-contrôle. Ceci ne doit JAMAIS arriver, et vous êtes encouragés
|
||||
à remonter n'importe quel log contenant ceci car il s'agira un bug.
|
||||
|
||||
c : le délai maximal d'attente du client a expiré (clitimeout).
|
||||
|
||||
s : le délai maximal d'attente du serveur a expiré (srvtimeout et contimeout)
|
||||
|
||||
- : terminaison normale de session.
|
||||
|
||||
- sur le second caractère, l'état d'avancement de la session TCP/HTTP lors de
|
||||
la fermeture :
|
||||
|
||||
R : attente d'une REQUETE HTTP complète de la part du client. Rien n'a
|
||||
été transmis au serveur.
|
||||
|
||||
C : attente de l'établissement d'une CONNEXION vers le serveur. Le
|
||||
serveur peut au plus avoir vu la tentative de connexion, mais
|
||||
aucune donnée n'a été échangée.
|
||||
|
||||
H : attente, réception ou traitement des en-têtes HTTP ("HEADERS").
|
||||
|
||||
D : transfert des DONNEES du serveur vers le client.
|
||||
|
||||
L : transfert des dernières ("LAST") données du proxy vers le client,
|
||||
alors que le serveur a déjà fini.
|
||||
|
||||
- : terminaison normale, après fin de transfert des données.
|
||||
|
||||
- le troisième caractère indique l'éventuelle identification d'un cookie de
|
||||
persistence (uniquement en mode HTTP) :
|
||||
|
||||
N : aucun cookie de persistence n'a été présenté.
|
||||
I : le client a présenté un cookie ne correspondant à aucun serveur
|
||||
connu.
|
||||
N : aucun cookie de persistence n'a été présenté. C'est généralement le
|
||||
cas sur les NOUVELLES connexions clients.
|
||||
|
||||
I : le client a présenté un cookie INVALIDE ne correspondant à aucun
|
||||
serveur connu. Ceci peut être dû à un changement de configuration
|
||||
récent, à des mélanges de noms de cookies entre sites HTTP/HTTPS,
|
||||
ou à une attaque.
|
||||
|
||||
D : le client a présenté un cookie correspondant à un serveur hors
|
||||
d'usage. Suivant l'option 'persist', il a été renvoyé vers un
|
||||
autre serveur ou a tout de même tenté de se connecter sur celui
|
||||
d'usage ("DOWN"). Suivant l'option 'persist', il a été renvoyé vers
|
||||
un autre serveur ou a tout de même tenté de se connecter sur celui
|
||||
correspondant au cookie.
|
||||
V : le client a présenté un cookie valide et a pu se connecter au
|
||||
|
||||
V : le client a présenté un cookie VALIDE et a pu se connecter au
|
||||
serveur correspondant.
|
||||
- : non appliquable
|
||||
|
||||
- le dernier caractère indique l'éventuel traitement effectué sur un cookie
|
||||
de persistence retrourné par le serveur (uniquement en mode HTTP) :
|
||||
- : non appliquable (pas de cookie positionné dans la configuration).
|
||||
|
||||
- le dernier caractère indique l'éventuel traitement effectué sur un cookie de
|
||||
persistence retrourné par le serveur (uniquement en mode HTTP) :
|
||||
|
||||
N : aucun cookie de persistance n'a été fourni par le serveur, et aucun
|
||||
n'a été inséré.
|
||||
|
||||
I : aucun cookie de persistance n'a été fourni par le serveur, et le
|
||||
proxy en a INSERE un.
|
||||
|
||||
N : aucun cookie de persistence n'a été fourni par le serveur.
|
||||
P : un cookie de persistence a été fourni par le serveur et transmis
|
||||
tel quel.
|
||||
I : aucun cookie n'a été fourni par le serveur, il a été inséré par le
|
||||
proxy.
|
||||
D : le cookie présenté par le serveur a été supprimé par le proxy pour
|
||||
tel quel ("PASSIF").
|
||||
|
||||
R : le cookie retourné par le serveur a été REECRIT par le proxy.
|
||||
|
||||
D : le cookie présenté par le serveur a été DETRUIT par le proxy pour
|
||||
ne pas être retourné au client.
|
||||
R : le cookie retourné par le serveur a été modifié par le proxy.
|
||||
|
||||
- : non appliquable
|
||||
|
||||
Le mot clé "capture" permet d'ajouter dans des logs HTTP des informations
|
||||
capturées dans les échanges. La version 1.1.17 supporte uniquement une capture
|
||||
de cookies client et serveur, ce qui permet dans bien des cas, de reconstituer
|
||||
la session d'un utilisateur. La syntaxe est la suivante :
|
||||
|
||||
La combinaison des deux premiers indicateurs fournit une grande quantitié
|
||||
d'informations sur ce qui se passait lorsque la session s'est terminée. Cela
|
||||
peut notamment aider à détecter une saturation de serveur, des troubles réseau,
|
||||
des épuisements de ressources système locales, des attaques, etc...
|
||||
|
||||
Les combinaisons d'indicateurs les plus fréquentes sont énumérées ici.
|
||||
|
||||
Indic Raison
|
||||
CR Le client a abandonné avant d'émettre une requête complète. Il est
|
||||
très probable que la requête ait été tapée à la main dans un client
|
||||
telnet et abortée trop tôt.
|
||||
|
||||
cR Le temps imparti au client a expiré avant réception d'une requête
|
||||
complète. Ceci est parfois causé par un paramètre TCP MSS trop élevé
|
||||
sur le client pour des réseaux PPPoE sur ADSL qui ne peuvent pas
|
||||
transporter des paquets entiers, ou par des clients qui énvoient des
|
||||
requêtes à la main et ne tapent pas assez vite.
|
||||
|
||||
SC Le serveur a explicitement refusé la connexion (le proxy a reçu un
|
||||
RST TCP ou un message ICMP en retour). Dans certains cas, cela peut
|
||||
être la couche réseau qui indique au proxy que le serveur n'est pas
|
||||
joignable (p.ex: pas de route, pas de réponse ARP en local, etc...)
|
||||
|
||||
sC La connexion au serveur n'a pas pu s'établir dans le temps imparti.
|
||||
|
||||
PC Le proxy a refusé d'établir une connexion au serveur parce que le
|
||||
nombre de connexions a atteint la limite 'maxconn' (global ou de
|
||||
l'instance). Le paramètre 'maxconn' de l'instance pourrait être
|
||||
augmenté, tout comme le paramètre 'maxconn' global.
|
||||
|
||||
RC Une ressource locale a été épuisée (mémoire, sockets, ports source),
|
||||
empêchant la connexion au serveur de s'établir. Les logs d'erreurs
|
||||
diront précisément ce qui manquait. Dans tous les cas, le seul remède
|
||||
consiste à affiner le paramétrage système.
|
||||
|
||||
cH Le temps imparti au client a expiré au cours d'une requête POST. Ceci
|
||||
est parfois causé par un paramètre TCP MSS trop élevé sur le client
|
||||
pour des réseaux PPPoE sur ADSL qui ne peuvent pas transporter des
|
||||
paquets entiers.
|
||||
|
||||
SH Le serveur a aborté brutalement alors qu'il devait envoyer ses
|
||||
en-têtes. En général, cela indique qu'il a crashé.
|
||||
|
||||
sH Le serveur n'a pas pu répondre durant le temps imparti, ce qui montre
|
||||
des transactions trop longues, probablement causées par un back-end
|
||||
saturé. Les seules solutions sont de corriger le problème sur
|
||||
l'application, d'accroître le paramètre 'srvtimeout' pour supporter
|
||||
des attentes plus longues au risque que les clients abandonnent à
|
||||
leur tour, ou bien d'ajouter des serveurs.
|
||||
|
||||
PR Le proxy a bloqué une requête du client, soit à cause d'une syntaxe
|
||||
HTTP invalide, auquel cas il a renvoyé une erreur HTTP 400 au client,
|
||||
soit à cause d'une requête validant un filtre d'interdiction, auquel
|
||||
cas le proxy a renvoyé une erreur HTTP 403.
|
||||
|
||||
PH Le proxy a bloqué la réponse du serveur parce qu'elle était invalide,
|
||||
incomplète, dangereuse ('cache control'), ou parce qu'elle validait
|
||||
un filtre de sécurité. Dans tous les cas, une erreur HTTP 502 est
|
||||
renvoyée au client.
|
||||
|
||||
cD Le client n'a pas lu de données pendant le temps qui lui était
|
||||
imparti. Ceci est souvent causé par des problèmes réseau côté client.
|
||||
|
||||
CD Le client a aborté sa connection de manière inattendue pendant le
|
||||
transfert des données. Ceci est provoqué soit par le crash d'un
|
||||
navigateur, ou par une session en HTTP keep-alive entre le serveur
|
||||
et le client terminée en premier par le client.
|
||||
|
||||
sD Le serveur n'a rien fait durant le temps imparti par le paramètre
|
||||
'srvtimeout'. Ceci est souvent causé par des timeouts trop courts
|
||||
sur des équipements de niveau 4 (firewalls, répartiteurs de charge)
|
||||
situés entre le proxy et le serveur.
|
||||
|
||||
4.2.5) Caractères non-imprimables
|
||||
---------------------------------
|
||||
Depuis la version 1.1.29, les caractères non-imprimables ne sont plus envoyés
|
||||
tels quels dans les lignes de logs, mais inscrits sous la forme de deux chiffres
|
||||
hexadécimaux, préfixés du caractère d'échappement '#'. Les seuls caractères
|
||||
dorénavant logués tels quels sont compris entre 32 et 126. Bien évidemment, le
|
||||
caractère d'échappement '#' est lui-même encodé afin de lever l'ambiguité. Il en
|
||||
est de même pour le caractère '"', ainsi que les caractères '{', '|' et '}' pour
|
||||
les en-têtes.
|
||||
|
||||
4.2.6) Capture d'en-têtes HTTP et de cookies
|
||||
--------------------------------------------
|
||||
La version 1.1.23 a apporté la capture des cookies, et la version 1.1.29 la
|
||||
capture d'en-têtes. Tout ceci est effectué en utilisant le mot-clé 'capture'.
|
||||
|
||||
Les captures de cookies facilitent le suivi et la reconstitution d'une session
|
||||
utilisateur. La syntaxe est la suivante :
|
||||
|
||||
capture cookie <préfixe_cookie> len <longueur_capture>
|
||||
|
||||
Ceci activera la capture de cookies à la fois dans les requêtes et dans les
|
||||
réponses. De cette manière, il devient facile de détecter lorsqu'un utilisateur
|
||||
bascule sur une nouvelle session par exemple, car le serveur lui réassignera un
|
||||
nouveau cookie.
|
||||
|
||||
Le premier cookie dont le nom commencera par <préfixe_cookie> sera capturé, et
|
||||
transmis sous la forme "NOM=valeur", sans toutefois, excéder <longueur_capture>
|
||||
caractères (64 au maximum). Lorsque le nom du cookie est fixe et connu, on peut
|
||||
@ -1297,68 +1545,17 @@ Exemples :
|
||||
Dans les logs, le champ précédant l'indicateur de complétude contient le cookie
|
||||
positionné par le serveur, précédé du cookie positionné par le client. Chacun
|
||||
de ces champs est remplacé par le signe "-" lorsqu'aucun cookie n'est fourni
|
||||
par le client ou le serveur.
|
||||
par le client ou le serveur, ou lorsque l'option est désactivée..
|
||||
|
||||
4.2.5) Exemples de logs
|
||||
-----------------------
|
||||
- haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57] relais-http Srv1 6559/7/147/6723 200 243 - - ---- "HEAD / HTTP/1.0"
|
||||
=> requête longue (6.5s) saisie à la main avec un client telnet. Le serveur a
|
||||
répondu en 147 ms et la session s'est terminée normalement ('----')
|
||||
|
||||
- haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/+30 200 +243 - - ---- "GET /image.iso HTTP/1.0"
|
||||
=> requête pour un long transfert. L'option 'logasap' était spécifiée donc le
|
||||
log a été généré juste avant le transfert de données. Le serveur a répondu
|
||||
en 14 ms, 243 octets d'entêtes ont été transférés au client, et le temps
|
||||
total entre l'accept() et le premier octet de donnée est de 30 ms.
|
||||
|
||||
- haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/30 502 243 - - PH-- "GET /cgi-bin/bug.cgi? HTTP/1.0"
|
||||
=> le proxy a bloqué une réponse du serveur soit à cause d'un filtre 'rspdeny'
|
||||
ou 'rspideny', soit parce qu'il a détecté un risque de fuite sensible
|
||||
d'informations risquant d'être cachées. Dans ce cas, la réponse est
|
||||
remplacée par '502 bad gateway'.
|
||||
|
||||
- haproxy[18113]: 127.0.0.1:34548 [15/Oct/2003:15:18:55] relais-http <NOSRV> -1/-1/-1/8490 -1 0 - - CR-- ""
|
||||
=> Le client n'a pas envoyé sa requête et a refermé la connexion lui-même
|
||||
('C---') au bout de 8.5s, alors que le relais attendait l'entête ('-R--').
|
||||
Aucune connexion n'a été envoyée vers le serveur.
|
||||
|
||||
- haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06] relais-http <NOSRV> -1/-1/-1/50001 408 0 - - cR-- ""
|
||||
=> Le client n'a pas envoyé sa requête et son time-out a expiré ('c---') au
|
||||
bout de 50s, alors que le relais attendait l'entête ('-R--'). Aucune
|
||||
connexion n'a été envoyée vers le serveur, mais le relais a tout de même
|
||||
pu renvoyer un message 408 au client.
|
||||
|
||||
- haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28] relais-tcp Srv1 0/5007 0 cD
|
||||
=> log en mode 'tcplog'. Expiration du time-out côté client ('c----') au bout
|
||||
de 5s.
|
||||
|
||||
- haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31] relais-http Srv1 3183/-1/-1/11215 503 0 - - SC-- "HEAD / HTTP/1.0"
|
||||
=> La requête client met 3s à entrer (peut-être un problème réseau), et la
|
||||
connexion ('SC--') vers le serveur échoue au bout de 4 tentatives de 2
|
||||
secondes (retries 3 dans la conf), puis un code 503 est retourné au
|
||||
client.
|
||||
|
||||
4.2.6) Caractères non-imprimables
|
||||
---------------------------------
|
||||
Depuis la version 1.1.29, les caractères non-imprimables ne sont plus envoyés
|
||||
tels quels dans les lignes de logs, mais inscrits sous la forme de deux
|
||||
chiffres hexadécimaux, préfixés du caractère d'échappement '#'. Les seuls
|
||||
caractères dorénavant logués tels quels sont compris entre 32 et 126. Bien
|
||||
évidemment, le caractère d'échappement '#' est lui-même encodé afin de lever
|
||||
l'ambiguité. Il en est de même pour le caractère '"', ainsi que les caractères
|
||||
'{', '|' et '}' pour les en-têtes.
|
||||
|
||||
4.2.7) Journalisation d'en-têtes
|
||||
--------------------------------
|
||||
Depuis la version 1.1.29, il est désormais possible de conserver des extraits
|
||||
d'en-têtes HTTP dans les logs. On peut aussi bien extraire des en-têtes de la
|
||||
requête que de la réponse. C'est particulièrement pratique pour savoir à quel
|
||||
serveur virtuel une requête s'adressait, pour connaitre la longueur des données
|
||||
émises lors d'un POST, ou encore loguer un identifiant unique de requête
|
||||
positionné en amont. Dans la réponse, on peut chercher également à conserver
|
||||
des informations relatives à la taille annoncée de la réponse, le
|
||||
fonctionnement attendu du cache, ou encore la localisation d'un objet en cas
|
||||
de redirection. La syntaxe est la suivante :
|
||||
Les captures d'en-têtes ont un rôle complètement différent. Elles sont utiles
|
||||
pour suivre un identifiant de requête globalement unique positionné par un
|
||||
autre proxy en amont, pour journaliser les noms de serveurs virtuels, les types
|
||||
de clients web, la longueur des POST, les 'referrers', etc. Dans la réponse, on
|
||||
peut chercher des informations relatives à la longueur annoncée de la réponse,
|
||||
le fonctionnement attendu du cache, ou encore la localisation d'un objet en cas
|
||||
de redirection. Tout comme pour les captures de cookies, il est possible
|
||||
d'inclure les en-têtes de requêtes et de réponse simultanément. La syntaxe est
|
||||
la suivante :
|
||||
|
||||
capture request header <nom> len <longueur max>
|
||||
capture response header <nom> len <longueur max>
|
||||
@ -1377,13 +1574,12 @@ Exemples:
|
||||
# noter l'URL de redirection
|
||||
capture response header Location len 20
|
||||
|
||||
Les en-têtes non trouvés sont logués à vide, et si un en-tête apparait
|
||||
plusieurs fois, seule la dernière occurence sera conservée. Les en-têtes de
|
||||
requête sont regroupés entre deux accolades '{' et '}' dans l'ordre de leur
|
||||
déclaration, et chacun séparés par une barre verticale '|', sans aucun espace.
|
||||
Les en-têtes de réponse sont présentés de la même manière, mais après un
|
||||
espace suivant le bloc d'en-tête de requête. Le tout précède la requête HTTP.
|
||||
Exemple :
|
||||
Les en-têtes non trouvés sont logués à vide, et si un en-tête apparait plusieurs
|
||||
fois, seule la dernière occurence sera conservée. Les en-têtes de requête sont
|
||||
regroupés entre deux accolades '{' et '}' dans l'ordre de leur déclaration, et
|
||||
chacun séparés par une barre verticale '|', sans aucun espace. Les en-têtes de
|
||||
réponse sont présentés de la même manière, mais après un espace suivant le bloc
|
||||
d'en-tête de requête. Le tout précède la requête HTTP. Exemple :
|
||||
|
||||
Config:
|
||||
|
||||
@ -1402,7 +1598,49 @@ Aug 9 20:26:09 localhost haproxy[2022]: 127.0.0.1:34014 [09/Aug/2004:20:26:09]
|
||||
Aug 9 20:30:46 localhost haproxy[2022]: 127.0.0.1:34020 [09/Aug/2004:20:30:46] relais-http netcache 0/0/182/+182 200 +279 - - ---- {w.ods.org||} {Formilux/0.1.8|3495|||} "GET http://w.ods.org/sytadin.html HTTP/1.1"
|
||||
Aug 9 20:30:46 localhost haproxy[2022]: 127.0.0.1:34028 [09/Aug/2004:20:30:46] relais-http netcache 0/2/126/+128 200 +223 - - ---- {www.infotrafic.com||http://w.ods.org/syt} {Apache/2.0.40 (Red H|9068|||} "GET http://www.infotrafic.com/images/live/cartesidf/grandes/idf_ne.png HTTP/1.1"
|
||||
|
||||
4.3) Modification des entêtes HTTP
|
||||
4.2.7) Exemples de logs
|
||||
-----------------------
|
||||
- haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57] relais-http Srv1 6559/7/147/6723 200 243 - - ---- 3/5 "HEAD / HTTP/1.0"
|
||||
=> requête longue (6.5s) saisie à la main avec un client telnet. Le serveur a
|
||||
répondu en 147 ms et la session s'est terminée normalement ('----')
|
||||
|
||||
- haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/+30 200 +243 - - ---- 3/3 "GET /image.iso HTTP/1.0"
|
||||
=> requête pour un long transfert. L'option 'logasap' était spécifiée donc le
|
||||
log a été généré juste avant le transfert de données. Le serveur a répondu
|
||||
en 14 ms, 243 octets d'en-têtes ont été transférés au client, et le temps
|
||||
total entre l'accept() et le premier octet de donnée est de 30 ms.
|
||||
|
||||
- haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/30 502 243 - - PH-- 2/3 "GET /cgi-bin/bug.cgi? HTTP/1.0"
|
||||
=> le proxy a bloqué une réponse du serveur soit à cause d'un filtre 'rspdeny'
|
||||
ou 'rspideny', soit parce qu'il a détecté un risque de fuite sensible
|
||||
d'informations risquant d'être cachées. Dans ce cas, la réponse est
|
||||
remplacée par '502 bad gateway'.
|
||||
|
||||
- haproxy[18113]: 127.0.0.1:34548 [15/Oct/2003:15:18:55] relais-http <NOSRV> -1/-1/-1/8490 -1 0 - - CR-- 2/2 ""
|
||||
=> Le client n'a pas envoyé sa requête et a refermé la connexion lui-même
|
||||
('C---') au bout de 8.5s, alors que le relais attendait l'en-tête ('-R--').
|
||||
Aucune connexion n'a été envoyée vers le serveur.
|
||||
|
||||
- haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06] relais-http <NOSRV> -1/-1/-1/50001 408 0 - - cR-- 2/2 ""
|
||||
=> Le client n'a pas envoyé sa requête et son time-out a expiré ('c---') au
|
||||
bout de 50s, alors que le relais attendait l'en-tête ('-R--'). Aucune
|
||||
connexion n'a été envoyée vers le serveur, mais le relais a tout de même
|
||||
pu renvoyer un message 408 au client.
|
||||
|
||||
- haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28] relais-tcp Srv1 0/5007 0 cD
|
||||
=> log en mode 'tcplog'. Expiration du time-out côté client ('cD') au bout de
|
||||
5s.
|
||||
|
||||
- haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31] relais-http Srv1 3183/-1/-1/11215 503 0 - - SC-- 202/205 "HEAD / HTTP/1.0"
|
||||
=> La requête client met 3s à entrer (peut-être un problème réseau), et la
|
||||
connexion ('SC--') vers le serveur échoue au bout de 4 tentatives de 2
|
||||
secondes (retries 3 dans la conf), puis un code 503 est retourné au client.
|
||||
Il y avait 202 connexions sur cette instance, et 205 sur l'ensemble des
|
||||
instances pour ce processus. Il est possible que le serveur ait refusé la
|
||||
connexion parce qu'il y en avait déjà trop d'établies.
|
||||
|
||||
|
||||
4.3) Modification des en-têtes HTTP
|
||||
----------------------------------
|
||||
En mode HTTP uniquement, il est possible de remplacer certains en-têtes dans la
|
||||
requête et/ou la réponse à partir d'expressions régulières. Il est également
|
||||
@ -1418,11 +1656,11 @@ La syntaxe est :
|
||||
reqirep <search> <replace> idem sans distinction majuscules/minuscules
|
||||
reqdel <search> pour supprimer un en-tête dans la requête
|
||||
reqidel <search> idem sans distinction majuscules/minuscules
|
||||
reqallow <search> autoriser la requête si un entête valide <search>
|
||||
reqallow <search> autoriser la requête si un en-tête valide <search>
|
||||
reqiallow <search> idem sans distinction majuscules/minuscules
|
||||
reqdeny <search> interdire la requête si un entête valide <search>
|
||||
reqdeny <search> interdire la requête si un en-tête valide <search>
|
||||
reqideny <search> idem sans distinction majuscules/minuscules
|
||||
reqpass <search> inhibe ces actions sur les entêtes validant <search>
|
||||
reqpass <search> inhibe ces actions sur les en-têtes validant <search>
|
||||
reqipass <search> idem sans distinction majuscules/minuscules
|
||||
|
||||
rspadd <string> pour ajouter un en-tête dans la réponse
|
||||
@ -1431,7 +1669,7 @@ La syntaxe est :
|
||||
rspdel <search> pour supprimer un en-tête dans la réponse
|
||||
rspidel <search> idem sans distinction majuscules/minuscules
|
||||
rspdeny <search> remplace la réponse par un HTTP 502 si un
|
||||
entête valide <search>
|
||||
en-tête valide <search>
|
||||
rspideny <search> idem sans distinction majuscules/minuscules
|
||||
|
||||
|
||||
@ -1472,7 +1710,7 @@ Remarques :
|
||||
une requête ou une réponse est limité à 4096 depuis la version 1.1.5 (cette
|
||||
limite était à 256 auparavant). Cette valeur est modifiable dans le code.
|
||||
Pour un usage temporaire, on peut gagner de la place en supprimant quelques
|
||||
entêtes inutiles avant les ajouts.
|
||||
en-têtes inutiles avant les ajouts.
|
||||
- une requête bloquée produira une réponse "HTTP 403 forbidden" tandis qu'une
|
||||
réponse bloquée produira une réponse "HTTP 502 Bad gateway".
|
||||
|
||||
@ -1522,7 +1760,7 @@ De plus, l'option 'forwardfor' ajoute l'adresse IP du client dans un champ
|
||||
connaître l'adresse IP du client initial.
|
||||
|
||||
Enfin, l'option 'httpclose' apparue dans la version 1.1.28/1.2.1 supprime tout
|
||||
entête de type 'Connection:' et ajoute 'Connection: close' dans les deux sens.
|
||||
en-tête de type 'Connection:' et ajoute 'Connection: close' dans les deux sens.
|
||||
Ceci simplifie la désactivation du keep-alive HTTP par rapport à l'ancienne
|
||||
méthode impliquant 4 règles.
|
||||
|
||||
@ -1574,30 +1812,30 @@ puisse corriger le nom du cookie dans toutes les futures requ
|
||||
4.5) Protection contre les fuites d'informations du serveur
|
||||
-----------------------------------------------------------
|
||||
Dans les versions 1.1.28 et 1.2.1, une nouvelle option 'checkcache' a été
|
||||
créée. Elle sert à inspecter minutieusement les entêtes 'Cache-control',
|
||||
créée. Elle sert à inspecter minutieusement les en-têtes 'Cache-control',
|
||||
'Pragma', et 'Set-cookie' dans les réponses serveur pour déterminer s'il y a
|
||||
un risque de cacher un cookie sur un proxy côté client. Quand cette option est
|
||||
activée, les seules réponses qui peuvent être retournées au client sont :
|
||||
- toutes celles qui n'ont pas d'entête 'Set-cookie' ;
|
||||
- toutes celles qui n'ont pas d'en-tête 'Set-cookie' ;
|
||||
- toutes celles qui ont un code de retour autre que 200, 203, 206, 300, 301,
|
||||
410, sauf si le serveur a positionné un entête 'Cache-control: public' ;
|
||||
410, sauf si le serveur a positionné un en-tête 'Cache-control: public' ;
|
||||
- celles qui font suite à une requête POST, sauf si le serveur a positionné
|
||||
un entête 'Cache-control: public' ;
|
||||
- celles qui ont un entête 'Pragma: no-cache' ;
|
||||
- celles qui ont un entête 'Cache-control: private' ;
|
||||
- celles qui ont un entête 'Cache-control: no-store' ;
|
||||
- celles qui ont un entête 'Cache-control: max-age=0' ;
|
||||
- celles qui ont un entête 'Cache-control: s-maxage=0' ;
|
||||
- celles qui ont un entête 'Cache-control: no-cache' ;
|
||||
- celles qui ont un entête 'Cache-control: no-cache="set-cookie"' ;
|
||||
- celles qui ont un entête 'Cache-control: no-cache="set-cookie,'
|
||||
un en-tête 'Cache-control: public' ;
|
||||
- celles qui ont un en-tête 'Pragma: no-cache' ;
|
||||
- celles qui ont un en-tête 'Cache-control: private' ;
|
||||
- celles qui ont un en-tête 'Cache-control: no-store' ;
|
||||
- celles qui ont un en-tête 'Cache-control: max-age=0' ;
|
||||
- celles qui ont un en-tête 'Cache-control: s-maxage=0' ;
|
||||
- celles qui ont un en-tête 'Cache-control: no-cache' ;
|
||||
- celles qui ont un en-tête 'Cache-control: no-cache="set-cookie"' ;
|
||||
- celles qui ont un en-tête 'Cache-control: no-cache="set-cookie,'
|
||||
(autorisant d'autres champs après set-cookie).
|
||||
|
||||
Si une réponse ne respecte pas ces pré-requis, alors elle sera bloquée de la
|
||||
même manière que s'il s'agissait d'un filtre 'rspdeny', avec en retour un
|
||||
message "HTTP 502 bad gateway". L'état de session montre "PH--" ce qui veut
|
||||
dire que c'est le proxy qui a bloqué la réponse durant le traitement des
|
||||
entêtes. De plus, un message d'alerte sera envoyé dans les logs de sorte que
|
||||
en-têtes. De plus, un message d'alerte sera envoyé dans les logs de sorte que
|
||||
l'administrateur sache qu'il y a une action correctrice à entreprendre.
|
||||
|
||||
4.6) Personalisation des erreurs
|
||||
@ -1642,8 +1880,8 @@ dans le champ Location avec la m
|
||||
navigateurs antérieurs à HTTP/1.1 ne connaissent pas ce code de retour. De
|
||||
plus, la plupart des navigateurs se comportent déjà avec le code 302 comme ils
|
||||
devraient le faire avec le 303. Donc, dans le but de laisser le choix à
|
||||
l'utilisateur, la version 1.2.5 apporte deux nouvelles commandes visant à
|
||||
remplacer 'errorloc' : 'errorloc302' et 'errorloc303'.
|
||||
l'utilisateur, les versions 1.1.31 et 1.2.5 apportent deux nouvelles commandes
|
||||
visant à remplacer 'errorloc' : 'errorloc302' et 'errorloc303'.
|
||||
|
||||
Leur usage non ambigü est recommandé à la place de la commande 'errorloc' (qui
|
||||
utilise toujours 302). Dans le doute, préférez l'utilisation de 'errorloc303'
|
||||
@ -1766,7 +2004,7 @@ echo 300 > /proc/sys/net/ipv4/tcp_keepalive_time
|
||||
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
|
||||
echo 0 > /proc/sys/net/ipv4/tcp_timestamps
|
||||
echo 0 > /proc/sys/net/ipv4/tcp_ecn
|
||||
echo 0 > /proc/sys/net/ipv4/tcp_sack
|
||||
echo 1 > /proc/sys/net/ipv4/tcp_sack
|
||||
echo 0 > /proc/sys/net/ipv4/tcp_dsack
|
||||
|
||||
# auto-tuned on 2.4
|
||||
|
17
haproxy.c
17
haproxy.c
@ -77,7 +77,7 @@
|
||||
#include "include/appsession.h"
|
||||
|
||||
#define HAPROXY_VERSION "1.2.6"
|
||||
#define HAPROXY_DATE "2005/07/06"
|
||||
#define HAPROXY_DATE "2005/08/07"
|
||||
|
||||
/* this is for libc5 for example */
|
||||
#ifndef TCP_NODELAY
|
||||
@ -1651,7 +1651,7 @@ static int maintain_proxies(void);
|
||||
/* this either returns the sockname or the original destination address. Code
|
||||
* inspired from Patrick Schaaf's example of nf_getsockname() implementation.
|
||||
*/
|
||||
static int get_original_dst(int fd, struct sockaddr_in *sa, int *salen) {
|
||||
static int get_original_dst(int fd, struct sockaddr_in *sa, socklen_t *salen) {
|
||||
#if defined(TPROXY) && defined(SO_ORIGINAL_DST)
|
||||
return getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, (void *)sa, salen);
|
||||
#else
|
||||
@ -1767,7 +1767,7 @@ int connect_server(struct session *s) {
|
||||
}
|
||||
else if (s->proxy->options & PR_O_TRANSP) {
|
||||
/* in transparent mode, use the original dest addr if no dispatch specified */
|
||||
int salen = sizeof(struct sockaddr_in);
|
||||
socklen_t salen = sizeof(struct sockaddr_in);
|
||||
if (get_original_dst(s->cli_fd, &s->srv_addr, &salen) == -1) {
|
||||
qfprintf(stderr, "Cannot get original server address.\n");
|
||||
return SN_ERR_INTERNAL;
|
||||
@ -1778,7 +1778,7 @@ int connect_server(struct session *s) {
|
||||
* the port the client connected to with an offset. */
|
||||
if (s->srv != NULL && s->srv->state & SRV_MAPPORTS) {
|
||||
struct sockaddr_in sockname;
|
||||
int namelen;
|
||||
socklen_t namelen;
|
||||
|
||||
namelen = sizeof(sockname);
|
||||
if (get_original_dst(s->cli_fd, (struct sockaddr_in *)&sockname, &namelen) == -1)
|
||||
@ -2441,7 +2441,7 @@ int event_accept(int fd) {
|
||||
|
||||
while (p->nbconn < p->maxconn) {
|
||||
struct sockaddr_storage addr;
|
||||
int laddr = sizeof(addr);
|
||||
socklen_t laddr = sizeof(addr);
|
||||
if ((cfd = accept(fd, (struct sockaddr *)&addr, &laddr)) == -1) {
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
@ -2589,7 +2589,7 @@ int event_accept(int fd) {
|
||||
if ((p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP)
|
||||
&& (p->logfac1 >= 0 || p->logfac2 >= 0)) {
|
||||
struct sockaddr_storage sockname;
|
||||
int namelen;
|
||||
socklen_t namelen;
|
||||
|
||||
namelen = sizeof(sockname);
|
||||
if (addr.ss_family != AF_INET ||
|
||||
@ -2630,7 +2630,7 @@ int event_accept(int fd) {
|
||||
|
||||
if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
|
||||
struct sockaddr_in sockname;
|
||||
int namelen;
|
||||
socklen_t namelen;
|
||||
int len;
|
||||
namelen = sizeof(sockname);
|
||||
if (addr.ss_family != AF_INET ||
|
||||
@ -2754,7 +2754,8 @@ int event_srv_chk_w(int fd) {
|
||||
struct task *t = fdtab[fd].owner;
|
||||
struct server *s = t->context;
|
||||
|
||||
int skerr, lskerr;
|
||||
int skerr;
|
||||
socklen_t lskerr;
|
||||
lskerr = sizeof(skerr);
|
||||
getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
|
||||
/* in case of TCP only, this tells us if the connection succeeded */
|
||||
|
Loading…
Reference in New Issue
Block a user