Apache: demande non sécurisée envoyée au port sécurisé… voulez rediriger

9

Préface

Premièrement: Une simple réécriture du port 80 -> du port 443 NE résoudra PAS ce problème. Dans presque toutes les questions précédentes, le fil de discussion, le fil de forum, etc., j'ai trouvé que c'était la première réponse ignorante et a été répétée plusieurs fois.

Deuxièmement: Oui, je sais que vous ne pouvez pas servir le trafic HTTP et HTTPS sur le même port. Ce n'est pas ça.

Scénario:

Serveur Apache hébergeant plusieurs sites via la multiplication de ports. Le port 80 dessert un site public. Le port 443 sert la version sécurisée de ce site.

Les ports 7443, 8443 et 9443 desservent chacun des sites distincts sécurisés par SSL.

Si un utilisateur tape l'URL ou reçoit un lien non valide, dites http: //hostname.tld: 7443 , la page ridicule suivante leur est donnée:

Message d'erreur Apache Bad Request

Au lieu du serveur, il suffit de les rediriger vers https: //hostname.tld: 7443 .

Ma question est, comment au nom du trou du cul de Zeus pouvez-vous modifier le comportement d'Apache ou ce message d'erreur pour rediriger automatiquement l'utilisateur?

Apache sert manifestement une demande non https (pour afficher ce message d'erreur) même s'il est configuré pour HTTPS. Il me semble remarquablement stupide de ne pas simplement faire la redirection par défaut, mais je peux comprendre pourquoi ils ont adopté le comportement qu'ils ont fait, même si je ne suis pas d'accord. Donc ma question est: pouvez-vous le changer? Ils gèrent l'erreur QUELQUE PART, et avec Apache étant la corne d'abondance de configuration qu'elle est, il va de soi qu'il existe une directive quelque part pour gérer ce comportement, mais je n'ai pas été en mesure de la trouver en plusieurs heures de bricolage jusqu'à présent.

Mise à jour:

J'ai tenté diverses choses, notamment:

  • en utilisant des ErrorDocument 400directives pour accéder à un CGI et à un script PHP qui envoient simplement des en Status 301- Locationtêtes. Il en résulte une page vierge. En utilisant ErrorDocument 400 https://hostname.tld:7443simplement, ce lien s'affiche sur la page.

  • L'utilisation de presque toutes les combinaisons de mod_rewriteI ou de Google peut arriver, y compris des déclarations générales qui dirigent entièrement le site; ceux-ci ne fonctionnent jamais . Littéralement, ils ne font rien. Je suppose qu'Apache est en train de commettre l'erreur ci-dessus avant même d'essayer de traiter les directives de réécriture.

Je ne peux pas utiliser de redirections basées sur le port, en raison de l'utilisation du port personnalisé. Je ne peux pas utiliser de redirections basées sur des scripts car elles ne sont jamais servies en raison de la non-correspondance http / https. Je suis presque prêt à attribuer cela à un bug ou à un comportement involontaire, mais quelqu'un a pensé à y insérer un message d'erreur très personnalisé, il n'a pas pris la peine de penser que vous voudriez peut-être simplement URL qu'ils fournissent déjà ?

peelman
la source
Daniel, C'était l'une des nombreuses questions que j'avais trouvées et des solutions que j'avais essayées avant de poster cette question. Je pense que le problème était le composant PHP, mais puisque la mise à jour de la réponse de @ hrunting fonctionne à merveille pour moi en ce moment, je ne vais pas y consacrer plus de temps que je ne l'ai déjà fait; du moins pas avant que je le doive.
peelman
2
vote positif pour la vidéo liée, il transmet parfaitement mes émotions
michele b

Réponses:

6

Je pense que c'est probablement un bug dans la façon dont Apache 2.2 et inférieur gère cette circonstance particulière.

Il semble qu'en cas d' 400 Bad Requesterreur de lecture SSL , Apache 2.2 ne renvoie pas le code de réponse HTTP ou les en-têtes, uniquement le corps de la réponse HTTP. Je teste en téléphonant au port 443 et en envoyant:

GET / HTTP/1.1

Le serveur renvoie immédiatement (pour moi):

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

Notez l'absence de code de réponse HTTP ou d'en-têtes HTTP.

Lorsque je fais cela sur un serveur Apache 2.4, j'obtiens:

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>

Si je configure une ligne ErrorDocument comme vous l'avez fait:

ErrorDocument 400 https://server.tld/

Ensuite, j'obtiens le code HTML pour une redirection 302, mais encore une fois, aucun des en-têtes. Sans le code de réponse de redirection 302 et l'en- Location:tête, le navigateur ne redirigera pas.

Essayez la mise à niveau vers Apache 2.4 et voyez si cela fonctionne. J'ai testé et confirmé avec au moins Apache 2.4.3, mais je n'ai pas fait l'effort de trouver exactement quand ce comportement a été mis à jour. Je soupçonne que dans la grande quantité de travail qu'ils ont fait en préparant 2.4, ils ont corrigé le comportement indésirable comme un effet secondaire.

Bogues Apache httpd pertinents:

MISE À JOUR

Vous pouvez forcer un bogue Apache à vous donner le comportement que vous souhaitez (la redirection) en demandant au script d'imprimer ses en-têtes (qui ne seront pas envoyés au client), puis de réimprimer manuellement les en-têtes que vous souhaitez. Voici un script Perl de base qui fonctionne sous 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

Vous devez savoir qu'il existe d'autres raisons pour lesquelles un 400 peut être généré en plus de simplement parler à un port SSL sans SSL. Le moyen le plus simple de le déterminer est de rechercher la HTTPSvariable d'environnement. S'il est défini, SSL a été négocié correctement et quelque chose d'autre provoque le 400 (ne faites pas l'astuce de double en-tête si c'est le cas). Si HTTPSn'est pas défini, renvoyez votre redirection comme ci-dessus.

chasse
la source
1
Saint. Merde. Réponse parfaite. Gracias.
peelman
Vous savez, en lisant ceci, je me dis: "Mec, ça craint vraiment si vous avez Apache 2.2 et que vous voulez ce genre de comportement de redirection." Je ne vais pas faire l'effort de trouver un deb Apache 2.4 approprié (ou faire le mien) pour mon système Ubuntu. Je parie que vous pouvez pirater une solution à partir de votre script PHP. Apache vide clairement la sortie vers le client, donc si vous retournez le contenu attendu spécifique, je parie que vous pouvez obtenir le comportement que vous recherchez sans mettre à niveau Apache. Essayez d'imprimer votre script PHP "HTTP / 1.1 302 Trouvé \ r \ nLocation : server.tld \ r \ n \ r \ n".
chasse
Le problème est qu'il ne semble pas que le script PHP soit en cours de traitement. Je dois noter que c'est actuellement assis sur Apache 2.2.22 sur Ubuntu Server 12.04. Et oui, ça craint vraiment, vraiment; surtout lorsque vous notez que dans ces rapports de bogues, ils semblent être complètement opposés, même en fournissant une option pour effectuer automatiquement la redirection, et il ne semble pas y avoir beaucoup d'espoir que 2.2 obtiendra jamais le correctif.
peelman
1
Et comme je l'ai dit ci-dessus, cela n'a tout simplement pas de sens pour moi pourquoi vous vous donnez la peine d'écrire ce message d'erreur, plutôt que de rediriger vers Secure (sérieusement, pourquoi ne pas simplement rediriger? Plus j'y pense, moins Je pense que c'est une mauvaise idée).
peelman
1
J'ai salué l'ensemble du système de fichiers à la recherche du texte de ce message sanglant pour voir si je peux d'où ils le lechent, au cas où je pourrais injecter une <javascriptbalise et avoir de la chance avec la redirection de piratage de cette façon, mais jusqu'à présent, non dé. Rien à ce sujet ne semble être géré d'une manière qui suit la génialité par ailleurs assez rigide d'Apache ...
peelman
-1

Vous pouvez résoudre ce problème avec mod-rewrite. Définissez une règle qui correspond à tout. Voir cette réponse sur Stackoverflow

trent
la source
Non, j'ai déjà essayé ça, ça ne marche pas. C'est comme s'il n'obtenait même pas les étapes ModRewrite parce qu'il frappait d'abord la non-correspondance http / https.
peelman
Hrm donc je suppose que vous avez commencé par le haut de votre fichier de configuration apache et que vous êtes descendu pour voir ce qu'il appelle
trent
J'ai pratiquement mémorisé tout le sites-availablerépertoire. Même si vous le redirigez simplement vers un non-sens, ou le redirigez vers un site différent, un port différent, etc., il ne fait que charger cette 400 mauvaise demande.
peelman