mirror of
				https://git.haproxy.org/git/haproxy.git/
				synced 2025-10-31 00:21:00 +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 ?
 |