comportamento estranho do mod_rewrite do apache

2

Sou novo no site e espero que você possa me ajudar com um problema que aconteceu comigo ao tentar instalar o Rhodecode. Aqui está a (longa) história:
Eu consegui instalar Rhodecode dentro de um virtualenv em uma caixa linux. Usando o servidor de desenvolvimento ( paster serve production.ini ), vejo que está funcionando perfeitamente. No entanto, eu queria usar o Apache como frontend para SSL, usando mod_rewrite para redirecionar solicitações http para https. Aqui está minha configuração:

default-vhost.conf

<VirtualHost _default_:80>
  ServerName hg.mydomain.com
  ServerAdmin [email protected]
  ServerAlias rhodecode.mydomain.com

  DocumentRoot "/srv/www/htdocs"
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
  HostnameLookups Off
  UseCanonicalName Off
  ServerSignature Off
  ....
</VirtualHost>

Eu uso mod_rewrite em vez de um redirecionamento porque quero que meu site seja acessado por dois nomes de domínio. Temos um site em hg.mydomain.com que estamos planejando substituir com o novo rhodecode.mydomain.com, então eu queria preservar o nome do host na regra de reescrita. Com esta diretiva:

Redirect permanent / https://hg.mydomain.com/

o site funciona perfeitamente e nenhum problema de redirecionamento ocorre. Mas quando eu navego para http://rhodecode.mydomain.com , eu sou redirecionado para o outro site, e não posso fazer isso até que o site em hg.mydomain.com seja descartado e hg.mydomain.com aponte para o mesmo IP que o código de rodapé.mydomain .com.

O problema
Às vezes, o Rhodecode inclui urls em respostas a ações que exigem autenticação. Por exemplo, se você é um convidado e tenta participar de um repositório privado, é redirecionado para a tela de login com uma URL como esta:

https://rhodecode.mydomain.com/_admin/login?came_from=%2F

onde o% 2F é um '/' codificado.
Após o login, sou redirecionado para https://rhodecode.mydomain.com/error/HTTP_NOT_FOUND.html.var e a página padrão do apache para um erro 404 é exibida. Depois disso, navegar para https://rhodecode.mydomain.com/ mostra que estou em sessão no site. Por que eu fui redirecionado para aquele estranho documento HTTP_NOT_FOUND.html.var? Aqui está o resto da minha configuração e as partes relevantes dos logs:

default-vhost-ssl.conf

<VirtualHost _default_:443>

  ServerName hg.mydomain.com
  ServerAdmin [email protected]
  ServerAlias rhodecode.mydomain.com

  DocumentRoot "/srv/www/htdocs"
  HostnameLookups Off
  UseCanonicalName Off
  ServerSignature Off

  SSLEngine on

  certificate stuff ...

  WSGIDaemonProcess hg.mydomain.com user=rhodecode group=users threads=5 \
  home=/home/rhodecode/rhodecode-env python-path=/home/rhodecode/rhodecode-env/lib/python2.7/site-packages
  WSGIScriptAlias / /home/rhodecode/rhodecode-env/dispatch.wsgi
  WSGIPassAuthorization On

  <Directory /home/rhodecode/rhodecode-env>
    WSGIProcessGroup hg.mydomain.com
    WSGIApplicationGroup %{GLOBAL}
    Order deny,allow
    Allow from all
  </Directory>

</VirtualHost>

Regravar Log

172.17.1.49 - - [04/Mar/2014:00:06:24 +0000] [rhodecode.mydomain.com/sid#7f6a03266f00][rid#7f69fd68d7a0/initial/redir#1] (2) init rewrite engine with requested uri /error/HTTP_NOT_FOUND.html.var
172.17.1.49 - - [04/Mar/2014:00:06:24 +0000] [rhodecode.mydomain.com/sid#7f6a03266f00][rid#7f69fd68d7a0/initial/redir#1] (3) applying pattern '(.*)' to uri '/error/HTTP_NOT_FOUND.html.var'
172.17.1.49 - - [04/Mar/2014:00:06:24 +0000] [rhodecode.mydomain.com/sid#7f6a03266f00][rid#7f69fd68d7a0/initial/redir#1] (4) RewriteCond: input='off' pattern='off' => matched
172.17.1.49 - - [04/Mar/2014:00:06:24 +0000] [rhodecode.mydomain.com/sid#7f6a03266f00][rid#7f69fd68d7a0/initial/redir#1] (2) rewrite '/error/HTTP_NOT_FOUND.html.var' -> 'https://rhodecode.mydomain.com/error/HTTP_NOT_FOUND.html.var'
172.17.1.49 - - [04/Mar/2014:00:06:24 +0000] [rhodecode.mydomain.com/sid#7f6a03266f00][rid#7f69fd68d7a0/initial/redir#1] (2) explicitly forcing redirect with https://rhodecode.mydomain.com/error/HTTP_NOT_FOUND.html.var
172.17.1.49 - - [04/Mar/2014:00:06:24 +0000] [rhodecode.mydomain.com/sid#7f6a03266f00][rid#7f69fd68d7a0/initial/redir#1] (1) escaping https://rhodecode.mydomain.com/error/HTTP_NOT_FOUND.html.var for redirect
172.17.1.49 - - [04/Mar/2014:00:06:24 +0000] [rhodecode.mydomain.com/sid#7f6a03266f00][rid#7f69fd68d7a0/initial/redir#1] (1) redirect to https://rhodecode.mydomain.com/error/HTTP_NOT_FOUND.html.var [REDIRECT/301]

Preste atenção na parte gratuita # 7f69fd68d7a0 / initial / redir # 1 . Quando eu envio URLs sem% 2F, essa parte não aparece no log.

Log de acessos

hg.mydomain.com:443 172.17.1.49 - - [04/Mar/2014:02:09:13 +0000] "POST /_admin/login?came_from=%252F HTTP/1.1" 302 186 "https://rhodecode.mydomain.com/_admin/login?came_from=%252F" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36"
hg.mydomain.com:80 172.17.1.49 - - [04/Mar/2014:02:09:14 +0000] "GET /_admin/%2F HTTP/1.1" 301 268 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36"
hg.mydomain.com:443 172.17.1.49 - - [04/Mar/2014:02:09:14 +0000] "GET /error/HTTP_NOT_FOUND.html.var HTTP/1.1" 200 1132 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36"
hg.mydomain.com:443 172.17.1.49 - - [04/Mar/2014:02:09:14 +0000] "GET /favicon.ico HTTP/1.1" 404 618 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36"

A primeira linha é a solicitação POST com os dados de autenticação. É bem-sucedido, então me redireciona para a página de administração. Na segunda linha, você pode ver o local de redirecionamento me mandou de volta para http (ele inseriu a porta 80) para / _admin /% 2F e, como tal, foi redirecionado para https mas magicamente transformado para /error/HTTP_NOT_FOUND.html.var

Solicitação HTTP (Alguns cabeçalhos omitidos por brevidade)

POST /_admin/login?came_from=%252F HTTP/1.1
Host: rhodecode.mydomain.com
Cache-Control: no-cache
Pragma: no-cache
Origin: https://rhodecode.mydomain.com
Content-Type: application/x-www-form-urlencoded
Referer: https://rhodecode.mydomain.com/_admin/login?came_from=%252F
Cookie: rhodecode=3af58050ce87a93caa5a4c6809c5dacef4afb29d8e74b152c97f469199c554b6f67f7aa7
...

Resposta HTTP

HTTP/1.1 302 Found
Date: Tue, 04 Mar 2014 02:24:11 GMT
Server: Apache/2.2.22 (Linux/SUSE)
Pragma: no-cache
Cache-Control: no-cache
Set-Cookie: rhodecode=f0a94a155738490da032b46354f4d72338902da2d69bc1177bcf4086aa8158f4719526e0; httponly; Path=/
Location: http://rhodecode.mydomain.com/_admin/%2F
...

Solicitação HTTP 2

GET /_admin/%2F HTTP/1.1
Host: rhodecode.mydomain.com
Cache-Control: no-cache
Pragma: no-cache
Cookie: rhodecode=f0a94a155738490da032b46354f4d72338902da2d69bc1177bcf4086aa8158f4719526e0
...

Resposta HTTP 2

HTTP/1.1 301 Moved Permanently
Date: Tue, 04 Mar 2014 02:24:12 GMT
Server: Apache/2.2.22 (Linux/SUSE)
Location: https://rhodecode.mydomain.com/error/HTTP_NOT_FOUND.html.var
...

E finalmente, tentar obter /error/HTTP_NOT_FOUND.html.var não me causa um erro 404, mas uma resposta 200 OK !!
Eu achei que os navegadores estavam fazendo algo estranho, então enviei uma solicitação HTTP bruta e obtive os mesmos resultados:

[Rober@yue ~]$ nc rhodecode.mydomain.com 80
GET /%2F HTTP/1.1
Host: rhodecode.mydomain.com

HTTP/1.1 301 Moved Permanently
Date: Tue, 04 Mar 2014 00:07:26 GMT
Server: Apache/2.2.22 (Linux/SUSE)
Location: https://rhodecode.mydomain.com/error/HTTP_NOT_FOUND.html.var
Content-Length: 268
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://rhodecode.mydomain.com/error/HTTP_NOT_FOUND.html.var">here</a>.</p>
</body></html>

Veja o cabeçalho da localização na resposta. Por que o Apache está fazendo isso em vez de apenas alterar a solicitação para https ???

Desculpe pelo texto mudo da minha pergunta, mas eu queria dar o máximo de informação possível para que você possa me ajudar a depurar isso:)

Obrigado a todos antecipadamente!

Editar
Como sugerido, queria descobrir se o Rhodecode estava enviando os redirecionamentos. Então eu mudei meu script wsgi para o mostrado na documentação: http://modwsgi.readthedocs.org/en/latest/configuration-guides/running-a-basic-application.html#wsgi-application-script-file . Ele sempre retorna um "Hello World" sem a possibilidade de redirecionamento. Enviei uma solicitação bruta para o site com os mesmos resultados, então o Apache deve estar alterando a URL de alguma forma. Aqui está o resultado:

GET /%2F HTTP/1.1
Host: rhodecode.mydomain.com

HTTP/1.1 301 Moved Permanently
Date: Thu, 06 Mar 2014 04:23:31 GMT
Server: Apache/2.2.22 (Linux/SUSE)
Location: https://rhodecode.mydomain.com/error/HTTP_NOT_FOUND.html.var
Content-Length: 268
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://rhodecode.mydomain.com/error/HTTP_NOT_FOUND.html.var">here</a>.</p>
</body></html>

Mas quando eu envio uma URL normal (sem% 2F), ela redireciona OK:

GET /abffr HTTP/1.1
Host: rhodecode.mydomain.com

HTTP/1.1 301 Moved Permanently
Date: Thu, 06 Mar 2014 04:25:19 GMT
Server: Apache/2.2.22 (Linux/SUSE)
Location: https://rhodecode.mydomain.com/abffr
Content-Length: 244
Content-Type: text/html; charset=iso-8859-1

O Apache parece não gostar da coisa% 2F ...

    
por rober710 04.03.2014 / 03:52

2 respostas

0

Acontece que havia duas coisas que estavam causando esse erro. O primeiro é o valor padrão de AllowEncodedSlashes, dos docs :

With the default value, Off, URLs which contain encoded path separators (%2F for / and additionally %5C for \ on according systems) are refused with a 404 (Not found) error.

Descobri isso ativando o máximo de detalhamento nos logs do apache e descobri isso:

[Mon Mar 10 04:53:43 2014] [info] [client 172.17.1.49] found %2f (encoded '/') in URI (decoded='//'), returning 404

Assim, todas as minhas solicitações com% 2F foram rejeitadas. Além disso, eu tinha essa configuração que veio no meu servidor por padrão:

<IfModule mod_negotiation.c>
<IfModule mod_include.c>
    <Directory "/usr/share/apache2/error">
        AllowOverride None
        Options IncludesNoExec
        AddOutputFilter Includes html
        AddHandler type-map var
        Order allow,deny
        Allow from all
        LanguagePriority en cs de es fr it ja ko nl pl pt-br ro sv tr
        ForceLanguagePriority Prefer Fallback
    </Directory>

    ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
    ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
    ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
    ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
    ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
    ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
    ErrorDocument 410 /error/HTTP_GONE.html.var
    ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
    ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
    ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
    ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
    ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
    ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
    ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
    ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
    ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
    ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
</IfModule>
</IfModule>

Assim, sempre que um erro 404 foi enviado ao cliente, o filtro Inclui combinado com a diretiva ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var fez com que um redirecionamento fosse enviado ao navegador para http://rhodecode.mydomain.com/error/HTTP_NOT_FOUND.html.var
Você pode ver esse comportamento em meus registros de reescrita, onde a expressão a ser reescrita é inicializada com /error/HTTP_NOT_FOUND.html.var:

172.17.1.49 - - [10/Mar/2014:04:04:23 +0000] [rhodecode.mydomain.com/sid#7f98fedd7f00][rid#7f98f91fe7a0/initial/redir#1] (2) init rewrite engine with requested uri /error/HTTP_NOT_FOUND.html.var

Observe também que redirecion # 1 indica que ocorreu um redirecionamento interno. Então, mudei minha configuração para

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
AllowEncodedSlashes NoDecode

E alterou a diretiva ifmodule para

<IfModule !mod_include.c>

Portanto, nenhuma diretiva ErrorDocument é executada e tudo funcionou perfeitamente!
Desta vez, os registros de reescrita mostram o% 2F no URL e não ocorre nenhum redirecionamento:

172.17.1.49 - - [10/Mar/2014:04:55:40 +0000] [rhodecode.mydomain.com/sid#7f9fd1f83f00][rid#7f9fcc3a90a0/initial] (2) init rewrite engine with requested uri /%2F
    
por 16.03.2014 / 03:15
0

O RhodeCode também tem um sinalizador especial para informar que você quer forçar o uso de ssl, o que significa que todos os redirecionamentos iriam sempre para https.

Em sua alteração do sinalizador .ini:

force_ssl = true

    
por 28.08.2015 / 12:21