mirror of
				https://git.haproxy.org/git/haproxy.git/
				synced 2025-11-03 18:11:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			263 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			263 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
Prévoir des commandes en plusieurs mots clés.
 | 
						|
Par exemple :
 | 
						|
 | 
						|
  timeout connection XXX
 | 
						|
  connection scale XXX
 | 
						|
 | 
						|
On doit aussi accepter les préfixes :
 | 
						|
 | 
						|
  tim co XXX
 | 
						|
  co sca XXX
 | 
						|
 | 
						|
Prévoir de ranger les combinaisons dans un tableau. On doit même
 | 
						|
pouvoir effectuer un mapping simplifiant le parseur.
 | 
						|
 | 
						|
 | 
						|
Pour les filtres :
 | 
						|
 | 
						|
 | 
						|
    <direction> <where> <what> <operator> <pattern> <action> [ <args>* ]
 | 
						|
 | 
						|
    <direction> = [ req | rsp ]
 | 
						|
    <where>     = [ in | out ]
 | 
						|
    <what>      = [ line | LINE | METH | URI | h(hdr) | H(hdr) | c(cookie) | C(cookie) ]
 | 
						|
    <operator>  = [ == | =~ | =* | =^ | =/ | != | !~ | !* | !^ | !/ ]
 | 
						|
    <pattern>   = "<string>"
 | 
						|
    <action>    = [ allow | permit | deny | delete | replace | switch | add | set | redir ]
 | 
						|
    <args>      = optionnal action args
 | 
						|
 | 
						|
    exemples:
 | 
						|
 | 
						|
        req in URI     =^ "/images" switch images
 | 
						|
        req in h(host) =* ".mydomain.com" switch mydomain
 | 
						|
        req in h(host) =~ "localhost(.*)" replace "www\1"
 | 
						|
 | 
						|
    alternative :
 | 
						|
 | 
						|
    <direction> <where> <action> [not] <what> [<operator> <pattern> [ <args>* ]]
 | 
						|
 | 
						|
        req in  switch   URI     =^ "/images" images
 | 
						|
        req in  switch   h(host) =* ".mydomain.com" mydomain
 | 
						|
        req in  replace  h(host) =~ "localhost(.*)" "www\1"
 | 
						|
        req in  delete   h(Connection)
 | 
						|
        req in  deny not line =~ "((GET|HEAD|POST|OPTIONS) /)|(OPTIONS *)"
 | 
						|
        req out set      h(Connection) "close"
 | 
						|
        req out add      line "Server: truc"
 | 
						|
 | 
						|
 | 
						|
    <direction> <action> <where> [not] <what> [<operator> <pattern> [ <args>* ]] ';' <action2> <what2>
 | 
						|
 | 
						|
        req in  switch   URI     =^ "/images/" images ; replace "/"
 | 
						|
        req in  switch   h(host) =* ".mydomain.com" mydomain
 | 
						|
        req in  replace  h(host) =~ "localhost(.*)" "www\1"
 | 
						|
        req in  delete   h(Connection)
 | 
						|
        req in  deny not line =~ "((GET|HEAD|POST|OPTIONS) /)|(OPTIONS *)"
 | 
						|
        req out set      h(Connection) "close"
 | 
						|
        req out add      line == "Server: truc"
 | 
						|
 | 
						|
 | 
						|
Extension avec des ACL :
 | 
						|
 | 
						|
        req in acl(meth_valid)   METH =~ "(GET|POST|HEAD|OPTIONS)"  
 | 
						|
        req in acl(meth_options) METH == "OPTIONS" 
 | 
						|
        req in acl(uri_slash)    URI  =^ "/" 
 | 
						|
        req in acl(uri_star)     URI  == "*" 
 | 
						|
 | 
						|
        req in deny acl !(meth_options && uri_star || meth_valid && uri_slash)
 | 
						|
 | 
						|
Peut-être plus simplement :
 | 
						|
 | 
						|
        acl meth_valid   METH =~ "(GET|POST|HEAD|OPTIONS)"  
 | 
						|
        acl meth_options METH == "OPTIONS" 
 | 
						|
        acl uri_slash    URI  =^ "/" 
 | 
						|
        acl uri_star     URI  == "*" 
 | 
						|
 | 
						|
        req in  deny not acl(meth_options uri_star, meth_valid uri_slash)
 | 
						|
 | 
						|
        req in  switch   URI     =^ "/images/" images ; replace "/"
 | 
						|
        req in  switch   h(host) =* ".mydomain.com" mydomain
 | 
						|
        req in  replace  h(host) =~ "localhost(.*)" "www\1"
 | 
						|
        req in  delete   h(Connection)
 | 
						|
        req in  deny not line =~ "((GET|HEAD|POST|OPTIONS) /)|(OPTIONS *)"
 | 
						|
        req out set      h(Connection) "close"
 | 
						|
        req out add      line == "Server: truc"
 | 
						|
 | 
						|
Prévoir le cas du "if" pour exécuter plusieurs actions :
 | 
						|
 | 
						|
        req in  if URI =^ "/images/" then replace "/" ; switch images
 | 
						|
 | 
						|
Utiliser les noms en majuscules/minuscules pour indiquer si on veut prendre
 | 
						|
en compte la casse ou non :
 | 
						|
 | 
						|
        if uri  =^ "/watch/"       setbe watch   rebase "/watch/" "/"
 | 
						|
        if uri  =* ".jpg"          setbe images
 | 
						|
        if uri  =~ ".*dll.*"       deny
 | 
						|
        if HOST =* ".mydomain.com" setbe mydomain
 | 
						|
        etc...
 | 
						|
 | 
						|
Another solution would be to have a dedicated keyword to URI remapping. It
 | 
						|
would both rewrite the URI and optionally switch to another backend.
 | 
						|
 | 
						|
        uriremap "/watch/"  "/"       watch
 | 
						|
        uriremap "/chat/"   "/"       chat
 | 
						|
        uriremap "/event/"  "/event/" event
 | 
						|
 | 
						|
Or better :
 | 
						|
 | 
						|
        uriremap "/watch/"  watch  "/"
 | 
						|
        uriremap "/chat/"   chat   "/"
 | 
						|
        uriremap "/event/"  event
 | 
						|
 | 
						|
For the URI, using a regex is sometimes useful (eg: providing a set of possible prefixes.
 | 
						|
 | 
						|
 | 
						|
Sinon, peut-être que le "switch" peut prendre un paramètre de mapping pour la partie matchée :
 | 
						|
 | 
						|
        req in  switch   URI     =^ "/images/" images:"/"
 | 
						|
 | 
						|
 | 
						|
2007/03/31 - Besoins plus précis.
 | 
						|
 | 
						|
1) aucune extension de branchement ou autre dans les "listen", c'est trop complexe.
 | 
						|
 | 
						|
Distinguer les données entrantes (in) et sortantes (out).
 | 
						|
 | 
						|
Le frontend ne voit que les requetes entrantes et les réponses sortantes.
 | 
						|
Le backend voir les requêtes in/out et les réponses in/out.
 | 
						|
Le frontend permet les branchements d'ensembles de filtres de requêtes vers
 | 
						|
d'autres. Le frontend et les ensembles de filtres de requêtes peuvent brancher
 | 
						|
vers un backend.
 | 
						|
 | 
						|
-----------+--------+----------+----------+---------+----------+
 | 
						|
  \  Where |        |          |          |         |          |
 | 
						|
   \______ | Listen | Frontend | ReqRules | Backend | RspRules |
 | 
						|
          \|        |          |          |         |          |
 | 
						|
Capability |        |          |          |         |          |
 | 
						|
-----------+--------+----------+----------+---------+----------+
 | 
						|
Frontend   |    X   |     X    |          |         |          |
 | 
						|
-----------+--------+----------+----------+---------+----------+
 | 
						|
FiltReqIn  |    X   |     X    |     X    |    X    |          |
 | 
						|
-----------+--------+----------+----------+---------+----------+
 | 
						|
JumpFiltReq|    X   |     X    |     X    |         |          | \
 | 
						|
-----------+--------+----------+----------+---------+----------+  > = ReqJump
 | 
						|
SetBackend |    X   |     X    |     X    |         |          | /
 | 
						|
-----------+--------+----------+----------+---------+----------+
 | 
						|
FiltReqOut |        |          |          |    X    |          |
 | 
						|
-----------+--------+----------+----------+---------+----------+
 | 
						|
FiltRspIn  |    X   |          |          |    X    |     X    |
 | 
						|
-----------+--------+----------+----------+---------+----------+
 | 
						|
JumpFiltRsp|        |          |          |    X    |     X    |
 | 
						|
-----------+--------+----------+----------+---------+----------+
 | 
						|
FiltRspOut |        |     X    |          |    X    |     X    |
 | 
						|
-----------+--------+----------+----------+---------+----------+
 | 
						|
Backend    |    X   |          |          |    X    |          |
 | 
						|
-----------+--------+----------+----------+---------+----------+
 | 
						|
 | 
						|
En conclusion
 | 
						|
-------------
 | 
						|
 | 
						|
Il y a au moins besoin de distinguer 8 fonctionnalités de base :
 | 
						|
 - capacité à recevoir des connexions (frontend)
 | 
						|
 - capacité à filtrer les requêtes entrantes
 | 
						|
 - capacité à brancher vers un backend ou un ensemble de règles de requêtes
 | 
						|
 - capacité à filtrer les requêtes sortantes
 | 
						|
 - capacité à filtrer les réponses entrantes
 | 
						|
 - capacité à brancher vers un autre ensemble de règles de réponses
 | 
						|
 - capacité à filtrer la réponse sortante
 | 
						|
 - capacité à gérer des serveurs (backend)
 | 
						|
 | 
						|
Remarque
 | 
						|
--------
 | 
						|
 - on a souvent besoin de pouvoir appliquer un petit traitement sur un ensemble
 | 
						|
   host/uri/autre. Le petit traitement peut consister en quelques filtres ainsi
 | 
						|
   qu'une réécriture du couple (host,uri).
 | 
						|
 | 
						|
 | 
						|
Proposition : ACL
 | 
						|
 | 
						|
Syntaxe :
 | 
						|
---------
 | 
						|
 | 
						|
   acl <name> <what> <operator> <value> ...
 | 
						|
 | 
						|
Ceci créera une acl référencée sous le nom <name> qui sera validée si
 | 
						|
l'application d'au moins une des valeurs <value> avec l'opérateur <operator>
 | 
						|
sur le sujet <what> est validée.
 | 
						|
 | 
						|
Opérateurs :
 | 
						|
------------
 | 
						|
 | 
						|
Toujours 2 caractères :
 | 
						|
 | 
						|
  [=!][~=*^%/.]
 | 
						|
 | 
						|
Premier caractère :  
 | 
						|
   '=' : OK si test valide
 | 
						|
   '!' : OK si test échoué.
 | 
						|
 | 
						|
Second caractère :
 | 
						|
   '~' : compare avec une regex
 | 
						|
   '=' : compare chaîne à chaîne
 | 
						|
   '*' : compare la fin de la chaîne (ex: =* ".mydomain.com")
 | 
						|
   '^' : compare le début de la chaîne (ex: =^ "/images/")
 | 
						|
   '%' : recherche une sous-chaîne
 | 
						|
   '/' : compare avec un mot entier en acceptant le '/' comme délimiteur
 | 
						|
   '.' : compare avec un mot entier en acceptant el '.' comme délimiteur
 | 
						|
 | 
						|
Ensuite on exécute une action de manière conditionnelle si l'ensemble des ACLs
 | 
						|
mentionnées sont validées (ou invalidées pour celles précédées d'un "!") :
 | 
						|
 | 
						|
   <what> <where> <action> on [!]<aclname> ...
 | 
						|
 | 
						|
 | 
						|
Exemple :
 | 
						|
---------
 | 
						|
 | 
						|
   acl www_pub host =. www www01 dev preprod
 | 
						|
   acl imghost host =. images
 | 
						|
   acl imgdir   uri =/ img
 | 
						|
   acl imagedir uri =/ images
 | 
						|
   acl msie h(user-agent) =% "MSIE"
 | 
						|
 | 
						|
   set_host  "images"       on www_pub imgdir 
 | 
						|
   remap_uri "/img"    "/"  on www_pub imgdir
 | 
						|
   remap_uri "/images" "/"  on www_pub imagedir
 | 
						|
   setbe images             on imghost
 | 
						|
   reqdel "Cookie"          on all
 | 
						|
 | 
						|
 | 
						|
 | 
						|
Actions possibles :
 | 
						|
 | 
						|
   req  {in|out} {append|delete|rem|add|set|rep|mapuri|rewrite|reqline|deny|allow|setbe|tarpit}
 | 
						|
   resp {in|out} {append|delete|rem|add|set|rep|maploc|rewrite|stsline|deny|allow}
 | 
						|
 | 
						|
   req in append <line>
 | 
						|
   req in delete <line_regex>
 | 
						|
   req in rem <header>
 | 
						|
   req in add <header> <new_value>
 | 
						|
   req in set <header> <new_value>
 | 
						|
   req in rep <header> <old_value> <new_value>
 | 
						|
   req in mapuri  <old_uri_prefix> <new_uri_prefix>
 | 
						|
   req in rewrite <old_uri_regex>  <new_uri>
 | 
						|
   req in reqline <old_req_regex>  <new_req>
 | 
						|
   req in deny
 | 
						|
   req in allow
 | 
						|
   req in tarpit
 | 
						|
   req in setbe <backend>
 | 
						|
 | 
						|
   resp out maploc <old_location_prefix> <new_loc_prefix>
 | 
						|
   resp out stsline <old_sts_regex> <new_sts_regex>
 | 
						|
 | 
						|
Les chaînes doivent être délimitées par un même caractère au début et à la fin,
 | 
						|
qui doit être échappé s'il est présent dans la chaîne. Tout ce qui se trouve
 | 
						|
entre le caractère de fin et les premiers espace est considéré comme des
 | 
						|
options passées au traitement. Par exemple :
 | 
						|
 | 
						|
   req in rep host /www/i /www/
 | 
						|
   req in rep connection /keep-alive/i "close"
 | 
						|
 | 
						|
Il serait pratique de pouvoir effectuer un remap en même temps qu'un setbe.
 | 
						|
 | 
						|
Captures: les séparer en in/out. Les rendre conditionnelles ?
 |