Blockieren Sie den direkten Zugriff auf die Webserver-IP über HTTPS

8

Ähnlich wie bei dieser und dieser Frage möchte ich Benutzer daran hindern, die IP für den Zugriff auf meinen Server zu verwenden.

Für HTTP (Port 80) funktioniert dies einwandfrei, nicht jedoch für HTTPS. Benutzer können also weiterhin https://<myip>auf den Webserver zugreifen, und nginx gibt das Standardzertifikat zurück. Übrigens verwende ich HTTP2 in meinen "üblichen" Serverblöcken (mit meinen Domainnamen), also verwende ich:

listen 443 ssl http2;
listen [::]:443 ssl http2;

Ich habe versucht, den HTTPS-IP-Zugriff jetzt zu blockieren:

server {
   listen 443 ssl;
   listen [::]:443 ssl;

   server_name _;
   return 444;
}

Leider blockiert dies alle HTTPS-Anforderungen, unabhängig davon, ob die Domain verwendet wird oder nicht. Ich weiß, dass es möglicherweise notwendig ist, Nicht-SNI-Clients zu blockieren, da diese natürlich nicht den verwendeten Domänennamen an den Server liefern, also bin ich damit einverstanden. (Ich meine, Kunden, die SNI nicht unterstützen, sind sowieso alt ...)

Ich ziehe es im Allgemeinen vor, dies in Nginx zu blockieren, aber wenn Sie einige Ideen zum Blockieren auf Firewall-Ebene (iptables) haben, würde ich diese auch gerne schätzen. Und wenn Sie argumentieren möchten, warum das Blockieren mit iptables besser ist, können Sie dies auch tun und mich davon überzeugen, auch HTTP-Anfragen (oder alle anderen) an die IP zu blockieren. Im Allgemeinen ist das Trennen der Verbindung in Ordnung (wie es der Nginx-Statuscode 444 tut).

Es gibt jedoch eine Anforderung: Ich möchte die IP-Adresse des Servers in der Konfiguration nicht explizit erwähnen, da es sich um eine dynamische IP handelt und der Server einen dynamischen DNS-Dienst verwendet.

Kurz gesagt, hier ist, was ich erreichen möchte:

  • Zugriff über IP blockieren
  • Zugriff über Domainnamen zulassen
  • Es ist in Ordnung, Nicht-SNI-Clients zu blockieren
  • Es ist in Ordnung, hierfür eine Firewall-Blockierung zu verwenden
  • Das Trennen der Verbindung ist in Ordnung
  • ohne die IP-Adresse des Servers zu erwähnen
  • Keine Offenlegung des Domainnamens über HTTPS

Bearbeiten: Ein weiterer fehlgeschlagener Versuch. Ich habe versucht, diesem Vorschlag zu folgen und dieses Konfigurations-Snippet zu verwenden, was logischerweise als eine gute Sache erscheint:

if ($host != "example.com") {
        return 444;
}

Grundsätzlich funktioniert es auch, aber wenn ich auf "https: //" zugreife, sehe ich, dass nginx zuerst bereits das HTTPS-Zertifikat (das den Domänennamen enthält) sendet, und erst wenn ich die Verbindungswarnung überspringe, sehe ich, dass es den Zugriff blockiert. Dies ist logisch, da nginx den Host-Header nur lesen kann, wenn die HTTPS-Verbindung besteht. Zu diesem Zeitpunkt sendet nginx jedoch bereits das Serverzertifikat mit dem Domänennamen, sodass ein Benutzer jetzt den Domänennamen hat und die Verbindung über die gesamte IP-Adresse wiederherstellen kann Blockieren nutzlos. Ich bin auch ein bisschen besorgt über den Leistungsaspekt dieser Lösung, da Nginx den Host-Header für jede Anfrage überprüft. Daher suche ich hier immer noch nach einer Lösung.

rugk
quelle
Bitte bearbeiten Sie Ihren Beitrag so, dass er nginx.conf und die vollständige Konfiguration für jeden Server enthält. Etwas, das Sie für nicht relevant halten, könnte sein.
Tim
Was ist das eigentliche Problem, das Sie lösen möchten? Leute, die den Namen des Servers sehen?
Joshua DeWald
"Was ist das eigentliche Problem, das Sie lösen wollen?" - Personen, die auf die IP meines Servers zugreifen, um herauszufinden, welche Domain verwendet wird. Also eine Art "Reverse DNS" -Vorbeugung. (obwohl dies natürlich nichts mit
DNS
Haben Sie Glück, hier eine Lösung zu finden? Ich habe auch dieses Problem.
Abarax
irgendein Update, Leute?
Phung D. An

Antworten:

8

Heute bin ich auf dasselbe Problem mit diesem Block gestoßen:

server {
  listen 443 ssl default_server;
  server_name <SERVER-IP>;
  return 444;
}

In den Nginx-Protokollen steht:

Beim Server, der während des SSL-Handshakes den SSL-Port überwacht, ist kein "ssl_certificate" definiert

Wie Sie bereits erwähnt haben, scheint dies auch die anderen Serverblöcke zu deaktivieren. Es ist möglich, dies mithilfe eines (selbstsignierten) Zertifikats für die Server-IP-Adresse zu beheben. Ich habe dies mit openssl gemacht:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt -subj '/CN=<SERVER-IP>'

Ändern Sie dann den Serverblock in:

server {
    listen 443 ssl default_server;
    server_name <server-ip>;
    ssl_certificate         /path/to/certificate.crt;
    ssl_certificate_key     /path/to/privateKey.key;
    return 444;
}

Wenn jemand die SERVER-IP über https verwendet, um auf den Server zuzugreifen, zeigt nginx das (selbstsignierte) Zertifikat und NICHT das Domain-Name-Zertifikat an, das Sie ausblenden möchten.

Übrigens, machen Sie Ihren Server-Block-with-IP zum Standard-Server. Auf diese Weise erhält ein Client mit deaktivierter SNI das IP-Zertifikat und NICHT das Domain-Name-Zertifikat. Dies kann auch mit openssl getestet werden (die Option -servername, mit der SNI aktiviert wird, wird weggelassen):

openssl s_client -connect <SERVER-IP>:443
BvE
quelle
Hört sich zuerst gut an, aber beachten Sie, dass es gegen die Anforderung "ohne Angabe der IP-Adresse des Servers" verstößt. Wenn Sie dynamisches DNS verwenden, können Sie dies nicht tun.
Rugk
@rugk lass CN einfach leer. -subj '/ CN ='
bin456789
Könnte auch mit Servername _ verwendet werden;
Intika
Das funktioniert total. Vielen Dank.
Shinebayar G
2

Versuchen Sie dies - das default_server-Bit ist der wichtige Teil. Wenn es nicht funktioniert, aktualisieren Sie bitte Ihre Frage mit der Konfiguration für andere Server, die 443 / SSL abhören.

server {
  listen 443 ssl default_server;
  listen [::]:443 ssl default_server; # not sure if you want/need it here as well. Try both ways.

 server_name _;
 return 444;
}
Tim
quelle
Danke, wusste nichts über diesen "default_server". Die HTTP-Lösung funktionierte auch ohne sie. Aber das hier funktioniert nicht. Es werden weiterhin alle HTTPS-Anforderungen blockiert. Ich habe bereits die Conf für andere Server erwähnt: Im Grunde ist es listen 443 ssl http2;.
Rugk
2
default_server wird empfohlen, da es nginx mitteilt, was zu tun ist, anstatt sich auf nginx-Standardeinstellungen zu verlassen, die sich in Zukunft ändern könnten.
Tim