Apache: solicitação insegura enviada à porta segura ... deseja redirecionar

9

Prefácio

Primeiramente: Uma simples reescrita da porta 80 -> porta 443 NÃO corrigirá isso. Em quase todas as perguntas anteriores, discussão por e-mail, discussão no fórum etc., descobri que essa foi a primeira resposta ignorante e foi repetida várias vezes.

Segundo: Sim, eu sei que você não pode servir tráfego HTTP e HTTPS na mesma porta. Isto não é isso.

Cenário:

Servidor Apache hospedando vários sites via multiplicação de portas. A porta 80 serve um site público. A porta 443 serve a versão segura desse site.

As portas 7443, 8443 e 9443 servem cada site separado protegido por SSL.

Se um usuário digitar incorretamente o URL ou receber um link inválido, diga http: //hostname.tld: 7443 , ele receberá a seguinte página ridícula:

Mensagem de erro de solicitação incorreta do Apache

Em vez de o servidor apenas os redirecionar para https: //hostname.tld: 7443 .

Minha pergunta é: como, em nome do buraco do Zeus, você pode modificar o comportamento do Apache ou esta mensagem de erro para redirecionar o usuário automaticamente?

O Apache está obviamente atendendo a uma solicitação não https (para exibir essa mensagem de erro), mesmo que esteja configurado para HTTPS. Parece-me incrivelmente estúpido não apenas fazer o redirecionamento por padrão, mas posso entender por que eles foram com o comportamento que fizeram, mesmo que eu não concorde. Então, minha pergunta é: você pode mudar isso? Eles estão lidando com o erro EM ALGUM LUGAR E, com o Apache sendo a cornucópia de configuração que é, é lógico que exista alguma diretiva em algum lugar para lidar com esse comportamento, mas não consegui encontrá-lo em várias horas de ajustes até agora.

Atualizar:

Eu tentei várias coisas, incluindo:

  • usando ErrorDocument 400diretivas para obter um script CGI e PHP que apenas envia Status 301e Locationcabeçalhos. Isso resulta em uma página em branco. Usar ErrorDocument 400 https://hostname.tld:7443simplesmente resulta na exibição desse link na página.

  • O uso de quase todas as combinações entre mod_rewriteeu ou o Google pode ser feito, incluindo declarações gerais que direcionam o site inteiramente; estes nunca funcionam. Literalmente, eles não fazem nada. Estou supondo que o Apache esteja chutando o erro acima antes mesmo de tentar processar as diretivas de reescrita.

Não posso usar redirecionamentos baseados em porta, devido ao uso personalizado da porta. Não posso usar redirecionamentos baseados em script porque eles nunca são exibidos devido à incompatibilidade http / https. Estou quase disposto a atribuir isso a um bug ou a um comportamento não intencional, mas alguém teve a intenção de colocar uma mensagem de erro muito personalizada lá, não se incomodou em pensar que talvez você queira apenas ir ao mercado URL que eles já estão fornecendo ?

peelman
fonte
Veja a resposta aceita para ssl e não-ssl em porta única
Daniel Vérité
Daniel, essa foi uma das muitas perguntas que encontrei e as soluções que tentei antes de postar essa pergunta. Acho que o problema era o componente PHP, mas como a atualização da resposta da @ hrunting está funcionando muito bem para mim no momento, não vou dedicar mais tempo do que já tenho; pelo menos não até que eu precise.
112713 peelman
2
upvote para o vídeo vinculado, ele transmite as minhas emoções perfeitamente
michele b

Respostas:

6

Eu acho que isso é provavelmente um bug na forma como o Apache 2.2 e inferior lida com essa circunstância específica.

Parece que em um 400 Bad Requesterro de leitura SSL , o Apache 2.2 não retorna o código de resposta HTTP ou os cabeçalhos, apenas o corpo da resposta HTTP. Eu testo telnetando para a porta 443 e enviando:

GET / HTTP/1.1

O servidor retorna imediatamente (para mim):

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
Reason: You're speaking plain HTTP to an SSL-enabled server port.<br />
Instead use the HTTPS scheme to access this URL, please.<br />
<blockquote>Hint: <a href="https://server.tld/"><b>https://server.tld/</b></a></blockquote></p>
</body></html>

Observe a falta de um código de resposta HTTP ou de qualquer cabeçalho HTTP.

Quando faço isso em um servidor Apache 2.4, recebo:

HTTP/1.1 400 Bad Request
Date: Sun, 10 Feb 2013 00:47:23 GMT
Server: Apache/2.4.3 (Unix) OpenSSL/1.0.0g
Content-Length: 462
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
Reason: You're speaking plain HTTP to an SSL-enabled server port.<br />
Instead use the HTTPS scheme to access this URL, please.<br />
</p>
<hr>
<address>Apache/2.4.3 (Unix) OpenSSL/1.0.0g Server at server.tld Port 443</address>
</body></html>

Se eu configurar uma linha ErrorDocument como você:

ErrorDocument 400 https://server.tld/

Então eu recebo o HTML para um redirecionamento 302, mas, novamente, nenhum dos cabeçalhos. Sem o código de resposta de redirecionamento 302 e o Location:cabeçalho, o navegador não redirecionará.

Tente atualizar para o Apache 2.4 e veja se funciona. Eu testei e confirmei com pelo menos o Apache 2.4.3, mas não fiz o esforço de descobrir exatamente quando esse comportamento foi atualizado. Eu suspeito que na grande quantidade de trabalho que eles fizeram na preparação do 2.4, eles corrigiram o comportamento indesejável como efeito colateral.

Erros httpd relevantes do Apache:

ATUALIZAR

Você pode forçar um Apache com erros a fornecer o comportamento que você deseja (o redirecionamento) fazendo com que o script imprima seus cabeçalhos (que não serão enviados ao cliente) e, em seguida, imprima manualmente novamente os cabeçalhos desejados. Aqui está um script Perl básico que funciona no Apache 2.2.22:

#!/usr/bin/perl

use strict;
use CGI;

my $q = CGI->new();

# this will cause Apache to handle the response properly, but is meaningless otherwise
print $q->redirect("https://localhost/");

# this actually performs the redirect
print "HTTP/1.1 302 Found\r\n";
print "Location: https://localhost/\r\n";
print "\r\n";

# you can do whatever you want here; this will be the HTML body

Você deve estar ciente de que existem outros motivos pelos quais um 400 pode ser gerado, além de apenas conversar com uma porta SSL sem SSL. A maneira mais fácil de determinar isso é procurar a HTTPSvariável de ambiente. Se estiver definido, o SSL foi negociado corretamente e outra coisa está causando o 400 (não faça o truque de cabeçalho duplo, se for esse o caso). Se HTTPSnão estiver definido, retorne seu redirecionamento como acima.

assustador
fonte
1
Piedosos. Porcaria. Resposta perfeita. Gracias.
10263 peelman
Você sabe, enquanto eu leio isso, penso comigo mesmo: "Cara, é realmente péssimo se você tem o Apache 2.2 e deseja esse tipo de comportamento de redirecionamento". Não vou me esforçar para encontrar uma deb apropriada do Apache 2.4 (ou criar minha própria) para o meu sistema Ubuntu. Aposto que você pode hackear uma solução do seu script PHP. O Apache claramente apenas descarta a saída para o cliente; portanto, se você retornar o conteúdo esperado específico, aposto que você pode obter o comportamento que procura sem atualizar o Apache. Tente fazer com que seu script PHP imprima "HTTP / 1.1 302 encontrado \ r \ nLocalização : server.tld \ r \ n \ r \ n".
Hrunting
O problema é que não parece que o script PHP esteja sendo processado. Devo observar que atualmente está no Apache 2.2.22 no Ubuntu Server 12.04. E sim, é realmente muito ruim; especialmente quando você observa que nesses relatórios de bugs, eles parecem estar completamente configurados, inclusive fornecendo uma opção para fazer o redirecionamento automaticamente, e não parece haver muita esperança de que o 2.2 esteja recebendo a correção.
22413 peelman
1
E, como eu disse acima, simplesmente não faz sentido para mim por que você passa pelo problema de escrever essa mensagem de erro, em vez de redirecionar para o seguro (sério, por que não apenas redirecionar? Quanto mais eu penso sobre isso, menos Eu acho que é uma má ideia).
10263 peelman
1
Eu dei uma olhada em todo o sistema de arquivos, procurando o texto dessa mensagem sangrenta, para ver se consigo de onde eles a estão drenando, com a possibilidade de injetar uma <javascripttag e ter sorte com o redirecionamento de hackers dessa maneira, mas até agora, não dados. Nada sobre este parece ser tratados de uma forma que segue a grandiosidade caso contrário bastante rígida Apache ...
peelman
-1

Você pode corrigir isso com reescrita mod. Defina uma regra para corresponder a qualquer coisa. Veja esta resposta no Stackoverflow

trent
fonte
Não, eu já tentei isso, não funciona. É como se nem chegasse às etapas do ModRewrite, porque atingia primeiro a incompatibilidade http / https.
22413 peelman
Hrm assim que eu supor que você começou a partir do topo do que você apache arquivo de configuração e trabalhou seu caminho para baixo para ver o que está chamando
Trent
Eu praticamente memorizei o sites-availablediretório inteiro . Mesmo se você apenas o redirecionar para bobagem, ou redirecioná-lo para um site diferente, porta diferente etc., ele continuará carregando essa 400 Solicitação inválida.
22813 peelman