¿Cómo combina Apache varias secciones de ubicación coincidentes?

35

Estoy trabajando en alguna configuración básica de apache, pero no entiendo con precisión cómo apache combina diferentes <Location>secciones cuando varias de ellas coinciden con una URL de solicitudes entrantes. La documentación de apache en su capítulo "Cómo se fusionan las secciones" es un poco confusa cuando se trata del orden / prioridad de varias secciones coincidentes del mismo tipo.

Por ejemplo, imagine la siguiente configuración de apache (ignore si el contenido real tiene sentido o no, solo estoy interesado en el orden de aplicación de cada regla / sección):

<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>

Ahora, si un cliente realiza una solicitud /sub/foobar, ¿cuál es la configuración final que se aplicará a esta solicitud?

¿Es la configuración aplicada el equivalente de:

# 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

o tal vez

# 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

o algo completamente diferente.

Gracias por tu ayuda, soy realmente confuso.

LordOfThePigs
fuente

Respuestas:

44

El orden de fusión es bastante complicado, y es fácil quedar atrapado por las excepciones ... El documento de Apache es " Cómo se fusionan las secciones "

De acuerdo con esa documentación, el orden de fusión de las secciones se realiza procesando todas las entradas coincidentes para cada tipo de coincidencia en el orden en que se encuentran en los archivos de configuración y luego pasando al siguiente tipo (con la excepción de <Directorio >, que se trata en orden de especificidad de ruta).

El orden de los tipos es Directory, DirectoryMatch, Filesy, por último Location. Las coincidencias posteriores sobrescriben las coincidencias anteriores. (* ProxyPass y Alias ​​se tratan de manera diferente nuevamente, vea la nota al final)

Y hay varias excepciones importantes a estas reglas que se aplican al uso de ProxyPass y ProxyPass en una sección <Location>. (vea abajo)

Entonces, según su ejemplo anterior, solicite http://somehost.com/sub/foobar con la siguiente configuración;

<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>

Acumularía las siguientes directivas ...

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

Con los partidos posteriores eliminando los duplicados anteriores, lo que resulta en;

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

Explicación
Más tarde coincide con sobreescritura partidos anteriores con la excepción de <Directory>donde los partidos se procesan en el orden: componente de directorio corto al más largo.

Entonces, por ejemplo,
<Directory /var/web/dir>
se procesará antes,
<Directory /var/web/dir/subdir>
independientemente del orden en que se especificaron esas directivas en la configuración, y la coincidencia más específica gana.

Cualquier Locationdirectiva coincidente siempre anulará una Directorydirectiva coincidente previamente .

La idea básica es que para una solicitud como GET /some/http/request.htmlinternamente se traducirá a una ubicación en el sistema de archivos a través de un Alias, ScriptAliaso para una ubicación de archivo normal bajo DocumentRootel VirtualHost con el que coincide.

Por lo tanto, una solicitud tendrá las siguientes propiedades que utiliza para la coincidencia:
Location: /some/http/request.html File: /var/www/html/mysite/some/http/request.html Directory: /var/www/html/mysite/some/http

Apache se aplicará entonces a su vez todos los Directorypartidos, en el orden de la especificidad de directorio, de la configuración, y luego a su vez se aplica DirectoryMatch, Filesy, finalmente, Locationcoincide en el orden en que se encuentran.

Por lo tanto , se Locationanula Files, que anula DirectoryMatch, con las rutas que coinciden Directorycon la prioridad más baja. Por lo tanto, en su ejemplo anterior, una solicitud para /sub/foobarque coincida con las primeras 3 ubicaciones en orden, por lo tanto, la última gana por directivas en conflicto.

(Tiene razón en que no está claro en los documentos cómo se resuelven algunos de los casos límite, es posible que cualquier allow from *tipo de directivas se conecte a las asociadas Order allow,deny, pero no lo probé. Además, ¿qué sucede si coincide, Satisfy Anypero usted haber recogido previamente un Allow from *...)

nota interesante sobre ProxyPass y Alias

Solo para ser molesto, ProxyPassy Aliasparece funcionar en la otra dirección .... ;-) ¡Básicamente golpea el primer partido, luego se detiene y lo usa!

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.

así que, básicamente, las directivas Alias ​​y ProxyPass deben especificarse, primero las más específicas;

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

y

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

Sin embargo, como ha señalado @orev. Puede tener una directiva ProxyPass en una directiva de ubicación, por lo que un ProxyPass más específico en una ubicación superará a cualquier ProxyPass encontrado anteriormente.

Tom H
fuente
3
Gracias por marcar la advertencia sobre el pedido de directivas ProxyPass. Me ahorró mucho dolor de cabeza
Jeremy French
2
Con respecto a ProxyPass "trabajar en la otra dirección" , esto solo es cierto si están fuera de a <Location>. Dentro de a <Location>, <Location>se siguen las reglas de fusión , lo que significa que desea que sus <Location>directivas menos específicas vengan antes que las más específicas. Esto permite que los más específicos anulen las directivas menos específicas. Solo puedes tener uno ProxyPasspor <Location>.
orev