* released 1.1.24
* if a client sent a full request then shut its write connection down, then
the request was aborted. This case was detected only when using haproxy
both as health-check client and as a server.
* if 'option httpchk' is used in a 'health' mode server, then responses will
change from 'OK' to 'HTTP/1.0 200 OK'.
* fixed a Linux-only bug in case of HTTP server health-checks, where a single
server response followed by a close could be ignored, and the server seen
as failed.
* renamed 'haproxy.txt' to 'haproxy-fr.txt'
* large documentation and examples cleanups
diff --git a/CHANGELOG b/CHANGELOG
index cdf4e5a..a2d962b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,16 @@
ChangeLog :
===========
+2003/09/21 : 1.1.24
+ - if a client sent a full request then shut its write connection down, then
+ the request was aborted. This case was detected only when using haproxy
+ both as health-check client and as a server.
+ - if 'option httpchk' is used in a 'health' mode server, then responses will
+ change from 'OK' to 'HTTP/1.0 200 OK'.
+ - fixed a Linux-only bug in case of HTTP server health-checks, where a single
+ server response followed by a close could be ignored, and the server seen
+ as failed.
+
2003/09/19 : 1.1.23
- fixed a stupid bug introduced in 1.1.22 which caused second and subsequent
'default' sections to keep previous parameters, and not initialize logs
diff --git a/doc/haproxy-en.txt b/doc/haproxy-en.txt
index 7d678d2..6d7f2e6 100644
--- a/doc/haproxy-en.txt
+++ b/doc/haproxy-en.txt
@@ -1,9 +1,9 @@
H A - P r o x y
---------------
- version 1.1.23
+ version 1.1.24
willy tarreau
- 2003/09/20
+ 2003/09/21
============
| Abstract |
@@ -332,14 +332,22 @@
This mode provides a way for external components to check the proxy's health.
It is meant to be used with intelligent load-balancers which can use send/expect
scripts to check for all of their servers' availability. This one simply accepts
-the connection, returns the word 'OK' and closes it. To enable it, simply
+the connection, returns the word 'OK' and closes it. If the 'option httpchk' is
+set, then the reply will be 'HTTP/1.0 200 OK' with no data, so that it can be
+tested from a tool which supports HTTP health-checks. To enable it, simply
specify 'health' as the working mode :
Example :
---------
+ # simple response : 'OK'
listen health_check 0.0.0.0:60000
mode health
+ # HTTP response : 'HTTP/1.0 200 OK'
+ listen http_health_check 0.0.0.0:60001
+ mode health
+ option httpchk
+
2.3) Limiting the number of simultaneous connections
----------------------------------------------------
@@ -640,8 +648,8 @@
server srv2 192.168.1.2:+1000
-3.1) Servers monitoring
------------------------
+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
@@ -850,45 +858,39 @@
4.2) Event logging
------------------
-
-- 8< - - - 8< - - - 8< - - - 8< - - - 8< - - - 8< - - -
-
-
-
-Les connexions TCP et HTTP peuvent donner lieu à une journalisation sommaire ou
-détaillée indiquant, pour chaque connexion, la date, l'heure, l'adresse IP
-source, le serveur destination, la durée de la connexion, les temps de réponse,
-la requête HTTP, le code de retour, la quantité de données transmises, et même
-dans certains cas, la valeur d'un cookie permettant de suivre les sessions.
-Tous les messages sont envoyés en syslog vers un ou deux serveurs. Se référer à
-la section 1.1 pour plus d'information sur les catégories de logs. La syntaxe
-est la suivante :
+TCP and HTTP connections can be logged with informations such as date, time,
+source IP address, destination address, connection duration, response times,
+HTTP request, the HTTP return code, number of bytes transmitted, the conditions
+in which the session ended, and even exchanged cookies values, to track a
+particular user's problems for example. All messages are sent to up to two
+syslog servers. Consult section 1.1 for more info about log facilities. The
+syntax follows :
- log <adresse_ip_1> <catégorie_1> [niveau_max_1]
- log <adresse_ip_2> <catégorie_2> [niveau_max_2]
-ou
+ log <address_1> <facility_1> [max_level_1]
+ log <address_2> <facility_2> [max_level_2]
+or
log global
-Remarque :
-----------
-La syntaxe spécifique 'log global' indique que l'on souhaite utiliser les
-paramètres de journalisation définis dans la section 'global'.
+Note :
+------
+The particular syntax 'log global' means that the same log configuration as the
+'global' section will be used.
-Exemple :
+Example :
---------
listen http_proxy 0.0.0.0:80
mode http
log 192.168.2.200 local3
log 192.168.2.201 local4
-Par défaut, les informations contenues dans les logs se situent au niveau TCP
-uniquement. Il faut préciser l'option 'httplog' pour obtenir les détails du
-protocole HTTP. Dans les cas où un mécanisme de surveillance effectuant des
-connexions et déconnexions fréquentes, polluerait 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).
+By default, only TCP information is logged. It is necessary to set the 'httplog'
+option to obtain more detailed information about HTTP contents. In the event
+where an external component would establish frequent connections to check the
+service, logs may be 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.
-Exemple :
+Example :
---------
listen http_proxy 0.0.0.0:80
mode http
@@ -896,88 +898,81 @@
option dontlognull
log 192.168.2.200 local3
-Depuis la version 1.1.18, un indicateur de complétude de la session a été ajouté
-dans les logs HTTP. C'est un champ de 4 caractères 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 :
+Since version 1.1.18, a session completion indicator has been added to HTTP
+logs. It's a 4-characters field preceeding the HTTP request, and indicating :
+ - On the first character, a code reporting the first event which caused the
+ session to terminate :
- 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)
- 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.
+ 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.
+ c : the client time-out expired first.
+ s : the server time-out expired first.
+ - : normal session completion.
- - sur le second caractère, l'état d'avancement de la session HTTP lors de la
- fermeture :
+ - on the second character, the HTTP session state when it was closed :
- 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
- 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
+ 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
+ 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.
- - le troisième caractère indique l'éventuelle identification d'un cookie de
- persistence :
+ - the third character tells whether the persistence cookie was provided by
+ the client :
- N : aucun cookie de persistence n'a été présenté.
- I : le client a présenté un cookie ne correspondant à aucun serveur
- connu.
- 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
- correspondant au cookie.
- V : le client a présenté un cookie valide et a pu se connecter au
- serveur correspondant.
- - : non appliquable
+ N : the client provided NO cookie.
+ I : the client provided an INVALID cookie matching no known server.
+ 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).
- - le dernier caractère indique l'éventuel traitement effectué sur un cookie de
- persistence retrourné par le serveur :
+ - the last character reports what operations were performed on the persistence
+ cookie returned by the server :
- N : aucun cookie de persistence n'a été fourni par le serveur.
- P : un cookie cookie de persistence n'a été fourni par le serveur.
- I : aucun cookie n'a été fourni par le serveur, il a été inséré par le
+ N : NO cookie was provided by the server.
+ 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 : le cookie présenté par le serveur a été supprimé 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
+ D : the cookie provided by the server was DELETED by the proxy.
+ R : the cookie provided by the server was REWRITTEN by the proxy.
+ - : does not apply (no cookie set in configuration).
-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 :
+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 :
- capture cookie <préfixe_cookie> len <longueur_capture>
+ capture cookie <cookie_prefix> len <capture_length>
-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
-le suffixer du signe "=" pour s'assurer qu'aucun autre cookie ne prendra sa
-place dans les logs.
+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
+ensure that no other cookie will be logged.
-Exemples :
+Examples :
----------
- # capture du premier cookie dont le nom commence par "ASPSESSION"
+ # capture the first cookie whose name starts with "ASPSESSION"
capture cookie ASPSESSION len 32
- # capture du premier cookie dont le nom est exactement "vgnvisitor"
+ # capture the first cookie whose name is exactly "vgnvisitor"
capture cookie vgnvisitor= len 32
-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.
+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.
-Enfin, 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.
+Last, 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).
-Exemple :
+Example :
---------
listen http_proxy 0.0.0.0:80
mode http
@@ -988,99 +983,134 @@
capture cookie userid= len 20
-4.3) Modification des entê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
-possible de bloquer certaines requêtes en fonction du contenu des en-têtes ou de
-la requête. Une limitation cependant : les en-têtes fournis au milieu de
-connexions persistentes (keep-alive) ne sont pas vus car ils sont considérés
-comme faisant partie des échanges de données consécutifs à la première requête.
-Les données ne sont pas affectées, ceci ne s'applique qu'aux en-têtes.
+4.3) HTTP header manipulation
+-----------------------------
+In HTTP mode, it is possible to rewrite, add or delete some of the request and
+response headers based on regular expressions. It is also possible to block a
+request or a response if a particular header matches a regular expression,
+which is enough to stops most elementary protocol attacks, and to protect
+against information leak from the internal network. But there is a limitation
+to this : since haproxy's HTTP engine knows nothing about keep-alive, only
+headers passed during the first request of a TCP session will be seen. All
+subsequent headers will be considered data only and not analyzed. Furthermore,
+haproxy doesn't touch data contents, it stops at the end of headers.
-La syntaxe est :
- reqadd <string> pour ajouter un en-tête dans la requête
- reqrep <search> <replace> pour modifier la requête
- 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>
- reqiallow <search> idem sans distinction majuscules/minuscules
- reqdeny <search> interdire la requête si un entête valide <search>
- reqideny <search> idem sans distinction majuscules/minuscules
- reqpass <search> inhibe ces actions sur les entêtes validant <search>
- reqipass <search> idem sans distinction majuscules/minuscules
+The syntax is :
+ reqadd <string> to add a header to the request
+ reqrep <search> <replace> to modify the request
+ reqirep <search> <replace> same, but ignoring the case
+ reqdel <search> to delete a header in the request
+ reqidel <search> same, but ignoring the case
+ reqallow <search> definitely allow a request if a header matches <search>
+ reqiallow <search> same, but ignoring the case
+ reqdeny <search> denies a request if a header matches <search>
+ reqideny <search> same, but ignoring the case
+ reqpass <search> ignore a header matching <search>
+ reqipass <search> same, but ignoring the case
- rspadd <string> pour ajouter un en-tête dans la réponse
- rsprep <search> <replace> pour modifier la réponse
- 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
+ rspadd <string> to add a header to the response
+ rsprep <search> <replace> to modify the response
+ rspirep <search> <replace> same, but ignoring the case
+ rspdel <search> to delete the response
+ rspidel <search> same, but ignoring the case
-<search> est une expression régulière compatible POSIX regexp supportant le
-groupage par parenthèses (sans les '\'). Les espaces et autres séparateurs
-doivent êtres précédés d'un '\' pour ne pas être confondus avec la fin de la
-chaîne. De plus, certains caractères spéciaux peuvent être précédés d'un
-backslach ('\') :
+<search> is a POSIX regular expression (regex) which supports grouping through
+parenthesis (without the backslash). Spaces and other delimiters must be
+prefixed with a backslash ('\') to avoid confusion with a field delimiter.
+Other characters may be prefixed with a backslash to change their meaning :
- \t pour une tabulation
- \r pour un retour charriot
- \n pour un saut de ligne
- \ pour différencier un espace d'un séparateur
- \# pour différencier un dièse d'un commentaire
- \\ pour utiliser un backslash dans la regex
- \\\\ pour utiliser un backslash dans le texte
- \xXX pour un caractère spécifique XX (comme en C)
+ \t for a tab
+ \r for a carriage return (CR)
+ \n for a new line (LF)
+ \ to mark a space and differentiate it from a delimiter
+ \# to mark a sharp and differentiate it from a comment
+ \\ to use a backslash in a regex
+ \\\\ to use a backslash in the text (*2 for regex, *2 for haproxy)
+ \xXX to write the ASCII hex code XX as in the C language
-<replace> contient la chaîne remplaçant la portion vérifiée par l'expression.
-Elle peut inclure les caractères spéciaux ci-dessus, faire référence à un
-groupe délimité par des parenthèses dans l'expression régulière, par sa
-position numérale. Les positions vont de 1 à 9, et sont codées par un '\'
-suivi du chiffre désiré. Il est également possible d'insérer un caractère non
-imprimable (utile pour le saut de ligne) inscrivant '\x' suivi du code
-hexadécimal de ce caractère (comme en C).
+<replace> containst the string to be used to replace the largest portion of text
+matching the regex. It can make use of the special characters above, and can
+reference a substring delimited by parenthesis in the regex, by the group
+numerical order from 1 to 9. In this case, you would write a backslah ('\')
+immediately followed by one digit indicating the group position.
-<string> représente une chaîne qui sera ajoutée systématiquement après la
-dernière ligne d'en-tête.
+<string> represents the string which will systematically be added after the last
+header line. It can also use special characters above.
-Remarques :
----------
- - la première ligne de la requête et celle de la réponse sont traitées comme
- des en-têtes, ce qui permet de réécrire des URL et des codes d'erreur.
- - 'reqrep' est l'équivalent de 'cliexp' en version 1.0, et 'rsprep' celui de
- 'srvexp'. Ces noms sont toujours supportés mais déconseillés.
- - pour des raisons de performances, le nombre total de caractères ajoutés sur
- 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.
+Notes :
+-------
+ - the first line is considered as a header, which makes it possible to rewrite
+ or filter HTTP requests URIs or response codes.
+ - 'reqrep' is the equivalent of 'cliexp' in version 1.0, and 'rsprep' is the
+ equivalent of 'srvexp' in 1.0. Those names are still supported but
+ deprecated.
+ - for performances reasons, the number of characters added to a request or to
+ a response is limited to 4096 since version 1.1.5 (it was 256 before). This
+ 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.
-Exemples :
---------
- reqrep ^(GET.*)(.free.fr)(.*) \1.online.fr\3
- reqrep ^(POST.*)(.free.fr)(.*) \1.online.fr\3
+Examples :
+----------
+ ###### a few examples ######
+
+ # rewrite 'online.fr' instead of 'free.fr' for GET and POST requests
+ reqrep ^(GET\ .*)(.free.fr)(.*) \1.online.fr\3
+ reqrep ^(POST\ .*)(.free.fr)(.*) \1.online.fr\3
+
+ # force proxy connections to close
reqirep ^Proxy-Connection:.* Proxy-Connection:\ close
- rspirep ^Server:.* Server:\ Tux-2.0
+ # rewrite locations
rspirep ^(Location:\ )([^:]*://[^/]*)(.*) \1\3
- rspidel ^Connection:
- rspadd Connection:\ close
+ ###### A full configuration being used on production ######
-4.4) Répartition avec persistence
----------------------------------
+ # Every header should end with a colon followed by one space.
+ reqideny ^[^:\ ]*[\ ]*$
-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 :
- - attribuer une valeur d'un cookie à chaque serveur
- - effectuer une répartition interne
- - insérer un cookie dans les réponses issues d'une répartition uniquement,
- et faire en sorte que des caches ne mémorisent pas ce cookie.
- - cacher ce cookie à l'application lors des requêtes ultérieures.
+ # block Apache chunk exploit
+ reqideny ^Transfer-Encoding:[\ ]*chunked
+ reqideny ^Host:\ apache-
-Exemple :
+ # block annoying worms that fill the logs...
+ reqideny ^[^:\ ]*\ .*(\.|%2e)(\.|%2e)(%2f|%5c|/|\\\\)
+ reqideny ^[^:\ ]*\ ([^\ ]*\ [^\ ]*\ |.*%00)
+ reqideny ^[^:\ ]*\ .*<script
+ reqideny ^[^:\ ]*\ .*/(root\.exe\?|cmd\.exe\?|default\.ida\?)
+
+ # allow other syntactically valid requests, and block any other method
+ reqipass ^(GET|POST|HEAD|OPTIONS)\ /.*\ HTTP/1\.[01]$
+ reqipass ^OPTIONS\ \\*\ HTTP/1\.[01]$
+ reqideny ^[^:\ ]*\
+
+ # force connection:close, thus disabling HTTP keep-alive
+ reqidel ^Connection:
+ rspidel ^Connection:
+ reqadd Connection:\ close
+ rspadd Connection:\ close
+
+ # change the server name
+ rspidel ^Server:\
+ rspadd Server:\ Formilux/0.1.8
+
+
+- 8< - - - 8< - - - 8< - - - 8< - - - 8< - - - 8< - - -
+
+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
+ - enable the load balancing between servers
+ - insert a cookie into responses resulting from the balancing algorithm
+ (indirect accesses), end ensure that no upstream proxy will cache it.
+ - remove the cookie in the request headers so that the application never sees
+ it.
+
+Example :
---------
listen application 0.0.0.0:80
mode http
@@ -1089,31 +1119,32 @@
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) Customizing errors
+-----------------------
-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
- - requête interdite (bloquée par un reqideny) => code HTTP 403
- - erreur interne du proxy => code HTTP 500
- - le serveur a retourné une réponse incomplète ou invalide => code HTTP 502
- - aucun serveur disponible pour cette requête => code HTTP 503
- - le serveur n'a pas répondu dans le temps imparti => code HTTP 504
+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
+ - forbidden request (matches a deny filter) => HTTP 403
+ - internal error in haproxy => HTTP 500
+ - the server returned an invalid or incomplete response => HTTP 502
+ - no server was available to handle the request => HTTP 503
+ - the server failed to reply in time => HTTP 504
-Un message d'erreur succint tiré de la RFC accompagne ces codes de retour.
-Cependant, en fonction du type de clientèle, on peut préférer retourner des
-pages personnalisées. Ceci est possible par le biais de la commande "errorloc" :
+A succint error message taken from the RFC accompanies these return codes.
+But depending on the clients knowledge, it may be better to return custom, user
+friendly, error pages. This is made possible through the use of the 'errorloc'
+command :
- errorloc <code_HTTP> <location>
+ errorloc <HTTP_code> <location>
-Au lieu de générer une erreur HTTP <code_HTTP> parmi les codes cités ci-dessus,
-le proxy génèrera un code de redirection temporaire (HTTP 302) vers l'adresse
-d'une page précisée dans <location>. Cette adresse peut être relative au site,
-ou absolue. Comme cette réponse est traîtée par le navigateur du client
-lui-même, il est indispensable que l'adresse fournie lui soit accessible.
+Instead of generating an HTTP error <HTTP_code> among those above, the proxy
+will return a temporary redirection code (HTTP 302) towards the address
+specified in <location>. This address may be either relative to the site or
+absolute. Since this request will be handled by the client's browser, it's
+mandatory that the returned address be reachable from the outside.
-Exemple :
+Example :
---------
listen application 0.0.0.0:80
errorloc 400 /badrequest.html
@@ -1124,30 +1155,28 @@
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.6) Modifying default values
+-----------------------------
-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.
+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...
-Les valeurs par défaut sont positionnées dans la dernière section 'defaults'
-précédent l'instance qui les utilisera. On peut donc mettre autant de sections
-'defaults' que l'on veut. Il faut juste se rappeler que la présence d'une telle
-section implique une annulation de tous les paramètres par défaut positionnés
-précédemment, dans le but de les remplacer.
+Default values are set in a 'defaults' section. Each of these section clears
+all previously set default parameters, so there may be as many default
+parameters as needed. Only the last one before a 'listen' section will be
+used for this section. The 'defaults' section uses the same syntax as the
+'listen' section, for the supported parameters. The 'defaults' keyword ignores
+everything on its command line, so that fake instance names can be specified
+there for better clarity.
-La section 'defaults' utilise la même syntaxe que la section 'listen', aux
-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.22, seuls les paramètres suivants peuvent être positionnés
-dans une section 'defaults' :
- - log (le premier et le second)
+In version 1.1.23, only those parameters can be preset in the 'default'
+section :
+ - log (the first and second one)
- 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)
+ - 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 }
@@ -1155,18 +1184,16 @@
- cookie, capture
- errorloc
-Ne sont pas supportés dans cette version, les adresses de dispatch et les
-configurations de serveurs, ainsi que tous les filtres basés sur les
-expressions régulières :
+As of 1.1.24, it is not possible to put certain parameters in a 'defaults'
+section, mainly regular expressions and server configurations :
- dispatch, server,
- - req*, rsp*,
+ - req*, rsp*
-Enfin, il n'y a pas le moyen, pour le moment, d'invalider un paramètre booléen
-positionné par défaut. Donc si une option est spécifiée dans les paramètres par
-défaut, le seul moyen de la désactiver pour une instance, c'est de changer les
-paramètres par défaut avant la déclaration de l'instance.
+Last, there's no way yet to change a boolean option from its assigned default
+value. So if an 'option' statement is set in a 'defaults' section, the only
+way to flush it is to redefine a new 'defaults' section without this 'option'.
-Exemples :
+Examples :
----------
defaults applications TCP
log global
@@ -1205,14 +1232,14 @@
server srv1 192.168.1.2:+8000 cookie srv2 check port 8080 inter 1000
defaults
- # section vide qui annule tous les paramètes par défaut.
+ # this empty section voids all default parameters
-=======================
-| Paramétrage système |
-=======================
+=========================
+| System-specific setup |
+=========================
-Sous Linux 2.4
-==============
+Linux 2.4
+=========
-- cut here --
#!/bin/sh
@@ -1254,4 +1281,17 @@
-- cut here --
--- fin --
+
+FreeBSD
+=======
+
+A FreeBSD port of HA-Proxy is now available and maintained, thanks to
+Clement Laforet <sheepkiller@cultdeadsheep.org>.
+
+For more information :
+http://www.freebsd.org/cgi/url.cgi?ports/net/haproxy/pkg-descr
+http://www.freebsd.org/cgi/cvsweb.cgi/ports/net/haproxy/
+http://www.freshports.org/net/haproxy
+
+
+-- end --
diff --git a/doc/haproxy.txt b/doc/haproxy-fr.txt
similarity index 95%
rename from doc/haproxy.txt
rename to doc/haproxy-fr.txt
index 5df305d..40bc27c 100644
--- a/doc/haproxy.txt
+++ b/doc/haproxy-fr.txt
@@ -1,9 +1,9 @@
H A - P r o x y
---------------
- version 1.1.23
+ version 1.1.24
willy tarreau
- 2003/09/20
+ 2003/09/21
================
| Introduction |
@@ -347,14 +347,22 @@
Il s'agit d'un mode offrant à un composant externe une visibilité de l'état de
santé du service. Il se contente de retourner "OK" à tout client se connectant
sur son port. Il peut être utilisé avec des répartiteurs de charge évolués pour
-déterminer quels sont les services utilisables. Pour activer ce mode, préciser
+déterminer quels sont les services utilisables. Si l'option 'httpchk' est
+activée, alors la réponse changera en 'HTTP/1.0 200 OK' pour satisfaire les
+attentes de composants sachant tester en HTTP. Pour activer ce mode, préciser
le mode HEALTH sous la déclaration du relais.
Exemple :
---------
+ # réponse simple : 'OK'
listen health_check 0.0.0.0:60000
mode health
+ # réponse HTTP : 'HTTP/1.0 200 OK'
+ listen http_health_check 0.0.0.0:60001
+ mode health
+ option httpchk
+
2.3) Limitation du nombre de connexions simultanées
---------------------------------------------------
@@ -951,7 +959,8 @@
persistence retrourné par le serveur :
N : aucun cookie de persistence n'a été fourni par le serveur.
- P : un cookie 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
@@ -1058,7 +1067,7 @@
dernière ligne d'en-tête.
Remarques :
----------
+-----------
- la première ligne de la requête et celle de la réponse sont traitées comme
des en-têtes, ce qui permet de réécrire des URL et des codes d'erreur.
- 'reqrep' est l'équivalent de 'cliexp' en version 1.0, et 'rsprep' celui de
@@ -1070,15 +1079,48 @@
entêtes inutiles avant les ajouts.
Exemples :
---------
- reqrep ^(GET.*)(.free.fr)(.*) \1.online.fr\3
- reqrep ^(POST.*)(.free.fr)(.*) \1.online.fr\3
+----------
+ ###### a few examples ######
+
+ # rewrite 'online.fr' instead of 'free.fr' for GET and POST requests
+ reqrep ^(GET\ .*)(.free.fr)(.*) \1.online.fr\3
+ reqrep ^(POST\ .*)(.free.fr)(.*) \1.online.fr\3
+
+ # force proxy connections to close
reqirep ^Proxy-Connection:.* Proxy-Connection:\ close
- rspirep ^Server:.* Server:\ Tux-2.0
+ # rewrite locations
rspirep ^(Location:\ )([^:]*://[^/]*)(.*) \1\3
- rspidel ^Connection:
- rspadd Connection:\ close
+
+ ###### A full configuration being used on production ######
+ # Every header should end with a colon followed by one space.
+ reqideny ^[^:\ ]*[\ ]*$
+
+ # block Apache chunk exploit
+ reqideny ^Transfer-Encoding:[\ ]*chunked
+ reqideny ^Host:\ apache-
+
+ # block annoying worms that fill the logs...
+ reqideny ^[^:\ ]*\ .*(\.|%2e)(\.|%2e)(%2f|%5c|/|\\\\)
+ reqideny ^[^:\ ]*\ ([^\ ]*\ [^\ ]*\ |.*%00)
+ reqideny ^[^:\ ]*\ .*<script
+ reqideny ^[^:\ ]*\ .*/(root\.exe\?|cmd\.exe\?|default\.ida\?)
+
+ # allow other syntactically valid requests, and block any other method
+ reqipass ^(GET|POST|HEAD|OPTIONS)\ /.*\ HTTP/1\.[01]$
+ reqipass ^OPTIONS\ \\*\ HTTP/1\.[01]$
+ reqideny ^[^:\ ]*\
+
+ # force connection:close, thus disabling HTTP keep-alive
+ reqidel ^Connection:
+ rspidel ^Connection:
+ reqadd Connection:\ close
+ rspadd Connection:\ close
+
+ # change the server name
+ rspidel ^Server:\
+ rspadd Server:\ Formilux/0.1.8
+
4.4) Répartition avec persistence
---------------------------------
@@ -1153,7 +1195,7 @@
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.22, seuls les paramètres suivants peuvent être positionnés
+Dans la version 1.1.23, seuls les paramètres suivants peuvent être positionnés
dans une section 'defaults' :
- log (le premier et le second)
- mode { tcp, http, health }
@@ -1171,7 +1213,7 @@
configurations de serveurs, ainsi que tous les filtres basés sur les
expressions régulières :
- dispatch, server,
- - req*, rsp*,
+ - req*, rsp*
Enfin, il n'y a pas le moyen, pour le moment, d'invalider un paramètre booléen
positionné par défaut. Donc si une option est spécifiée dans les paramètres par
@@ -1266,4 +1308,16 @@
-- cut here --
+Sous FreeBSD
+============
+
+Un port de HA-Proxy sous FreeBSD est désormais disponible, grâce à
+Clement Laforet <sheepkiller@cultdeadsheep.org>.
+
+Pour plus d'informations :
+http://www.freebsd.org/cgi/url.cgi?ports/net/haproxy/pkg-descr
+http://www.freebsd.org/cgi/cvsweb.cgi/ports/net/haproxy/
+http://www.freshports.org/net/haproxy
+
+
-- fin --
diff --git a/examples/examples.cfg b/examples/examples.cfg
index 8bec828..0850c40 100644
--- a/examples/examples.cfg
+++ b/examples/examples.cfg
@@ -145,6 +145,7 @@
listen health 0.0.0.0:31300
mode health
+ option httpchk
clitimeout 1500
srvtimeout 1500
maxconn 6000
diff --git a/examples/haproxy.cfg b/examples/haproxy.cfg
index b6d877f..705c93e 100644
--- a/examples/haproxy.cfg
+++ b/examples/haproxy.cfg
@@ -1,3 +1,5 @@
+# this config needs haproxy-1.1.23
+
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
@@ -10,41 +12,33 @@
#debug
#quiet
-listen appli1-rewrite 0.0.0.0:10001
+defaults
log global
mode http
option httplog
option dontlognull
- cookie SERVERID rewrite
- balance roundrobin
- server app1_1 192.168.34.23:8080 cookie app1inst1 check inter 2000 rise 2 fall 5
- server app1_2 192.168.34.32:8080 cookie app1inst2 check inter 2000 rise 2 fall 5
- server app1_3 192.168.34.27:8080 cookie app1inst3 check inter 2000 rise 2 fall 5
- server app1_4 192.168.34.42:8080 cookie app1inst4 check inter 2000 rise 2 fall 5
retries 3
redispatch
maxconn 2000
contimeout 5000
clitimeout 50000
srvtimeout 50000
-
+
+listen appli1-rewrite 0.0.0.0:10001
+ cookie SERVERID rewrite
+ balance roundrobin
+ server app1_1 192.168.34.23:8080 cookie app1inst1 check inter 2000 rise 2 fall 5
+ server app1_2 192.168.34.32:8080 cookie app1inst2 check inter 2000 rise 2 fall 5
+ server app1_3 192.168.34.27:8080 cookie app1inst3 check inter 2000 rise 2 fall 5
+ server app1_4 192.168.34.42:8080 cookie app1inst4 check inter 2000 rise 2 fall 5
+
listen appli2-insert 0.0.0.0:10002
- log global
- mode http
- option httplog
- option dontlognull
option httpchk
balance roundrobin
cookie SERVERID insert indirect nocache
server inst1 192.168.114.56:80 cookie server01 check inter 2000 fall 3
server inst2 192.168.114.56:81 cookie server02 check inter 2000 fall 3
capture cookie vgnvisitor= len 32
- retries 3
- redispatch
- maxconn 2000
- contimeout 5000
- clitimeout 50000
- srvtimeout 50000
reqidel ^Connection: # disable keep-alive
reqadd Connection:\ close
@@ -53,40 +47,16 @@
rspidel ^Set-cookie:\ IP= # do not let this cookie tell our internal IP address
listen appli3-relais 0.0.0.0:10003
- log global
- mode http
- option httplog
- option dontlognull
dispatch 192.168.135.17:80
- retries 3
- redispatch
- maxconn 2000
- contimeout 5000
- clitimeout 50000
- srvtimeout 50000
listen appli4-backup 0.0.0.0:10004
- log global
- mode http
- option httplog
- option dontlognull
option httpchk /index.html
option persist
balance roundrobin
server inst1 192.168.114.56:80 check inter 2000 fall 3
server inst2 192.168.114.56:81 check inter 2000 fall 3 backup
- retries 3
- redispatch
- maxconn 2000
- contimeout 5000
- clitimeout 50000
- srvtimeout 50000
listen appli5-backup 0.0.0.0:10005
- log global
- mode http
- option httplog
- option dontlognull
option httpchk *
balance roundrobin
cookie SERVERID insert indirect nocache
@@ -94,12 +64,7 @@
server inst2 192.168.114.56:81 cookie server02 check inter 2000 fall 3
server inst3 192.168.114.57:80 backup check inter 2000 fall 3
capture cookie ASPSESSION len 32
- retries 3
- redispatch
- maxconn 2000
- contimeout 5000
- clitimeout 50000
- srvtimeout 50000
+ srvtimeout 20000
reqidel ^Connection: # disable keep-alive
reqadd Connection:\ close
diff --git a/haproxy.c b/haproxy.c
index 43c4c65..ebf2832 100644
--- a/haproxy.c
+++ b/haproxy.c
@@ -53,8 +53,8 @@
#include <linux/netfilter_ipv4.h>
#endif
-#define HAPROXY_VERSION "1.1.23"
-#define HAPROXY_DATE "2003/09/20"
+#define HAPROXY_VERSION "1.1.24"
+#define HAPROXY_DATE "2003/09/21"
/* this is for libc5 for example */
#ifndef TCP_NODELAY
@@ -2167,7 +2167,10 @@
fdtab[cfd].state = FD_STREADY;
if (p->mode == PR_MODE_HEALTH) { /* health check mode, no client reading */
- client_retnclose(s, 3, "OK\n"); /* forge an "OK" response */
+ if (p->options & PR_O_HTTP_CHK) /* "option httpchk" will make it speak HTTP */
+ client_retnclose(s, 19, "HTTP/1.0 200 OK\r\n\r\n"); /* forge a 200 response */
+ else
+ client_retnclose(s, 3, "OK\n"); /* forge an "OK" response */
}
else {
FD_SET(cfd, StaticReadEvent);
@@ -2215,6 +2218,7 @@
int skerr, lskerr;
lskerr = sizeof(skerr);
getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
+ /* in case of TCP only, this tells us if the connection succeeded */
if (skerr)
s->result = -1;
else {
@@ -2260,19 +2264,23 @@
int skerr, lskerr;
lskerr = sizeof(skerr);
- getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
- s->result = -1;
- if (!skerr) {
+
+ s->result = len = -1;
#ifndef MSG_NOSIGNAL
+ getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
+ if (!skerr)
len = recv(fd, reply, sizeof(reply), 0);
#else
- len = recv(fd, reply, sizeof(reply), MSG_NOSIGNAL);
+ /* Warning! Linux returns EAGAIN on SO_ERROR if data are still available
+ * but the connection was closed on the remote end. Fortunately, recv still
+ * works correctly and we don't need to do the getsockopt() on linux.
+ */
+ len = recv(fd, reply, sizeof(reply), MSG_NOSIGNAL);
#endif
- if ((len >= sizeof("HTTP/1.0 000")) &&
- !memcmp(reply, "HTTP/1.", 7) &&
- (reply[9] == '2' || reply[9] == '3')) /* 2xx or 3xx */
- s->result = 1;
- }
+ if ((len >= sizeof("HTTP/1.0 000")) &&
+ !memcmp(reply, "HTTP/1.", 7) &&
+ (reply[9] == '2' || reply[9] == '3')) /* 2xx or 3xx */
+ s->result = 1;
FD_CLR(fd, StaticReadEvent);
task_wakeup(&rq, t);
@@ -2455,7 +2463,14 @@
* better to release the maximum of system buffers instead ? */
//FD_CLR(t->cli_fd, StaticReadEvent);
//tv_eternity(&t->crexpire);
- break;
+
+ /* FIXME: if we break here (as up to 1.1.23), having the client
+ * shutdown its connection can lead to an abort further.
+ * it's better to either return 1 or even jump directly to the
+ * data state which will save one schedule.
+ */
+ //break;
+ goto process_data;
}
/* to get a complete header line, we need the ending \r\n, \n\r, \r or \n too */
@@ -2777,6 +2792,7 @@
return t->cli_state != CL_STHEADERS;
}
else if (c == CL_STDATA) {
+ process_data:
/* read or write error */
if (t->res_cw == RES_ERROR || t->res_cr == RES_ERROR) {
tv_eternity(&t->crexpire);
@@ -3985,11 +4001,11 @@
//
// }
- status=select(maxfd,
- readnotnull ? ReadEvent : NULL,
- writenotnull ? WriteEvent : NULL,
- NULL,
- (next_time >= 0) ? &delta : NULL);
+ status = select(maxfd,
+ readnotnull ? ReadEvent : NULL,
+ writenotnull ? WriteEvent : NULL,
+ NULL,
+ (next_time >= 0) ? &delta : NULL);
/* this is an experiment on the separation of the select work */
// status = (readnotnull ? select(maxfd, ReadEvent, NULL, NULL, (next_time >= 0) ? &delta : NULL) : 0);