nginx:正確に指定されたSSLサーバーブロックがすべてのSSLのキャッチオールとして機能するのを防ぐ方法


17

多くの仮想サーバーを備えたWebサーバーがあります。そのうちの1つのみがSSLです。問題は、SSLをリッスンするキャッチオールサーバーブロックがないため、他のサイトへのhttps要求はすべて1つのSSLブロックによって処理されることです。

基本的に、私の構成は次のようになります。

# the catch all
server {
  listen 80 default;

  # I could add this, but since I have no default cert, I cannot enable SSL,
  # and this listen ends up doing nothing (apparently).
  # listen 443; 

  server_name _;
  # ...
}

# some server
server {
  listen 80;
  server_name server1.com;
  # ...
}

# some other server ...
server {
  listen 80;
  server_name server2.com;
  # ...
}

# ... and it's https equivalent
server {
  listen 443;
  ssl on;
  server_name server2.com;
  # ...
}

443にはデフォルトのリスナーがないため、次のようなリクエストhttps://server1.comserver2.comhttpsブロックによって処理されます。これがためにロジックを次のserver_nameのドキュメント。

一致するものがない場合、構成ファイル内のサーバー{...}ブロックが次の順序に基づいて使用されます。

  1. [default | default_server]としてマークされた、一致するlistenディレクティブを持つサーバーブロック
  2. 一致するlistenディレクティブを持つ最初のサーバーブロック(または暗黙的なlisten 80;)

この問題の推奨解決策は何ですか?443でリッスンして不正な要求を処理できるように、catch all serverブロックのダミー証明書を設定する必要がありますか?ホスト名が完全に一致することを強制するパラメータがありますserverか?


ユーザーがhttpsを使用して他のサイトにアクセスしようとすると、どうなりますか?
デビッドシュワルツ

理想的には、ホスト名が一致しない限り、nginxでhttpsをまったく提供しないか、同じホストでhttpにリダイレクトするかのいずれかです。
-numbers1311407

回答:


9

理想的には、ホスト名が一致しない限り、nginxでhttpsをまったく提供しないか、同じホストでhttpにリダイレクトするかのいずれかです。

どちらも不可能です。https://foo.example.com/にアクセスするクライアントからの接続は、名前の1つとして「foo.example.com」を含むSSL証明書以外では受け入れられません。SSL接続が受け入れられるまでリダイレクトする機会はありません。

各サイトをSSL用に構成する場合、証明書エラーをクリックするユーザーは、要求したサイトを取得します。エラーページのみを提供するSSLの「すべてをキャッチ」サイトを構成し、SSLをサポートすることになっている1つのサイトの名前ベースの仮想ホスティングを構成する場合、エラーページをクライアントに提供できます。

SSLとHTTPの仮想ホスティングはうまく連携しません。


これはドキュメントを読んだ後に集めたものです。私は何かを逃したことを望んでいました。SSLの警告はまったく気にしません。私はちょうど誰かが入力したくないserver1.comをにnginxの言うする方法は本当にありません自体がserver2.com ...のホームページを見て、見つからない、要求を受け入れますか?
numbers1311407

要求を受け入れない場合、最初のサイトは機能しません。ユーザーがアクセスしようとしているサイトを見つけるために、リクエストを受け入れる必要があります。
デビッドシュワルツ

2
foo.example.comにアクセスするクライアントからの接続は、名前の1つとして「foo.example.com」を持つSSL証明書以外では受け入れられません。」-これは正しくありません。サーバーは要求を受け入れ、要求されたDNがサーバー証明書DNと一致することを確認するのはクライアント次第です。
ColinM

4

行う唯一の方法は、自己署名SSL証明書を作成し、それを使用して着信https要求の制御を取得することです。この投稿で概説したいくつかの簡単な手順で、自己署名SSL証明書を作成できます。

ファイル名がserver.crtの自己署名証明書を作成するとします。次に、nginx設定に次を追加します。

server {
    listen  443;

    ssl    on;
    ssl_certificate         /etc/nginx/ssl/server.crt;
    ssl_certificate_key     /etc/nginx/ssl/server.key;

    server_name server1.com;

    keepalive_timeout 60;
    rewrite ^       http://$server_name$request_uri? permanent;
}

ブラウザのSSL警告メッセージは引き続き表示されますが、少なくとも次に何が起こるかを制御できます。


1
私はこれに賛同する。信頼されていない証明書に関する警告メッセージがブラウザに表示されるという問題がありますが、ユーザーがhttps:// <ip-address>にアクセスして、実際の仮想ホストのいずれか(無効なホスト名が一致しないため)、無効な自己署名ダミー証明書を提供する方が良いでしょう。そのようなことは、「ここには何も見当たらず、別のホストからの証明書すらありません」と伝えます。
ダニエルF

2

catch-allサーバーブロックを追加し、ステータスコード444を返します。データを送信する前に接続を閉じるようにnginxに指示します。

server {
    listen 443 default_server ssl;
    server_name _;
    return 444;
}

1

最近では、TLSサーバー名表示拡張機能(SNI、RFC 6066)を使用できます。HTTPSリスナーは、適切な証明書を提供する前にドメイン名を認識できます。

これは、すべてのドメインの証明書が必要であることを意味し、SNIを使用して他のドメインのいずれかを認識する場合、サーバー名が必要な単一のものと一致しない限り、HTTP非暗号化バージョンへのHTTP 301リダイレクトを使用できます暗号化。

Sginの詳細については、nginxのドキュメントhttp://nginx.org/en/docs/http/configuring_https_servers.htmlで入手できます。


0

要求されたホスト名をhttp {}ブロック内の有効なホスト名にマップします。

map $ssl_server_name $correct_hostname_example {
  default 0;
  example.com 1;
  www.example.com 1;
}

そして、server {}ブロックで間違ったホスト名を持つ接続を強制終了します:

if ($correct_hostname_example = 0) {
  return 444;
}

複数のサーバーブロックに必要な複数のマップを使用します。接続は証明書の1つを使用して確立されますが、この最後のブロックがSSLを提供するすべてのサーバーブロックに存在する場合、無効なホスト名との接続を効果的に「ブロック」します。最初のサーバーブロックでのみ必要な場合がありますが、すべてのサーバーブロックに追加すると、順序が問題になりません。

$ssl_server_name変数は、nginxの1.7以上に存在しています。


0

これは私が問題を解決した方法です:

  1. 自己署名証明書を作成します。

openssl req -nodes -x509 -newkey rsa:4096 -keyout self_key.pem -out self_cert.pem -days 3650

  1. NginXが見つけられる場所にコピーします:

cp self*.pem /etc/nginx/ssl/

  1. キャッチオールルートを設定します。
server {
    listen 443 default_server ssl;

    ssl on;
    ssl_certificate /etc/nginx/ssl/self_cert.pem;
    ssl_certificate_key /etc/nginx/ssl/self_key.pem;

    return 301 http://$host;
}

これが何をするか:それそれ自身の証明書を持っていないサーバーであなたに警告(それを回避する方法はありません)を与えますが、警告は間違った証明書名を言いません。ユーザーが「とにかく訪問」をクリックすると、入力したサイトの非SSLバージョンにリダイレクトされます。

警告

SLL対応サイトでのみ定義されているwww.example.com(定義されていないexample.com)場合、キャッチオールルートはhttps://example.com自己署名証明書と対応する警告を提供することになります。


-2

httpにリダイレクトします:

server {
    listen       443;
    server_name  *.com;
    rewrite        ^ http://$host$request_uri? permanent;
}    

404を返す:

server {
    listen       443;
    server_name  *.com;
    return 404;
}    

1
SSLトンネルを確立する必要があるため、HTTPリダイレクトが発生する前にSSL警告が発生します。David Schwartzの受け入れられた回答を参照してください。
cjc
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.