W jaki sposób Apache łączy wiele pasujących sekcji lokalizacji

35

Pracuję nad podstawową konfiguracją Apache, ale nie rozumiem dokładnie, w jaki sposób Apache łączy różne <Location>sekcje, gdy kilka z nich pasuje do adresu URL żądań przychodzących. Dokumentacja Apache w rozdziale „Jak scalać sekcje” jest nieco myląca, jeśli chodzi o kolejność / priorytet kilku pasujących sekcji tego samego typu.

Na przykład wyobraź sobie następującą konfigurację apache (zignoruj, czy rzeczywista zawartość ma sens, czy nie, interesuje mnie tylko kolejność aplikacji dla każdej reguły / sekcji):

<Location / >
  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
</Location>

<Location /sub/foo>
  Order allow,deny
</Location>

<Location /sub >
  Order deny,allow
  Require valid-user
  Satisfy all
</Location>

<Location /doesnt/match >
  ProxyPass !
</Location>

Teraz, jeśli klient przesyła żądanie /sub/foobar, jaka jest ostateczna konfiguracja, która zostanie zastosowana do tego żądania?

Czy zastosowana konfiguracja odpowiada:

# All the directives contained in all the matchin Locations in declaration order
ProxyPass http://backend.com/
Order allow,deny
Satisfy any
Order allow,deny
Order deny,allow
Require valid-user
Satisfy all

albo może

# same as above, but with longest matching path last
ProxyPass http://backend.com/
Order allow,deny
Satisfy any
Order deny,allow
Require valid-user
Satisfy all
Order allow,deny

lub coś zupełnie innego.

Dzięki za pomoc, jestem naprawdę zagubiony.

LordOfThePigs
źródło

Odpowiedzi:

44

Kolejność scalania jest dość skomplikowana i łatwo jest złapać się na wyjątki ... Dokumentacja Apache brzmi „ Jak scalane są sekcje

Zgodnie z tą dokumentacją kolejność scalania sekcji odbywa się poprzez przetworzenie wszystkich pasujących wpisów dla każdego typu dopasowania w kolejności, w jakiej występują w plikach konfiguracyjnych, a następnie przejście do następnego typu (z wyjątkiem <Directory >, która jest traktowana w kolejności specyficzności ścieżki).

Kolejność typów jest Directory, DirectoryMatch, Files, i wreszcie Location. Późniejsze mecze zastępują wcześniejsze mecze. (* ProxyPass i Alias ​​są ponownie traktowane inaczej, patrz uwaga na końcu)

Istnieje kilka ważnych wyjątków od tych reguł, które dotyczą używania ProxyPass i ProxyPass w sekcji <Lokalizacja>. (patrz poniżej)

Więc z powyższego przykładu, prosząc http://somehost.com/sub/foobar o konfigurację follwing;

<Location / >
  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
</Location>

<Location /sub/foo>
  Order allow,deny
</Location>

<Location /sub >
  Order deny,allow
  Require valid-user
  Satisfy all
</Location>

<Location /doesnt/match >
  ProxyPass !
</Location>

Gromadziłoby następujące dyrektywy ....

  ProxyPass http://backend.com/
  Order allow,deny
  Satisfy any
  Order allow,deny
  Order deny,allow
  Require valid-user
  Satisfy all   

Późniejsze dopasowania eliminują poprzednie duplikaty, co powoduje;

  ProxyPass http://backend.com/
  Order deny,allow
  Require valid-user
  Satisfy all   

Objaśnienie
Późniejsze dopasowania zastępują wcześniejsze dopasowania, z wyjątkiem miejsc, w <Directory>których dopasowania są przetwarzane w kolejności: najkrótszy składnik katalogu na najdłuższy.

Na przykład
<Directory /var/web/dir>
będą przetwarzane wcześniej,
<Directory /var/web/dir/subdir>
bez względu na kolejność tych dyrektyw w konfiguracji, a bardziej szczegółowe dopasowanie wygrywa.

Każda pasująca Locationdyrektywa zawsze zastąpi wcześniej pasującą Directorydyrektywę.

Podstawowym założeniem jest to, że na żądanie jak GET /some/http/request.htmlwewnętrznie zostanie on przetłumaczony na miejscu w systemie plików za pośrednictwem Alias, ScriptAliaslub w przypadku normalnej lokalizacji pliku pod DocumentRootdo VirtualHost że dopasowane.

Dlatego żądanie będzie mieć następujące właściwości, których używa do dopasowywania:
Location: /some/http/request.html File: /var/www/html/mysite/some/http/request.html Directory: /var/www/html/mysite/some/http

Apache będzie następnie zastosować po kolei wszystkie Directorymecze, w kolejności od specyfiki katalogów, z config, a następnie z kolei zastosować DirectoryMatch, Filesi wreszcie Locationmecze w kolejności, w jakiej są one spotkaliśmy.

LocationZastępuje więc Files, które zastępuje DirectoryMatch, ścieżki pasujące Directorydo najniższego priorytetu. Dlatego w powyższym przykładzie prośba o /sub/foobardopasowanie pierwszych 3 lokalizacji w kolejności, a więc ostatnia wygrywa w przypadku sprzecznych dyrektyw.

(Masz rację, że z dokumentów nie wynika jasno, w jaki sposób rozwiązano niektóre przypadki skrajne, możliwe jest, że wszelkie allow from *powiązane dyrektywy zostaną połączone z powiązanymi Order allow,deny, ale tego nie przetestowałem. Co się stanie, jeśli pasujesz, Satisfy Anyale ty wcześniej zebrałem Allow from *...)

interesująca notatka o ProxyPass i Aliasie

Po prostu denerwujące ProxyPassi Aliaswydaje się działać w innym kierunku .... ;-) W zasadzie uderza w pierwszy mecz, a potem zatrzymuje się i używa tego!

Ordering ProxyPass Directives

The configured ProxyPass and ProxyPassMatch rules are 
checked in the order of configuration. 
The first rule that matches wins. So
usually you should sort conflicting ProxyPass rules starting with the
longest URLs first. Otherwise later rules for longer URLS will be
hidden by any earlier rule which uses a leading substring of the URL.
Note that there is some relation with worker sharing.

For the same reasons exclusions must come before the general 
ProxyPass directives.

więc w zasadzie należy określić dyrektywy Alias ​​i ProxyPass, najpierw najbardziej szczegółowe;

Alias "/foo/bar" "/srv/www/uncommon/bar"
Alias "/foo"     "/srv/www/common/foo"

i

ProxyPass "/special-area" "http://special.example.com" smax=5 max=10
ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofailover=On

Jednak, jak zauważył @orev. Możesz mieć dyrektywę ProxyPass w dyrektywie lokalizacji, a więc bardziej szczegółowe ProxyPass w lokalizacji pobije wszystkie wcześniej znalezione ProxyPass.

Tom H.
źródło
3
Dziękujemy za zgłoszenie ostrzeżenia o zamawianiu dyrektyw ProxyPass. Zaoszczędził mi dużo bólu głowy
Jeremy French
2
Jeśli chodzi o ProxyPass „działanie w innym kierunku” , jest to prawdą tylko wtedy, gdy znajdują się poza obszarem<Location> . Wewnątrz a <Location>przestrzegane są zasady łączenia <Location>, co oznacza, że ​​chcesz, aby Twoje najmniej szczegółowe <Location>dyrektywy były przed tymi bardziej szczegółowymi. To pozwala bardziej szczegółowym zastąpić mniej szczegółowe dyrektywy. Możesz mieć tylko jeden ProxyPassna <Location>.
orev