Apache: niepewne żądanie wysłane do bezpiecznego portu… chce się przekierować

9

Przedmowa

Po pierwsze: zwykły port 80 -> przepisanie portu 443 NIE naprawi tego. W prawie każdym poprzednim pytaniu, wątku pocztowym, wątku forum itp. Znalazłem, że była to pierwsza ignorancka odpowiedź i kilka razy papugowałem.

Po drugie: Tak, wiem, że nie możesz obsługiwać ruchu HTTP i HTTPS na tym samym porcie. To nie tak.

Scenariusz:

Serwer Apache hostujący wiele witryn poprzez mnożenie portów. Port 80 obsługuje witrynę publiczną. Port 443 obsługuje bezpieczną wersję tej witryny.

Porty 7443, 8443 i 9443 obsługują osobne witryny zabezpieczone protokołem SSL.

Jeśli użytkownik pomyli adres URL lub poda nieprawidłowy link, powiedz http: //nazwa_hosta.tld: 7443 , otrzyma następującą śmieszną stronę:

Komunikat o błędzie Apache Bad Request

Zamiast serwera po prostu przekierowuję je na https: //hostname.tld: 7443 .

Moje pytanie brzmi: w jaki sposób, w imię dziury Zeusa, możesz zmodyfikować zachowanie Apache lub ten komunikat o błędzie, aby automatycznie przekierować użytkownika?

Apache oczywiście obsługuje żądanie inne niż https (aby wyświetlić ten komunikat o błędzie), nawet jeśli jest skonfigurowany do HTTPS. Wydaje mi się niezwykle głupie, że nie tylko domyślnie przekierowuję, ale rozumiem, dlaczego zachowali się tak, jak oni, nawet jeśli się z tym nie zgadzam. Moje pytanie brzmi: czy możesz to zmienić? Obsługują błąd GDZIEKOLWIEK, a ponieważ Apache jest konfiguracją róg obfitości, jest oczywiste, że istnieje jakaś dyrektywa, która poradziłaby sobie z tym zachowaniem, ale do tej pory nie udało mi się go znaleźć przez kilka godzin majstrowania.

Aktualizacja:

Próbowałem różnych rzeczy, w tym:

  • używając ErrorDocument 400dyrektyw, aby dostać się do CGI i skryptu PHP, który właśnie wysyła Status 301i Locationnagłówki. Powoduje to, że strona jest pusta. Użycie ErrorDocument 400 https://hostname.tld:7443po prostu powoduje wyświetlenie tego linku na stronie.

  • Używając prawie każdej kombinacji mod_rewriteI lub Google, można wymyślić, w tym ogólne oświadczenia, które całkowicie kierują witryną; te nigdy nie działają. Dosłownie nic nie robią. Zastanawiam się, że Apache wykrywa powyższy błąd, zanim nawet spróbuje przetworzyć dyrektywy przepisujące.

Nie mogę używać przekierowań opartych na portach z powodu niestandardowego użycia portu. Nie mogę używać przekierowań opartych na skryptach, ponieważ nigdy nie są obsługiwane z powodu niezgodności http / https. Prawie jestem skłonny przypisać to błędowi lub niezamierzonemu zachowaniu, ale ktoś miał dość czasu, aby umieścić tam niestandardowy komunikat o błędzie, nie zawracał sobie głowy myśleniem, że może chcesz po prostu pojechać do Adres URL, który już podają ?

peelman
źródło
Zobacz zaakceptowaną odpowiedź zarówno
Daniel Vérité
Daniel, to było jedno z wielu pytań, które znalazłem i rozwiązań, które próbowałem przed opublikowaniem tego pytania. Myślę, że problemem był komponent PHP, ale ponieważ aktualizacja odpowiedzi @ hrunting działa teraz dla mnie pięknie, nie zamierzam poświęcać na to więcej czasu, niż mam; przynajmniej dopóki nie będę musiał.
peelman
2
głosowanie za dołączonym filmem doskonale przekazuje moje emocje
michele b

Odpowiedzi:

6

Myślę, że to prawdopodobnie błąd w tym, jak Apache 2.2 i niższe radzą sobie z tą konkretną okolicznością.

Wygląda na to, że w przypadku 400 Bad Requestbłędu odczytu SSL Apache 2.2 nie zwraca kodu odpowiedzi HTTP ani nagłówków, tylko treść odpowiedzi HTTP. Testuję przez telnetting do portu 443 i wysyłanie:

GET / HTTP/1.1

Serwer natychmiast zwraca (dla mnie):

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

Zwróć uwagę na brak kodu odpowiedzi HTTP lub nagłówków HTTP.

Kiedy robię to na serwerze Apache 2.4, otrzymuję:

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>

Jeśli skonfiguruję wiersz ErrorDocument tak jak ty:

ErrorDocument 400 https://server.tld/

Potem dostaję HTML dla przekierowania 302, ale znowu, żaden z nagłówków. Bez kodu odpowiedzi 302 i Location:nagłówka przeglądarka nie przekieruje.

Spróbuj zaktualizować do Apache 2.4 i sprawdź, czy to działa. Testowałem i potwierdziłem co najmniej Apache 2.4.3, ale nie starałem się znaleźć dokładnie, kiedy to zachowanie zostało zaktualizowane. Podejrzewam, że przy dużej ilości pracy, jaką wykonali przygotowując 2.4, poprawili niepożądane zachowanie jako efekt uboczny.

Istotne błędy httpd Apache:

AKTUALIZACJA

Możesz zmusić błędnego Apache'a, aby dał ci pożądane zachowanie (przekierowanie), każąc skryptowi wydrukować nagłówki (które nie zostaną wysłane do klienta), a następnie ręcznie wydrukować ponownie żądane nagłówki. Oto podstawowy skrypt Perla działający pod 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

Należy pamiętać, że istnieją inne powody, dla których 400 może zostać wygenerowane, poza rozmową z portem SSL bez SSL. Najłatwiejszym sposobem ustalenia tego jest poszukiwanie HTTPSzmiennej środowiskowej. Jeśli jest ustawiony, protokół SSL został poprawnie wynegocjowany i coś innego powoduje 400 (nie rób sztuczki z podwójnym nagłówkiem, jeśli tak jest). Jeśli HTTPSnie jest ustawiony, zwróć przekierowanie jak wyżej.

polowanie
źródło
1
Święty. Bzdury. Idealna odpowiedź. Gracias.
peelman
Wiesz, kiedy to czytam, myślę sobie: „Człowieku, naprawdę jest do kitu, jeśli masz Apache 2.2 i chcesz tego rodzaju przekierowania”. Nie zamierzam podejmować wysiłku, aby znaleźć odpowiedni deb (Apache 2.4) (lub zrobić własny) dla mojego systemu Ubuntu. Założę się, że możesz zhakować rozwiązanie ze skryptu PHP. Apache najwyraźniej po prostu wysyła dane wyjściowe do klienta, więc jeśli zwrócisz konkretną oczekiwaną treść, założę się, że możesz uzyskać zachowanie, którego szukasz, bez aktualizacji Apache. Spróbuj wydrukować skrypt PHP „Znaleziono HTTP / 1.1 302 \ r \ nLokalizacja: server.tld \ r \ n \ r \ n”.
polowanie
Problem polega na tym, że nie wydaje się, aby skrypt PHP był przetwarzany. Powinienem zauważyć, że obecnie jest to wersja Apache 2.2.22 na Ubuntu Server 12.04. I tak, to naprawdę bardzo do bani; szczególnie, gdy zauważysz, że w tych raportach o błędach wydaje się, że są one całkowicie ustawione wbrew nawet możliwości automatycznego przekierowania, i nie wydaje się, aby istniała duża nadzieja, że ​​2.2 otrzyma naprawę.
peelman
1
I jak powiedziałem wyżej, po prostu nie ma dla mnie sensu, dlaczego robisz tyle trudu, aby napisać ten komunikat o błędzie, zamiast przekierowywać na bezpieczne (poważnie, dlaczego nie po prostu przekierować? Im więcej o tym myślę, tym mniej Myślę, że to zły pomysł).
peelman
1
Przeszukałem cały system plików, szukając tekstu tej cholernej wiadomości, aby zobaczyć, czy mogę, skąd się go wysysa, przy okazji mogłem wstrzyknąć <javascripttag i mieć szczęście z przekierowaniem hakowania w ten sposób, ale jak dotąd nie kostka do gry. Wydaje się, że nic w tym zakresie nie jest obsługiwane w sposób, który byłby zgodny z dość sztywną
niesamowitością
-1

Możesz to naprawić za pomocą mod-rewrite. Ustaw regułę, aby dopasować wszystko. Zobacz tę odpowiedź na Stackoverflow

trent
źródło
Nie, już tego próbowałem, to nie działa. To tak, jakby nawet nie dostał się do kroków ModRewrite, ponieważ najpierw uderzył w niezgodność http / https.
peelman
Hrm, więc zakładam, że zacząłeś od początku pliku konfiguracyjnego apache i zacząłeś schodzić w dół, aby zobaczyć, jak to się nazywa
trent
Praktycznie zapamiętałem cały sites-availablekatalog. Nawet jeśli przekierujesz go do bzdur lub przekierujesz na inną stronę, inny port itp., Po prostu ładuje 400 błędnych żądań.
peelman