mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-10 16:00:08 +00:00
* released 1.2.1 (1.1.28)
* added the '-V' command line option to verbosely report errors even though the -q or 'quiet' options are specified. This is useful with '-c'. * added a Red Hat init script and a .spec from Simon Matter <simon.matter@invoca.ch> * added 'rspdeny' and 'rspideny' to block certain responses to avoid sensible information leak from servers. * more examples added into the configuration
This commit is contained in:
parent
97f58576eb
commit
982249e9e7
16
CHANGELOG
16
CHANGELOG
@ -1,13 +1,19 @@
|
||||
ChangeLog :
|
||||
===========
|
||||
2004/06/06 : 1.2.1 (1.1.28)
|
||||
- added the '-V' command line option to verbosely report errors even though
|
||||
the -q or 'quiet' options are specified. This is useful with '-c'.
|
||||
- added a Red Hat init script and a .spec from Simon Matter <simon.matter@invoca.ch>
|
||||
|
||||
2004/06/05 : 1.2.1 (1.1.28)
|
||||
- added the "logasap" option which produces a log without waiting for
|
||||
the data to be transferred from the server to the client.
|
||||
- added the "httpclose" option which removes any "connection:" header
|
||||
and adds "Connection: close" in both direction.
|
||||
2004/06/05 :
|
||||
- added the "logasap" option which produces a log without waiting for the data
|
||||
to be transferred from the server to the client.
|
||||
- added the "httpclose" option which removes any "connection:" header and adds
|
||||
"Connection: close" in both direction.
|
||||
- added the 'checkcache' option which blocks cacheable responses containing
|
||||
dangerous headers, such as 'set-cookie'.
|
||||
- added 'rspdeny' and 'rspideny' to block certain responses to avoid sensible
|
||||
information leak from servers.
|
||||
|
||||
2004/04/18 :
|
||||
- send an EMERG log when no server is available for a given proxy
|
||||
|
@ -1,9 +1,9 @@
|
||||
|
||||
H A - P r o x y
|
||||
---------------
|
||||
version 1.1.27
|
||||
version 1.2.1
|
||||
willy tarreau
|
||||
2003/10/27
|
||||
2004/06/06
|
||||
|
||||
============
|
||||
| Abstract |
|
||||
@ -35,6 +35,10 @@ There are only a few command line options :
|
||||
-N <high limit for the per-proxy number of simultaneous connections>
|
||||
-d starts in foregreound with debugging mode enabled
|
||||
-D starts in daemon mode
|
||||
-q disable messages on output
|
||||
-V displays messages on output even when -q or 'quiet' are specified.
|
||||
-c only checks config file and exits with code 0 if no error was found, or
|
||||
exits with code 1 if a syntax error was found.
|
||||
-p <pidfile> asks the process to write down each of its children's
|
||||
pids to this file in daemon mode.
|
||||
-s shows statistics (only if compiled in)
|
||||
@ -219,7 +223,7 @@ reasons.
|
||||
1.5) Increasing the overall processing power
|
||||
--------------------------------------------
|
||||
On multi-processor systems, it may seem to be a shame to use only one processor,
|
||||
eventhough the load needed to saturate a recent processor are far above common
|
||||
eventhough the load needed to saturate a recent processor is far above common
|
||||
usage. Anyway, for very specific needs, the proxy can start several processes
|
||||
between which the operating system will spread the incoming connections. The
|
||||
number of processes is controlled by the 'nbproc' parameter in the 'global'
|
||||
@ -379,7 +383,7 @@ Example :
|
||||
The 'maxconn' parameter allows a proxy to refuse connections above a certain
|
||||
amount of simultaneous ones. When the limit is reached, it simply stops
|
||||
listening, but the system may still be accepting them because of the back log
|
||||
queue. These connections will be processed further when other ones have freed
|
||||
queue. These connections will be processed later when other ones have freed
|
||||
some slots. This provides a serialization effect which helps very fragile
|
||||
servers resist to high loads. Se further for system limitations.
|
||||
|
||||
@ -733,6 +737,11 @@ The servers status will be dumped into the logs at the 'notice' level, as well
|
||||
as on <stderr> if not closed. For this reason, it's always a good idea to have
|
||||
one local log server at the 'notice' level.
|
||||
|
||||
Since version 1.1.28 and 1.2.1, if an instance loses all its servers, an
|
||||
emergency mesasge will be sent in the logs to inform the administator that an
|
||||
immediate action must be taken.
|
||||
|
||||
|
||||
Examples :
|
||||
----------
|
||||
# same setup as in paragraph 3) with TCP monitoring
|
||||
@ -917,6 +926,15 @@ 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 :
|
||||
---------
|
||||
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 --
|
||||
|
||||
Another option, 'httplog', provides more detailed information about HTTP
|
||||
contents, such as the request and some cookies. In the event where an external
|
||||
component would establish frequent connections to check the service, logs may be
|
||||
@ -932,6 +950,34 @@ Example :
|
||||
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"
|
||||
|
||||
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
|
||||
new option 'logasap' has been introduced in 1.1.28/1.2.1. When specified, the
|
||||
proxy will log as soon as possible, just before data transfer begins. This means
|
||||
that in case of TCP, it will still log the connection status to the server, and
|
||||
in case of HTTP, it will log just after processing the server headers. In this
|
||||
case, the number of bytes reported is the number of header bytes sent to the
|
||||
client.
|
||||
|
||||
In order to avoid confusion with normal logs, the total time field and the
|
||||
number of bytes are prefixed with a '+' sign which mean that real numbers are
|
||||
certainly bigger.
|
||||
|
||||
Example :
|
||||
---------
|
||||
|
||||
listen http_proxy 0.0.0.0:80
|
||||
mode http
|
||||
option httplog
|
||||
option dontlognull
|
||||
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"
|
||||
|
||||
|
||||
4.2.3) Timing events
|
||||
--------------------
|
||||
Timers provide a great help in trouble shooting network problems. All values
|
||||
@ -956,8 +1002,10 @@ reported under the form 'Tq/Tc/Tr/Tt' :
|
||||
means that the last the response header (empty line) was never seen.
|
||||
|
||||
- Tt: total session duration time, between the moment the proxy accepted it
|
||||
and the moment both ends were closed. From this one, we can deduce Td,
|
||||
the data transmission time, by substracting other timers when valid :
|
||||
and the moment both ends were closed. The exception is when the 'logasap'
|
||||
option is specified. In this case, it only equals (Tq+Tc+Tr), and is
|
||||
prefixed with a '+' sign. From this field, we can deduce Td, the data
|
||||
transmission time, by substracting other timers when valid :
|
||||
|
||||
Td = Tt - (Tq + Tc + Tr)
|
||||
|
||||
@ -1005,7 +1053,9 @@ TCP and HTTP logs provide a session completion indicator. It's a 4-characters
|
||||
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, or because a DENY filter was matched.
|
||||
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.
|
||||
- : normal session completion.
|
||||
@ -1014,7 +1064,7 @@ TCP and HTTP logs provide a session completion indicator. It's a 4-characters
|
||||
|
||||
R : waiting for complete REQUEST from the client
|
||||
C : waiting for CONNECTION to establish on the server
|
||||
H : waiting for complete HEADERS from 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.
|
||||
@ -1073,6 +1123,18 @@ client. Each of these field is replaced with '-' when no cookie was seen.
|
||||
=> 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--').
|
||||
@ -1122,6 +1184,8 @@ The syntax is :
|
||||
rspirep <search> <replace> same, but ignoring the case
|
||||
rspdel <search> to delete the response
|
||||
rspidel <search> same, but ignoring the case
|
||||
rspdeny <search> replaces a response with a HTTP 502 if a header matches <search>
|
||||
rspideny <search> same, but ignoring the case
|
||||
|
||||
|
||||
<search> is a POSIX regular expression (regex) which supports grouping through
|
||||
@ -1160,6 +1224,9 @@ Notes :
|
||||
value is easy to modify in the code if needed (#define). If it is too short
|
||||
on occasional uses, it is possible to gain some space by removing some
|
||||
useless headers before adding new ones.
|
||||
- a denied request will generate an "HTTP 403 forbidden" response, while a
|
||||
denied response will generate an "HTTP 502 Bad gateway" response.
|
||||
|
||||
|
||||
Examples :
|
||||
----------
|
||||
@ -1195,20 +1262,21 @@ Examples :
|
||||
reqideny ^[^:\ ]*\
|
||||
|
||||
# force connection:close, thus disabling HTTP keep-alive
|
||||
reqidel ^Connection:
|
||||
rspidel ^Connection:
|
||||
reqadd Connection:\ close
|
||||
rspadd Connection:\ close
|
||||
option httpclose
|
||||
|
||||
# change the server name
|
||||
rspidel ^Server:\
|
||||
rspadd Server:\ Formilux/0.1.8
|
||||
|
||||
|
||||
Last, the 'forwardfor' option creates an HTTP 'X-Forwarded-For' header which
|
||||
Also, the 'forwardfor' option creates an HTTP 'X-Forwarded-For' header which
|
||||
contains the client's IP address. This is useful to let the final web server
|
||||
know what the client address was (eg for statistics on domains).
|
||||
|
||||
Last, the 'httpclose' option removes any 'Connection' header both ways, and
|
||||
adds a 'Connection: close' header in each direction. This makes it easier to
|
||||
disable HTTP keep-alive than the previous 4-rules block..
|
||||
|
||||
Example :
|
||||
---------
|
||||
listen http_proxy 0.0.0.0:80
|
||||
@ -1217,10 +1285,10 @@ Example :
|
||||
option httplog
|
||||
option dontlognull
|
||||
option forwardfor
|
||||
option httpclose
|
||||
|
||||
4.4) Load balancing with persistence
|
||||
------------------------------------
|
||||
|
||||
Combining cookie insertion with internal load balancing allows to transparently
|
||||
bring persistence to applications. The principle is quite simple :
|
||||
- assign a cookie value to each server
|
||||
@ -1239,9 +1307,35 @@ Example :
|
||||
server 192.168.1.1:80 cookie server01 check
|
||||
server 192.168.1.2:80 cookie server02 check
|
||||
|
||||
4.5) Customizing errors
|
||||
-----------------------
|
||||
4.5) Protection against information leak from the servers
|
||||
---------------------------------------------------------
|
||||
In versions 1.1.28/1.2.1, a new option 'checkcache' was created. It carefully
|
||||
checks 'Cache-control', 'Pragma' and 'Set-cookie' headers in server response
|
||||
to check if there's a risk of caching a cookie on a client-side proxy. When this
|
||||
option is enabled, the only responses which can be delivered to the client are :
|
||||
- all those without 'Set-Cookie' header ;
|
||||
- all those with a return code other than 200, 203, 206, 300, 301, 410,
|
||||
provided that the server has not set a 'Cache-control: public' header ;
|
||||
- all those that come from a POST request, provided that the server has not
|
||||
set a 'Cache-Control: public' header ;
|
||||
- those with a 'Pragma: no-cache' header
|
||||
- those with a 'Cache-control: private' header
|
||||
- those with a 'Cache-control: no-store' header
|
||||
- those with a 'Cache-control: max-age=0' header
|
||||
- those with a 'Cache-control: s-maxage=0' header
|
||||
- those with a 'Cache-control: no-cache' header
|
||||
- those with a 'Cache-control: no-cache="set-cookie"' header
|
||||
- those with a 'Cache-control: no-cache="set-cookie,' header
|
||||
(allowing other fields after set-cookie)
|
||||
|
||||
If a response doesn't respect these requirements, then it will be blocked just
|
||||
as if it was from an 'rspdeny' filter, with an "HTTP 502 bad gateway". The
|
||||
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 :
|
||||
- invalid or too long request => HTTP 400
|
||||
- request not completely sent in time => HTTP 408
|
||||
@ -1275,9 +1369,8 @@ Example :
|
||||
errorloc 503 http://192.168.114.58/error50x.html
|
||||
errorloc 504 http://192.168.114.58/error50x.html
|
||||
|
||||
4.6) Modifying default values
|
||||
4.7) Modifying default values
|
||||
-----------------------------
|
||||
|
||||
Version 1.1.22 introduced the notion of default values, which eliminates the
|
||||
pain of often repeating common parameters between many instances, such as
|
||||
logs, timeouts, modes, etc...
|
||||
@ -1290,7 +1383,7 @@ used for this section. The 'defaults' section uses the same syntax as the
|
||||
everything on its command line, so that fake instance names can be specified
|
||||
there for better clarity.
|
||||
|
||||
In version 1.1.23, only those parameters can be preset in the 'default'
|
||||
In version 1.1.28/1.2.1, only those parameters can be preset in the 'default'
|
||||
section :
|
||||
- log (the first and second one)
|
||||
- mode { tcp, http, health }
|
||||
@ -1298,8 +1391,8 @@ section :
|
||||
- disabled (to disable every further instances)
|
||||
- enabled (to enable every further instances, this is the default)
|
||||
- contimeout, clitimeout, srvtimeout, grace, retries, maxconn
|
||||
- option { redispatch, transparent, keepalive, forwardfor, httplog,
|
||||
dontlognull, persist, httpchk }
|
||||
- option { redispatch, transparent, keepalive, forwardfor, logasap, httpclose,
|
||||
checkcache, httplog, tcplog, dontlognull, persist, httpchk }
|
||||
- redispatch, redisp, transparent, source { addr:port }
|
||||
- cookie, capture
|
||||
- errorloc
|
||||
|
@ -1,9 +1,9 @@
|
||||
|
||||
H A - P r o x y
|
||||
---------------
|
||||
version 1.1.27
|
||||
version 1.2.1
|
||||
willy tarreau
|
||||
2003/10/27
|
||||
2004/06/06
|
||||
|
||||
================
|
||||
| Introduction |
|
||||
@ -37,6 +37,12 @@ Les options de lancement sont peu nombreuses :
|
||||
-N <nombre maximal de connexions simultanées par proxy>
|
||||
-d active le mode debug
|
||||
-D passe en daemon
|
||||
-q désactive l'affichage de messages sur la sortie standard.
|
||||
-V affiche les messages sur la sortie standard, même si -q ou 'quiet' sont
|
||||
spécifiés.
|
||||
-c vérifie le fichier de configuration puis quitte avec un code de retour 0
|
||||
si aucune erreur n'a été trouvée, ou 1 si une erreur de syntaxe a été
|
||||
détectée.
|
||||
-p <fichier> indique au processus père qu'il doit écrire les PIDs de ses
|
||||
fils dans ce fichier en mode démon.
|
||||
-s affiche les statistiques (si option compilée)
|
||||
@ -754,6 +760,10 @@ les logs en niveau "notice", ainsi que sur la sortie d'erreurs si elle est
|
||||
active. C'est une bonne raison pour avoir au moins un serveur de logs local en
|
||||
niveau notice.
|
||||
|
||||
Depuis la version 1.1.18 (et 1.2.1), un message d'urgence est envoyé dans les
|
||||
logs en niveau 'emerg' si tous les serveurs d'une même instance sont tombés,
|
||||
afin de notifier l'administrateur qu'il faut prendre une action immédiate.
|
||||
|
||||
Exemples :
|
||||
----------
|
||||
# conf du paragraphe 3) avec surveillance TCP
|
||||
@ -937,6 +947,15 @@ 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 :
|
||||
---------
|
||||
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 --
|
||||
|
||||
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
|
||||
surveillance effectuant des connexions et déconnexions fréquentes, polluerait
|
||||
@ -952,6 +971,35 @@ Exemple :
|
||||
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"
|
||||
|
||||
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.
|
||||
Pour pallier à ce problème, une nouvelle option 'logasap' a été introduite dans
|
||||
la version 1.1.28 (1.2.1). Lorsqu'elle est activée, le proxy loguera le plus 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.
|
||||
|
||||
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.
|
||||
|
||||
Exemple :
|
||||
---------
|
||||
|
||||
listen http_proxy 0.0.0.0:80
|
||||
mode http
|
||||
option httplog
|
||||
option dontlognull
|
||||
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"
|
||||
|
||||
|
||||
4.2.3) Chronométrage des événements
|
||||
-----------------------------------
|
||||
Pour déceler des problèmes réseau, les mesures du temps écoulé entre certains
|
||||
@ -980,8 +1028,11 @@ la forme Tq/Tc/Tr/Tt :
|
||||
|
||||
- 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é
|
||||
refermée aux deux extrémités (client et serveur). On peut donc en déduire
|
||||
Td, le temps de transfert des données, en excluant les autres temps :
|
||||
refermée aux deux extrémités (client et serveur). La signification change
|
||||
un peu si l'option 'logasap' est présente. Dans ce cas, le temps correspond
|
||||
uniquement à (Tq + Tc + Tr), et se trouve préfixé d'un signe '+'. On peut
|
||||
donc déduire Td, le temps de transfert des données, en excluant les autres
|
||||
temps :
|
||||
|
||||
Td = Tt - (Tq + Tc + Tr)
|
||||
|
||||
@ -1032,7 +1083,9 @@ C'est un champ de 4 caract
|
||||
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 ou de configuration (ex: filtre d'URL)
|
||||
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.
|
||||
@ -1042,7 +1095,7 @@ C'est un champ de 4 caract
|
||||
|
||||
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 attendant la réception totale des entêtes du 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.
|
||||
@ -1107,6 +1160,18 @@ client ou le serveur.
|
||||
=> 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--').
|
||||
@ -1155,6 +1220,9 @@ La syntaxe est :
|
||||
rspirep <search> <replace> idem sans distinction majuscules/minuscules
|
||||
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>
|
||||
rspideny <search> idem sans distinction majuscules/minuscules
|
||||
|
||||
|
||||
<search> est une expression régulière compatible POSIX regexp supportant le
|
||||
@ -1195,6 +1263,8 @@ Remarques :
|
||||
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.
|
||||
- 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".
|
||||
|
||||
Exemples :
|
||||
----------
|
||||
@ -1230,20 +1300,22 @@ Exemples :
|
||||
reqideny ^[^:\ ]*\
|
||||
|
||||
# force connection:close, thus disabling HTTP keep-alive
|
||||
reqidel ^Connection:
|
||||
rspidel ^Connection:
|
||||
reqadd Connection:\ close
|
||||
rspadd Connection:\ close
|
||||
option httpclos
|
||||
|
||||
# change the server name
|
||||
rspidel ^Server:\
|
||||
rspadd Server:\ Formilux/0.1.8
|
||||
|
||||
|
||||
Enfin, l'option 'forwardfor' ajoute l'adresse IP du client dans un champ
|
||||
De plus, l'option 'forwardfor' ajoute l'adresse IP du client dans un champ
|
||||
'X-Forwarded-For' de la requête, ce qui permet à un serveur web final de
|
||||
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.
|
||||
Ceci simplifie la désactivation du keep-alive HTTP par rapport à l'ancienne
|
||||
méthode impliquant 4 règles.
|
||||
|
||||
Exemple :
|
||||
---------
|
||||
listen http_proxy 0.0.0.0:80
|
||||
@ -1252,10 +1324,10 @@ Exemple :
|
||||
option httplog
|
||||
option dontlognull
|
||||
option forwardfor
|
||||
option httpclose
|
||||
|
||||
4.4) Répartition avec persistence
|
||||
---------------------------------
|
||||
|
||||
La combinaison de l'insertion de cookie avec la répartition de charge interne
|
||||
permet d'assurer une persistence dans les sessions HTTP d'une manière
|
||||
pratiquement transparente pour les applications. Le principe est simple :
|
||||
@ -1274,9 +1346,37 @@ Exemple :
|
||||
server 192.168.1.1:80 cookie server01 check
|
||||
server 192.168.1.2:80 cookie server02 check
|
||||
|
||||
4.5) Personalisation des erreurs
|
||||
--------------------------------
|
||||
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', '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 ont un code de retour autre que 200, 203, 206, 300, 301,
|
||||
410, sauf si le server a positionné un entê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,'
|
||||
(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
|
||||
l'administrateur sache qu'il y a une action correctrice à entreprendre.
|
||||
|
||||
4.6) Personalisation des erreurs
|
||||
--------------------------------
|
||||
Certaines situations conduisent à retourner une erreur HTTP au client :
|
||||
- requête invalide ou trop longue => code HTTP 400
|
||||
- requête mettant trop de temps à venir => code HTTP 408
|
||||
@ -1309,9 +1409,8 @@ Exemple :
|
||||
errorloc 503 http://192.168.114.58/error50x.html
|
||||
errorloc 504 http://192.168.114.58/error50x.html
|
||||
|
||||
4.6) Changement des valeurs par défaut
|
||||
4.7) Changement des valeurs par défaut
|
||||
--------------------------------------
|
||||
|
||||
Dans la version 1.1.22 est apparue la notion de valeurs par défaut, ce qui évite
|
||||
de répéter des paramètres communs à toutes les instances, tels que les timeouts,
|
||||
adresses de log, modes de fonctionnement, etc.
|
||||
@ -1326,16 +1425,16 @@ La section 'defaults' utilise la m
|
||||
paramètres près qui ne sont pas supportés. Le mot clé 'defaults' peut accepter
|
||||
un commentaire en guise paramètre.
|
||||
|
||||
Dans la version 1.1.23, seuls les paramètres suivants peuvent être positionnés
|
||||
dans une section 'defaults' :
|
||||
Dans la version 1.1.28/1.2.1, seuls les paramètres suivants peuvent être
|
||||
positionnés dans une section 'defaults' :
|
||||
- log (le premier et le second)
|
||||
- mode { tcp, http, health }
|
||||
- balance { roundrobin }
|
||||
- disabled (pour désactiver toutes les instances qui suivent)
|
||||
- enabled (pour faire l'opération inverse, mais c'est le cas par défaut)
|
||||
- contimeout, clitimeout, srvtimeout, grace, retries, maxconn
|
||||
- option { redispatch, transparent, keepalive, forwardfor, httplog,
|
||||
dontlognull, persist, httpchk }
|
||||
- option { redispatch, transparent, keepalive, forwardfor, logasap, httpclose,
|
||||
checkcache, httplog, tcplog, dontlognull, persist, httpchk }
|
||||
- redispatch, redisp, transparent, source { addr:port }
|
||||
- cookie, capture
|
||||
- errorloc
|
||||
|
@ -1,13 +1,13 @@
|
||||
# this config needs haproxy-1.1.23
|
||||
# this config needs haproxy-1.1.28 or haproxy-1.2.1
|
||||
|
||||
global
|
||||
log 127.0.0.1 local0
|
||||
log 127.0.0.1 local1 notice
|
||||
#log loghost local0 info
|
||||
maxconn 4096
|
||||
chroot /tmp
|
||||
uid 11
|
||||
gid 2
|
||||
chroot /usr/share/haproxy
|
||||
uid 99
|
||||
gid 99
|
||||
daemon
|
||||
#debug
|
||||
#quiet
|
||||
@ -40,10 +40,7 @@ listen appli2-insert 0.0.0.0:10002
|
||||
server inst2 192.168.114.56:81 cookie server02 check inter 2000 fall 3
|
||||
capture cookie vgnvisitor= len 32
|
||||
|
||||
reqidel ^Connection: # disable keep-alive
|
||||
reqadd Connection:\ close
|
||||
rspidel ^Connection:
|
||||
rspadd Connection:\ close
|
||||
option httpclose # disable keep-alive
|
||||
rspidel ^Set-cookie:\ IP= # do not let this cookie tell our internal IP address
|
||||
|
||||
listen appli3-relais 0.0.0.0:10003
|
||||
@ -66,10 +63,9 @@ listen appli5-backup 0.0.0.0:10005
|
||||
capture cookie ASPSESSION len 32
|
||||
srvtimeout 20000
|
||||
|
||||
reqidel ^Connection: # disable keep-alive
|
||||
reqadd Connection:\ close
|
||||
rspidel ^Connection:
|
||||
rspadd Connection:\ close
|
||||
option httpclose # disable keep-alive
|
||||
option checkcache # block response if set-cookie & cacheable
|
||||
|
||||
rspidel ^Set-cookie:\ IP= # do not let this cookie tell our internal IP address
|
||||
|
||||
errorloc 502 http://192.168.114.58/error502.html
|
||||
|
114
examples/haproxy.init
Normal file
114
examples/haproxy.init
Normal file
@ -0,0 +1,114 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# chkconfig: - 85 15
|
||||
# description: HA-Proxy is a TCP/HTTP reverse proxy which is particularly suited \
|
||||
# for high availability environments.
|
||||
# processname: haproxy
|
||||
# config: /etc/haproxy/haproxy.cfg
|
||||
# pidfile: /var/run/haproxy.pid
|
||||
|
||||
# Script Author: Simon Matter <simon.matter@invoca.ch>
|
||||
# Version: 2004060600
|
||||
|
||||
# Source function library.
|
||||
if [ -f /etc/init.d/functions ]; then
|
||||
. /etc/init.d/functions
|
||||
elif [ -f /etc/rc.d/init.d/functions ] ; then
|
||||
. /etc/rc.d/init.d/functions
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Source networking configuration.
|
||||
. /etc/sysconfig/network
|
||||
|
||||
# Check that networking is up.
|
||||
[ ${NETWORKING} = "no" ] && exit 0
|
||||
|
||||
# This is our service name
|
||||
BASENAME=`basename $0`
|
||||
if [ -L $0 ]; then
|
||||
BASENAME=`find $0 -name $BASENAME -printf %l`
|
||||
BASENAME=`basename $BASENAME`
|
||||
fi
|
||||
|
||||
[ -f /etc/$BASENAME/$BASENAME.cfg ] || exit 1
|
||||
|
||||
RETVAL=0
|
||||
|
||||
start() {
|
||||
/usr/sbin/$BASENAME -c -q -f /etc/$BASENAME/$BASENAME.cfg
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Errors found in configuration file, check it with '$BASENAME check'."
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -n "Starting $BASENAME: "
|
||||
daemon /usr/sbin/$BASENAME -D -f /etc/$BASENAME/$BASENAME.cfg -p /var/run/$BASENAME.pid
|
||||
RETVAL=$?
|
||||
echo
|
||||
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$BASENAME
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo -n "Shutting down $BASENAME: "
|
||||
killproc $BASENAME -USR1
|
||||
RETVAL=$?
|
||||
echo
|
||||
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$BASENAME
|
||||
[ $RETVAL -eq 0 ] && rm -f /var/run/$BASENAME.pid
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
restart() {
|
||||
/usr/sbin/$BASENAME -c -q -f /etc/$BASENAME/$BASENAME.cfg
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Errors found in configuration file, check it with '$BASENAME check'."
|
||||
return 1
|
||||
fi
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
check() {
|
||||
/usr/sbin/$BASENAME -c -q -V -f /etc/$BASENAME/$BASENAME.cfg
|
||||
}
|
||||
|
||||
rhstatus() {
|
||||
status $BASENAME
|
||||
}
|
||||
|
||||
condrestart() {
|
||||
[ -e /var/lock/subsys/$BASENAME ] && restart || :
|
||||
}
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
restart
|
||||
;;
|
||||
reload)
|
||||
restart
|
||||
;;
|
||||
condrestart)
|
||||
condrestart
|
||||
;;
|
||||
status)
|
||||
rhstatus
|
||||
;;
|
||||
check)
|
||||
check
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $BASENAME {start|stop|restart|reload|condrestart|status|check}"
|
||||
RETVAL=1
|
||||
esac
|
||||
|
||||
exit $RETVAL
|
92
examples/haproxy.spec
Normal file
92
examples/haproxy.spec
Normal file
@ -0,0 +1,92 @@
|
||||
Summary: HA-Proxy is a TCP/HTTP reverse proxy for high availability environments
|
||||
Name: haproxy
|
||||
Version: 1.2.1
|
||||
Release: 1
|
||||
License: GPL
|
||||
Group: System Environment/Daemons
|
||||
URL: http://w.ods.org/tools/%{name}/
|
||||
Packager: Simon Matter <simon.matter@invoca.ch>
|
||||
Vendor: Invoca Systems
|
||||
Distribution: Invoca Linux Server
|
||||
Source0: http://w.ods.org/tools/%{name}/%{name}-%{version}.tar.gz
|
||||
Source1: %{name}.cfg
|
||||
Source2: %{name}.init
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-root
|
||||
BuildRequires: pcre-devel
|
||||
Prereq: /sbin/chkconfig
|
||||
|
||||
%description
|
||||
HA-Proxy is a TCP/HTTP reverse proxy which is particularly suited for high
|
||||
availability environments. Indeed, it can:
|
||||
- route HTTP requests depending on statically assigned cookies
|
||||
- spread the load among several servers while assuring server persistence
|
||||
through the use of HTTP cookies
|
||||
- switch to backup servers in the event a main one fails
|
||||
- accept connections to special ports dedicated to service monitoring
|
||||
- stop accepting connections without breaking existing ones
|
||||
- add/modify/delete HTTP headers both ways
|
||||
- block requests matching a particular pattern
|
||||
|
||||
It needs very little resource. Its event-driven architecture allows it to easily
|
||||
handle thousands of simultaneous connections on hundreds of instances without
|
||||
risking the system's stability.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
%{__make} REGEX=pcre DEBUG=""
|
||||
|
||||
%install
|
||||
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
|
||||
|
||||
%{__install} -d %{buildroot}%{_sbindir}
|
||||
%{__install} -d %{buildroot}%{_sysconfdir}/rc.d/init.d
|
||||
%{__install} -d %{buildroot}%{_sysconfdir}/logrotate.d
|
||||
%{__install} -d %{buildroot}%{_sysconfdir}/%{name}
|
||||
%{__install} -d %{buildroot}%{_datadir}/%{name}
|
||||
|
||||
%{__install} -s %{name} %{buildroot}%{_sbindir}/
|
||||
%{__install} -c -m 644 %{SOURCE1} %{buildroot}%{_sysconfdir}/%{name}/
|
||||
%{__install} -c -m 755 %{SOURCE2} %{buildroot}%{_sysconfdir}/rc.d/init.d/%{name}
|
||||
|
||||
%clean
|
||||
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
|
||||
|
||||
%post
|
||||
/sbin/chkconfig --add %{name}
|
||||
|
||||
%preun
|
||||
if [ $1 = 0 ]; then
|
||||
/sbin/service %{name} stop >/dev/null 2>&1 || :
|
||||
/sbin/chkconfig --del %{name}
|
||||
fi
|
||||
|
||||
%postun
|
||||
if [ "$1" -ge "1" ]; then
|
||||
/sbin/service %{name} condrestart >/dev/null 2>&1 || :
|
||||
fi
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc CHANGELOG TODO examples
|
||||
%attr(0755,root,root) %{_sbindir}/%{name}
|
||||
%dir %{_sysconfdir}/%{name}
|
||||
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/%{name}.cfg
|
||||
%attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name}
|
||||
%dir %{_datadir}/%{name}
|
||||
|
||||
%changelog
|
||||
* Sun Jun 6 2004 Willy Tarreau <willy@w.ods.org>
|
||||
- updated to 1.1.28
|
||||
- added config check support to the init script
|
||||
|
||||
* Tue Oct 28 2003 Simon Matter <simon.matter@invoca.ch>
|
||||
- updated to 1.1.27
|
||||
- added pid support to the init script
|
||||
|
||||
* Wed Oct 22 2003 Simon Matter <simon.matter@invoca.ch>
|
||||
- updated to 1.1.26
|
||||
|
||||
* Thu Oct 16 2003 Simon Matter <simon.matter@invoca.ch>
|
||||
- initial build
|
@ -7,7 +7,7 @@ option bin reserved_option /usr/sbin/haproxy
|
||||
option cmdline reserved_option '$bin -f ${opt_config} -p ${pidfile} -D -q'
|
||||
|
||||
function do_help {
|
||||
echo "Usage: ${0##*/} <status|start|stop|help>"
|
||||
echo "Usage: ${0##*/} <status|start|stop|help|conf>"
|
||||
echo "List of config.rc options (name, type, default value, current value) :"
|
||||
echo
|
||||
echo " - config ; def=/etc/haproxy/haproxy.cfg ; cur=$opt_confdir"
|
||||
@ -15,6 +15,11 @@ function do_help {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# reads the configuration file and checks its syntax.
|
||||
function do_conf {
|
||||
$bin -c -V -q -f ${opt_config}
|
||||
}
|
||||
|
||||
# assign default values to options and variables before parsing the cfg file
|
||||
function fct_begin_section {
|
||||
pidfile="/var/run/haproxy${2:+-$2}.pid"
|
||||
|
146
haproxy.c
146
haproxy.c
@ -8,7 +8,10 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Please refer to RFC2068 or RFC2616 for informations about HTTP protocol, and
|
||||
* RFC2965 for informations about cookies usage.
|
||||
* RFC2965 for informations about cookies usage. More generally, the IETF HTTP
|
||||
* Working Group's web site should be consulted for protocol related changes :
|
||||
*
|
||||
* http://ftp.ics.uci.edu/pub/ietf/http/
|
||||
*
|
||||
* Pending bugs (may be not fixed because never reproduced) :
|
||||
* - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
|
||||
@ -54,7 +57,7 @@
|
||||
#endif
|
||||
|
||||
#define HAPROXY_VERSION "1.2.1"
|
||||
#define HAPROXY_DATE "2004/06/05"
|
||||
#define HAPROXY_DATE "2004/06/06"
|
||||
|
||||
/* this is for libc5 for example */
|
||||
#ifndef TCP_NODELAY
|
||||
@ -300,6 +303,7 @@ int strlcpy2(char *dst, const char *src, int size) {
|
||||
#define MODE_DAEMON 8
|
||||
#define MODE_QUIET 16
|
||||
#define MODE_CHECK 32
|
||||
#define MODE_VERBOSE 64
|
||||
|
||||
/* server flags */
|
||||
#define SRV_RUNNING 1 /* the server is UP */
|
||||
@ -684,13 +688,14 @@ void display_version() {
|
||||
void usage(char *name) {
|
||||
display_version();
|
||||
fprintf(stderr,
|
||||
"Usage : %s -f <cfgfile> [ -vd"
|
||||
"Usage : %s -f <cfgfile> [ -vdV"
|
||||
#if STATTIME > 0
|
||||
"sl"
|
||||
#endif
|
||||
"D ] [ -n <maxconn> ] [ -N <maxpconn> ] [ -p <pidfile> ]\n"
|
||||
" -v displays version\n"
|
||||
" -d enters debug mode\n"
|
||||
" -V enters verbose mode (disables quiet mode)\n"
|
||||
#if STATTIME > 0
|
||||
" -s enables statistics output\n"
|
||||
" -l enables long statistics format\n"
|
||||
@ -714,7 +719,7 @@ void Alert(char *fmt, ...) {
|
||||
struct timeval tv;
|
||||
struct tm *tm;
|
||||
|
||||
if (!(global.mode & MODE_QUIET)) {
|
||||
if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
|
||||
va_start(argp, fmt);
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
@ -736,7 +741,7 @@ void Warning(char *fmt, ...) {
|
||||
struct timeval tv;
|
||||
struct tm *tm;
|
||||
|
||||
if (!(global.mode & MODE_QUIET)) {
|
||||
if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
|
||||
va_start(argp, fmt);
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
@ -755,7 +760,7 @@ void Warning(char *fmt, ...) {
|
||||
void qfprintf(FILE *out, char *fmt, ...) {
|
||||
va_list argp;
|
||||
|
||||
if (!(global.mode & MODE_QUIET)) {
|
||||
if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
|
||||
va_start(argp, fmt);
|
||||
vfprintf(out, fmt, argp);
|
||||
fflush(out);
|
||||
@ -2100,9 +2105,6 @@ int event_accept(int fd) {
|
||||
s->req = s->rep = NULL; /* will be allocated later */
|
||||
s->flags = 0;
|
||||
|
||||
if (p->options & PR_O_CHK_CACHE)
|
||||
s->flags |= SN_CACHEABLE | SN_CACHE_COOK;
|
||||
|
||||
s->res_cr = s->res_cw = s->res_sr = s->res_sw = RES_SILENT;
|
||||
s->cli_fd = cfd;
|
||||
s->srv_fd = -1;
|
||||
@ -2165,7 +2167,7 @@ int event_accept(int fd) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((global.mode & MODE_DEBUG) && !(global.mode & MODE_QUIET)) {
|
||||
if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
|
||||
struct sockaddr_in sockname;
|
||||
int namelen;
|
||||
int len;
|
||||
@ -2525,8 +2527,10 @@ int process_cli(struct session *t) {
|
||||
if (t->proxy->options & PR_O_HTTP_CLOSE)
|
||||
buffer_replace2(req, req->h, req->h, "Connection: close\r\n", 19);
|
||||
|
||||
if (!memcmp(req->data, "POST ", 5))
|
||||
t->flags |= SN_POST; /* this is a POST request */
|
||||
if (!memcmp(req->data, "POST ", 5)) {
|
||||
/* this is a POST request, which is not cacheable by default */
|
||||
t->flags |= SN_POST;
|
||||
}
|
||||
|
||||
t->cli_state = CL_STDATA;
|
||||
req->rlim = req->data + BUFSIZE; /* no more rewrite needed */
|
||||
@ -2608,7 +2612,7 @@ int process_cli(struct session *t) {
|
||||
|
||||
delete_header = 0;
|
||||
|
||||
if ((global.mode & MODE_DEBUG) && !(global.mode & MODE_QUIET)) {
|
||||
if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
|
||||
int len, max;
|
||||
len = sprintf(trash, "%08x:%s.clihdr[%04x:%04x]: ", t->uniq_id, t->proxy->id, (unsigned short)t->cli_fd, (unsigned short)t->srv_fd);
|
||||
max = ptr - req->h;
|
||||
@ -3085,7 +3089,7 @@ int process_cli(struct session *t) {
|
||||
return 0;
|
||||
}
|
||||
else { /* CL_STCLOSE: nothing to do */
|
||||
if ((global.mode & MODE_DEBUG) && !(global.mode & MODE_QUIET)) {
|
||||
if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
|
||||
int len;
|
||||
len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n", t->uniq_id, t->proxy->id, (unsigned short)t->cli_fd, (unsigned short)t->srv_fd);
|
||||
write(1, trash, len);
|
||||
@ -3288,6 +3292,21 @@ int process_srv(struct session *t) {
|
||||
}
|
||||
}
|
||||
|
||||
/* next, we'll block if an 'rspideny' or 'rspdeny' filter matched */
|
||||
if (t->flags & SN_SVDENY) {
|
||||
tv_eternity(&t->srexpire);
|
||||
tv_eternity(&t->swexpire);
|
||||
fd_delete(t->srv_fd);
|
||||
t->srv_state = SV_STCLOSE;
|
||||
t->logs.status = 502;
|
||||
client_return(t, t->proxy->errmsg.len502, t->proxy->errmsg.msg502);
|
||||
if (!(t->flags & SN_ERR_MASK))
|
||||
t->flags |= SN_ERR_PRXCOND;
|
||||
if (!(t->flags & SN_FINST_MASK))
|
||||
t->flags |= SN_FINST_H;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* we'll have something else to do here : add new headers ... */
|
||||
|
||||
if ((t->srv) && !(t->flags & SN_DIRECT) && (t->proxy->options & PR_O_COOK_INS) &&
|
||||
@ -3366,14 +3385,38 @@ int process_srv(struct session *t) {
|
||||
*/
|
||||
|
||||
|
||||
if (t->logs.logwait & LW_RESP) {
|
||||
if (t->logs.status == -1) {
|
||||
t->logs.logwait &= ~LW_RESP;
|
||||
t->logs.status = atoi(rep->h + 9);
|
||||
switch (t->logs.status) {
|
||||
case 200:
|
||||
case 203:
|
||||
case 206:
|
||||
case 300:
|
||||
case 301:
|
||||
case 410:
|
||||
/* RFC2616 @13.4:
|
||||
* "A response received with a status code of
|
||||
* 200, 203, 206, 300, 301 or 410 MAY be stored
|
||||
* by a cache (...) unless a cache-control
|
||||
* directive prohibits caching."
|
||||
*
|
||||
* RFC2616 @9.5: POST method :
|
||||
* "Responses to this method are not cacheable,
|
||||
* unless the response includes appropriate
|
||||
* Cache-Control or Expires header fields."
|
||||
*/
|
||||
if ((!t->flags & SN_POST) && (t->proxy->options & PR_O_CHK_CACHE))
|
||||
t->flags |= SN_CACHEABLE | SN_CACHE_COOK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete_header = 0;
|
||||
|
||||
if ((global.mode & MODE_DEBUG) && !(global.mode & MODE_QUIET)) {
|
||||
if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
|
||||
int len, max;
|
||||
len = sprintf(trash, "%08x:%s.srvhdr[%04x:%04x]: ", t->uniq_id, t->proxy->id, (unsigned short)t->cli_fd, (unsigned short)t->srv_fd);
|
||||
max = ptr - rep->h;
|
||||
@ -3434,21 +3477,27 @@ int process_srv(struct session *t) {
|
||||
t->flags &= ~SN_CACHEABLE & ~SN_CACHE_COOK;
|
||||
else if (strncasecmp(rep->h, "Cache-control: ", 15) == 0) {
|
||||
if (strncasecmp(rep->h + 15, "no-cache", 8) == 0) {
|
||||
if (rep->h + 23 == ptr || rep->h[23] == ';')
|
||||
if (rep->h + 23 == ptr || rep->h[23] == ',')
|
||||
t->flags &= ~SN_CACHEABLE & ~SN_CACHE_COOK;
|
||||
else {
|
||||
if (strncasecmp(rep->h + 23, "=\"set-cookie", 12) == 0
|
||||
&& (rep->h[35] == '"' || rep->h[35] == ';'))
|
||||
&& (rep->h[35] == '"' || rep->h[35] == ','))
|
||||
t->flags &= ~SN_CACHE_COOK;
|
||||
}
|
||||
} else if ((strncasecmp(rep->h + 15, "private", 7) == 0 &&
|
||||
(rep->h + 22 == ptr || rep->h[22] == ';'))
|
||||
(rep->h + 22 == ptr || rep->h[22] == ','))
|
||||
|| (strncasecmp(rep->h + 15, "no-store", 8) == 0 &&
|
||||
(rep->h + 23 == ptr || rep->h[23] == ';'))) {
|
||||
(rep->h + 23 == ptr || rep->h[23] == ','))) {
|
||||
t->flags &= ~SN_CACHEABLE & ~SN_CACHE_COOK;
|
||||
} else if (strncasecmp(rep->h + 15, "max-age=0", 9) == 0 &&
|
||||
(rep->h + 24 == ptr || rep->h[24] == ';')) {
|
||||
(rep->h + 24 == ptr || rep->h[24] == ',')) {
|
||||
t->flags &= ~SN_CACHEABLE & ~SN_CACHE_COOK;
|
||||
} else if (strncasecmp(rep->h + 15, "s-maxage=0", 10) == 0 &&
|
||||
(rep->h + 25 == ptr || rep->h[25] == ',')) {
|
||||
t->flags &= ~SN_CACHEABLE & ~SN_CACHE_COOK;
|
||||
} else if (strncasecmp(rep->h + 15, "public", 6) == 0 &&
|
||||
(rep->h + 21 == ptr || rep->h[21] == ',')) {
|
||||
t->flags |= SN_CACHEABLE | SN_CACHE_COOK;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3869,7 +3918,7 @@ int process_srv(struct session *t) {
|
||||
return 0;
|
||||
}
|
||||
else { /* SV_STCLOSE : nothing to do */
|
||||
if ((global.mode & MODE_DEBUG) && !(global.mode & MODE_QUIET)) {
|
||||
if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
|
||||
int len;
|
||||
len = sprintf(trash, "%08x:%s.srvcls[%04x:%04x]\n", t->uniq_id, t->proxy->id, (unsigned short)t->cli_fd, (unsigned short)t->srv_fd);
|
||||
write(1, trash, len);
|
||||
@ -3916,7 +3965,7 @@ int process_session(struct task *t) {
|
||||
s->proxy->nbconn--;
|
||||
actconn--;
|
||||
|
||||
if ((global.mode & MODE_DEBUG) && !(global.mode & MODE_QUIET)) {
|
||||
if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
|
||||
int len;
|
||||
len = sprintf(trash, "%08x:%s.closed[%04x:%04x]\n", s->uniq_id, s->proxy->id, (unsigned short)s->cli_fd, (unsigned short)s->srv_fd);
|
||||
write(1, trash, len);
|
||||
@ -5436,6 +5485,26 @@ int cfg_parse_listen(char *file, int linenum, char **args) {
|
||||
|
||||
chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
|
||||
}
|
||||
else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
|
||||
regex_t *preg;
|
||||
if (curproxy == &defproxy) {
|
||||
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*(args[1]) == 0) {
|
||||
Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
preg = calloc(1, sizeof(regex_t));
|
||||
if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
|
||||
Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
|
||||
}
|
||||
else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
|
||||
regex_t *preg;
|
||||
if (curproxy == &defproxy) {
|
||||
@ -5477,6 +5546,26 @@ int cfg_parse_listen(char *file, int linenum, char **args) {
|
||||
|
||||
chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
|
||||
}
|
||||
else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
|
||||
regex_t *preg;
|
||||
if (curproxy == &defproxy) {
|
||||
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*(args[1]) == 0) {
|
||||
Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
preg = calloc(1, sizeof(regex_t));
|
||||
if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
|
||||
Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
|
||||
}
|
||||
else if (!strcmp(args[0], "rspadd")) { /* add response header */
|
||||
if (curproxy == &defproxy) {
|
||||
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
|
||||
@ -5830,7 +5919,7 @@ void init(int argc, char **argv) {
|
||||
if (1<<INTBITS != sizeof(int)*8) {
|
||||
fprintf(stderr,
|
||||
"Error: wrong architecture. Recompile so that sizeof(int)=%d\n",
|
||||
sizeof(int)*8);
|
||||
(int)(sizeof(int)*8));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -5851,6 +5940,8 @@ void init(int argc, char **argv) {
|
||||
display_version();
|
||||
exit(0);
|
||||
}
|
||||
else if (*flag == 'V')
|
||||
arg_mode |= MODE_VERBOSE;
|
||||
else if (*flag == 'd')
|
||||
arg_mode |= MODE_DEBUG;
|
||||
else if (*flag == 'c')
|
||||
@ -5884,7 +5975,7 @@ void init(int argc, char **argv) {
|
||||
argv++; argc--;
|
||||
}
|
||||
|
||||
global.mode = (arg_mode & (MODE_DAEMON | MODE_QUIET | MODE_DEBUG));
|
||||
global.mode = (arg_mode & (MODE_DAEMON | MODE_VERBOSE | MODE_QUIET | MODE_CHECK | MODE_DEBUG));
|
||||
|
||||
if (!cfg_cfgfile)
|
||||
usage(old_argv);
|
||||
@ -5896,7 +5987,7 @@ void init(int argc, char **argv) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (arg_mode & MODE_CHECK) {
|
||||
if (global.mode & MODE_CHECK) {
|
||||
qfprintf(stdout, "Configuration file is valid : %s\n", cfg_cfgfile);
|
||||
exit(0);
|
||||
}
|
||||
@ -5919,7 +6010,8 @@ void init(int argc, char **argv) {
|
||||
/* command line debug mode inhibits configuration mode */
|
||||
global.mode &= ~(MODE_DAEMON | MODE_QUIET);
|
||||
}
|
||||
global.mode |= (arg_mode & (MODE_DAEMON | MODE_QUIET | MODE_DEBUG | MODE_STATS | MODE_LOG));
|
||||
global.mode |= (arg_mode & (MODE_DAEMON | MODE_QUIET | MODE_VERBOSE
|
||||
| MODE_DEBUG | MODE_STATS | MODE_LOG));
|
||||
|
||||
if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
|
||||
Warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
|
||||
|
Loading…
Reference in New Issue
Block a user