Willy Tarreau | d1142aa | 2007-01-07 13:03:59 +0100 | [diff] [blame] | 1 | Prévoir des commandes en plusieurs mots clés. |
| 2 | Par exemple : |
| 3 | |
| 4 | timeout connection XXX |
| 5 | connection scale XXX |
| 6 | |
| 7 | On doit aussi accepter les préfixes : |
| 8 | |
| 9 | tim co XXX |
| 10 | co sca XXX |
| 11 | |
| 12 | Prévoir de ranger les combinaisons dans un tableau. On doit même |
| 13 | pouvoir effectuer un mapping simplifiant le parseur. |
| 14 | |
| 15 | |
| 16 | Pour les filtres : |
| 17 | |
| 18 | |
| 19 | <direction> <where> <what> <operator> <pattern> <action> [ <args>* ] |
| 20 | |
| 21 | <direction> = [ req | rsp ] |
| 22 | <where> = [ in | out ] |
| 23 | <what> = [ line | LINE | METH | URI | h(hdr) | H(hdr) | c(cookie) | C(cookie) ] |
| 24 | <operator> = [ == | =~ | =* | =^ | =/ | != | !~ | !* | !^ | !/ ] |
| 25 | <pattern> = "<string>" |
| 26 | <action> = [ allow | permit | deny | delete | replace | switch | add | set | redir ] |
| 27 | <args> = optionnal action args |
| 28 | |
| 29 | exemples: |
| 30 | |
| 31 | req in URI =^ "/images" switch images |
| 32 | req in h(host) =* ".mydomain.com" switch mydomain |
| 33 | req in h(host) =~ "localhost(.*)" replace "www\1" |
| 34 | |
| 35 | alternative : |
| 36 | |
| 37 | <direction> <where> <action> [not] <what> [<operator> <pattern> [ <args>* ]] |
| 38 | |
| 39 | req in switch URI =^ "/images" images |
| 40 | req in switch h(host) =* ".mydomain.com" mydomain |
| 41 | req in replace h(host) =~ "localhost(.*)" "www\1" |
| 42 | req in delete h(Connection) |
| 43 | req in deny not line =~ "((GET|HEAD|POST|OPTIONS) /)|(OPTIONS *)" |
| 44 | req out set h(Connection) "close" |
| 45 | req out add line "Server: truc" |
| 46 | |
| 47 | |
| 48 | <direction> <action> <where> [not] <what> [<operator> <pattern> [ <args>* ]] ';' <action2> <what2> |
| 49 | |
| 50 | req in switch URI =^ "/images/" images ; replace "/" |
| 51 | req in switch h(host) =* ".mydomain.com" mydomain |
| 52 | req in replace h(host) =~ "localhost(.*)" "www\1" |
| 53 | req in delete h(Connection) |
| 54 | req in deny not line =~ "((GET|HEAD|POST|OPTIONS) /)|(OPTIONS *)" |
| 55 | req out set h(Connection) "close" |
| 56 | req out add line == "Server: truc" |
| 57 | |
| 58 | |
| 59 | Extension avec des ACL : |
| 60 | |
| 61 | req in acl(meth_valid) METH =~ "(GET|POST|HEAD|OPTIONS)" |
| 62 | req in acl(meth_options) METH == "OPTIONS" |
| 63 | req in acl(uri_slash) URI =^ "/" |
| 64 | req in acl(uri_star) URI == "*" |
| 65 | |
| 66 | req in deny acl !(meth_options && uri_star || meth_valid && uri_slash) |
| 67 | |
| 68 | Peut-être plus simplement : |
| 69 | |
| 70 | acl meth_valid METH =~ "(GET|POST|HEAD|OPTIONS)" |
| 71 | acl meth_options METH == "OPTIONS" |
| 72 | acl uri_slash URI =^ "/" |
| 73 | acl uri_star URI == "*" |
| 74 | |
| 75 | req in deny not acl(meth_options uri_star, meth_valid uri_slash) |
| 76 | |
| 77 | req in switch URI =^ "/images/" images ; replace "/" |
| 78 | req in switch h(host) =* ".mydomain.com" mydomain |
| 79 | req in replace h(host) =~ "localhost(.*)" "www\1" |
| 80 | req in delete h(Connection) |
| 81 | req in deny not line =~ "((GET|HEAD|POST|OPTIONS) /)|(OPTIONS *)" |
| 82 | req out set h(Connection) "close" |
| 83 | req out add line == "Server: truc" |
| 84 | |
| 85 | Prévoir le cas du "if" pour exécuter plusieurs actions : |
| 86 | |
| 87 | req in if URI =^ "/images/" then replace "/" ; switch images |
| 88 | |
| 89 | Utiliser les noms en majuscules/minuscules pour indiquer si on veut prendre |
| 90 | en compte la casse ou non : |
| 91 | |
| 92 | if uri =^ "/watch/" setbe watch rebase "/watch/" "/" |
| 93 | if uri =* ".jpg" setbe images |
| 94 | if uri =~ ".*dll.*" deny |
| 95 | if HOST =* ".mydomain.com" setbe mydomain |
| 96 | etc... |
| 97 | |
| 98 | Another solution would be to have a dedicated keyword to URI remapping. It |
| 99 | would both rewrite the URI and optionally switch to another backend. |
| 100 | |
| 101 | uriremap "/watch/" "/" watch |
| 102 | uriremap "/chat/" "/" chat |
| 103 | uriremap "/event/" "/event/" event |
| 104 | |
| 105 | Or better : |
| 106 | |
| 107 | uriremap "/watch/" watch "/" |
| 108 | uriremap "/chat/" chat "/" |
| 109 | uriremap "/event/" event |
| 110 | |
| 111 | For the URI, using a regex is sometimes useful (eg: providing a set of possible prefixes. |
| 112 | |
| 113 | |
| 114 | Sinon, peut-être que le "switch" peut prendre un paramètre de mapping pour la partie matchée : |
| 115 | |
| 116 | req in switch URI =^ "/images/" images:"/" |
| 117 | |
Willy Tarreau | 985fc56 | 2007-04-01 09:44:10 +0200 | [diff] [blame] | 118 | |
| 119 | 2007/03/31 - Besoins plus précis. |
| 120 | |
| 121 | 1) aucune extension de branchement ou autre dans les "listen", c'est trop complexe. |
| 122 | |
| 123 | Distinguer les données entrantes (in) et sortantes (out). |
| 124 | |
| 125 | Le frontend ne voit que les requetes entrantes et les réponses sortantes. |
| 126 | Le backend voir les requêtes in/out et les réponses in/out. |
| 127 | Le frontend permet les branchements d'ensembles de filtres de requêtes vers |
| 128 | d'autres. Le frontend et les ensembles de filtres de requêtes peuvent brancher |
| 129 | vers un backend. |
| 130 | |
| 131 | -----------+--------+----------+----------+---------+----------+ |
| 132 | \ Where | | | | | | |
| 133 | \______ | Listen | Frontend | ReqRules | Backend | RspRules | |
| 134 | \| | | | | | |
| 135 | Capability | | | | | | |
| 136 | -----------+--------+----------+----------+---------+----------+ |
| 137 | Frontend | X | X | | | | |
| 138 | -----------+--------+----------+----------+---------+----------+ |
| 139 | FiltReqIn | X | X | X | X | | |
| 140 | -----------+--------+----------+----------+---------+----------+ |
| 141 | JumpFiltReq| X | X | X | | | \ |
| 142 | -----------+--------+----------+----------+---------+----------+ > = ReqJump |
| 143 | SetBackend | X | X | X | | | / |
| 144 | -----------+--------+----------+----------+---------+----------+ |
| 145 | FiltReqOut | | | | X | | |
| 146 | -----------+--------+----------+----------+---------+----------+ |
| 147 | FiltRspIn | X | | | X | X | |
| 148 | -----------+--------+----------+----------+---------+----------+ |
| 149 | JumpFiltRsp| | | | X | X | |
| 150 | -----------+--------+----------+----------+---------+----------+ |
| 151 | FiltRspOut | | X | | X | X | |
| 152 | -----------+--------+----------+----------+---------+----------+ |
| 153 | Backend | X | | | X | | |
| 154 | -----------+--------+----------+----------+---------+----------+ |
| 155 | |
| 156 | En conclusion |
| 157 | ------------- |
| 158 | |
| 159 | Il y a au moins besoin de distinguer 8 fonctionnalités de base : |
| 160 | - capacité à recevoir des connexions (frontend) |
| 161 | - capacité à filtrer les requêtes entrantes |
| 162 | - capacité à brancher vers un backend ou un ensemble de règles de requêtes |
| 163 | - capacité à filtrer les requêtes sortantes |
| 164 | - capacité à filtrer les réponses entrantes |
| 165 | - capacité à brancher vers un autre ensemble de règles de réponses |
| 166 | - capacité à filtrer la réponse sortante |
| 167 | - capacité à gérer des serveurs (backend) |
| 168 | |
| 169 | Remarque |
| 170 | -------- |
| 171 | - on a souvent besoin de pouvoir appliquer un petit traitement sur un ensemble |
| 172 | host/uri/autre. Le petit traitement peut consister en quelques filtres ainsi |
| 173 | qu'une réécriture du couple (host,uri). |
| 174 | |
| 175 | |
| 176 | Proposition : ACL |
| 177 | |
| 178 | Syntaxe : |
| 179 | --------- |
| 180 | |
| 181 | acl <name> <what> <operator> <value> ... |
| 182 | |
| 183 | Ceci créera une acl référencée sous le nom <name> qui sera validée si |
| 184 | l'application d'au moins une des valeurs <value> avec l'opérateur <operator> |
| 185 | sur le sujet <what> est validée. |
| 186 | |
| 187 | Opérateurs : |
| 188 | ------------ |
| 189 | |
| 190 | Toujours 2 caractères : |
| 191 | |
| 192 | [=!][~=*^%/.] |
| 193 | |
| 194 | Premier caractère : |
| 195 | '=' : OK si test valide |
| 196 | '!' : OK si test échoué. |
| 197 | |
| 198 | Second caractère : |
| 199 | '~' : compare avec une regex |
| 200 | '=' : compare chaîne à chaîne |
| 201 | '*' : compare la fin de la chaîne (ex: =* ".mydomain.com") |
| 202 | '^' : compare le début de la chaîne (ex: =^ "/images/") |
| 203 | '%' : recherche une sous-chaîne |
| 204 | '/' : compare avec un mot entier en acceptant le '/' comme délimiteur |
| 205 | '.' : compare avec un mot entier en acceptant el '.' comme délimiteur |
| 206 | |
| 207 | Ensuite on exécute une action de manière conditionnelle si l'ensemble des ACLs |
| 208 | mentionnées sont validées (ou invalidées pour celles précédées d'un "!") : |
| 209 | |
| 210 | <what> <where> <action> on [!]<aclname> ... |
| 211 | |
| 212 | |
| 213 | Exemple : |
| 214 | --------- |
| 215 | |
| 216 | acl www_pub host =. www www01 dev preprod |
| 217 | acl imghost host =. images |
| 218 | acl imgdir uri =/ img |
| 219 | acl imagedir uri =/ images |
| 220 | acl msie h(user-agent) =% "MSIE" |
| 221 | |
| 222 | set_host "images" on www_pub imgdir |
| 223 | remap_uri "/img" "/" on www_pub imgdir |
| 224 | remap_uri "/images" "/" on www_pub imagedir |
| 225 | setbe images on imghost |
| 226 | reqdel "Cookie" on all |
| 227 | |
| 228 | |
| 229 | |
| 230 | Actions possibles : |
| 231 | |
| 232 | req {in|out} {append|delete|rem|add|set|rep|mapuri|rewrite|reqline|deny|allow|setbe|tarpit} |
| 233 | resp {in|out} {append|delete|rem|add|set|rep|maploc|rewrite|stsline|deny|allow} |
| 234 | |
| 235 | req in append <line> |
| 236 | req in delete <line_regex> |
| 237 | req in rem <header> |
| 238 | req in add <header> <new_value> |
| 239 | req in set <header> <new_value> |
| 240 | req in rep <header> <old_value> <new_value> |
| 241 | req in mapuri <old_uri_prefix> <new_uri_prefix> |
| 242 | req in rewrite <old_uri_regex> <new_uri> |
| 243 | req in reqline <old_req_regex> <new_req> |
| 244 | req in deny |
| 245 | req in allow |
| 246 | req in tarpit |
| 247 | req in setbe <backend> |
| 248 | |
| 249 | resp out maploc <old_location_prefix> <new_loc_prefix> |
| 250 | resp out stsline <old_sts_regex> <new_sts_regex> |
| 251 | |
| 252 | Les chaînes doivent être délimitées par un même caractère au début et à la fin, |
| 253 | qui doit être échappé s'il est présent dans la chaîne. Tout ce qui se trouve |
| 254 | entre le caractère de fin et les premiers espace est considéré comme des |
| 255 | options passées au traitement. Par exemple : |
| 256 | |
| 257 | req in rep host /www/i /www/ |
| 258 | req in rep connection /keep-alive/i "close" |
| 259 | |
| 260 | Il serait pratique de pouvoir effectuer un remap en même temps qu'un setbe. |
| 261 | |
| 262 | Captures: les séparer en in/out. Les rendre conditionnelles ? |