nginxがドメイン名に応答するのはなぜですか?


139

私はnginxをRuby / Sinatraアプリで稼働させており、すべて順調です。しかし、私は今、同じサーバーから2番目のアプリケーションを実行しようとしているときに、何か奇妙なことに気付きました。まず、これが私のnginx.confです。

pid /tmp/nginx.pid;
error_log /tmp/nginx.error.log;

events {
  worker_connections 1024;
  accept_mutex off;
}

http {
  default_type application/octet-stream;
  access_log /tmp/nginx.access.log combined;

  sendfile on;
  tcp_nopush on;
  tcp_nodelay off;

  gzip on;
  gzip_http_version 1.0;
  gzip_proxied any;
  gzip_min_length 500;
  gzip_disable "MSIE [1-6]\.";
  gzip_types text/plain text/xml text/css
             text/comma-separated-values
             text/javascript application/x-javascript
             application/atom+xml;

  upstream app {
    server unix:/var/www/app/tmp/sockets/unicorn.sock fail_timeout=0;
  }

  server {
    listen 80;
    client_max_body_size 4G;
    server_name FAKE.COM;

    keepalive_timeout 5;

    root /var/www/app/public;

    location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;

      if (!-f $request_filename) {
        proxy_pass http://app;
        break;
      }
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /var/www/app/public;
    }
  }
}
                                                          68,0-1        B

server_nameがに設定されFAKE.COMていることに注目してください。サーバーは、他のドメイン名を介してそのサーバーにヒットするすべてのホストに応答しています。特定のサーバーがリクエストにのみ応答するようにするにはどうすればよいFAKE.COMですか?


listen fake.com | something.com:80 このコマンドは、ないフィルタserver_name
Alexei Martchenko 2016年

回答:


202

nginx設定の最初のサーバーブロックは、特定のサーバーブロックがないサーバーにヒットするすべてのリクエストのデフォルトです。

したがって、設定では、実際のドメインがREAL.COMであると想定して、ユーザーが入力すると、サーバーに解決されます。このセットアップ用のサーバーブロックがないため、FAKE.COMのサーバーブロックが最初になります。サーバーブロック(この場合はサーバーブロックのみ)がその要求を処理します。

このため、適切なNginx構成には、特定のドメインの他のサーバーをフォローする前に、デフォルトの特定のサーバーブロックがあります。

# Default server
server {
    return 404;
}

server {
    server_name domain_1;
    [...]
}

server {
    server_name domain_2;
    [...]
}

**編集**

一部のユーザーはこの例に少し混乱しているようで、単一のconfファイルなどに制限されていると思います。

上記はOPが必要に応じて開発する簡単な例であることに注意してください。

私は個人的にこれと同じように個別のvhost confファイルを使用しています(CentOS / RHEL):

http {
    [...]
    # Default server
    server {
        return 404;
    }
    # Other servers
    include /etc/nginx/conf.d/*.conf;
}

/etc/nginx/conf.d/ メインのnginx.confファイルのサーバーブロックの後に含まれるdomain_1.conf、domain_2.conf ... domain_n.confが含まれます。これは常に最初であり、default_serverで上書きされない限り、常にデフォルトになります。他の場所での指令。

この場合、他のサーバーのconfファイルのファイル名のアルファベット順は関係ありません。

さらに、この配置により、複数のデフォルトを定義できるという点で、柔軟性が大幅に向上します。

私の特定のケースでは、内部インターフェイスのポート8080でのみApacheをリッスンしており、ApacheにPHPおよびPerlスクリプトをプロキシします。

ただし、Apacheが標準のポート80で実行されていないことを検出して「助け」ようとするため、添付された出力htmlに「:8080」のリンクを返す2つの個別のアプリケーションを実行します。

これにより、外部インターフェイスからApacheに到達できず、リンクがポート80を指す必要があるため、リンクが無効になるという問題が発生します。

このようなリクエストをリダイレクトするために、ポート8080のデフォルトサーバーを作成することで、これを解決します。

http {
    [...]
    # Default server block for undefined domains
    server {
        listen 80;
        return 404;
    }
    # Default server block to redirect Port 8080 for all domains
    server {
        listen my.external.ip.addr:8080;
        return 301 http://$host$request_uri;
    }
    # Other servers
    include /etc/nginx/conf.d/*.conf;
}

通常のサーバーブロックの何もポート8080でリッスンしないため、リダイレクトのデフォルトサーバーブロックは、nginx.conf内での位置に基づいて、そのようなリクエストを透過的に処理します。

実際にはそのようなサーバーブロックが4つありますが、これは単純化された使用例です。


1
Nginxは大文字と小文字を区別する必要があります。「サーバー」はサーバーで、「リターン」はリターンである必要があります。これにより、このコードをコピーするときのいくつかの問題が解消されることを願っています。
Capaj 2013

2
静的、Oleg Neumyvkinの回答を参照してください-サイトで利用可能な複数の設定ファイルがある場合、アルファベット順で最初のファイルの最初のサーバーがデフォルトです。これが問題になるのではないかと思います。また、多くのディストリビューションは再起動する前に「nginx -t」を実行して設定をテストします-再起動を妨げるエラーが発生する可能性があります。
jwhitlock 2013

2
これは不完全であり、受け入れられた答えではありません。これを機能させるには、listenディレクティブからdefault_serverを削除する必要もあります。
Ben

@benまず、OPの問題の例に「default_server」がなかったため、その質問の詳細に合わせて回答が調整されました。第二に、最初の定義済みサーバーをデフォルトにするための指示に従って、誰もが別のサーバーの場所にdefault_serverを定義する理由は私を超えています。いずれの場合でも、default_serverが明確に定義されている場合、このQ / Aセットは、発生する可能性のある問題を解決するために参照する必要があるものではありません。
Dayo

1
@Dayoあなたは、OPによって投稿された特定の構成に対処したことは正しいです。しかし、質問の完全な回答を得るには、default_serverについて言及する必要があると思います。答えを読んで、default_serverがそれをどのように妨害するかを理解していない可能性があります。一部のディストリビューションではdefault_serverがファイルで定義されて出荷されているため、ユーザーにはわかりにくい可能性があるため、さらに可能性が高くなります。
ベン

61

あなたは、デフォルトのサーバーが必要ですキャッチオールを、あなたは返すことができ404返すことによって、すべてではない応答(一部の帯域幅を節約します)に、より良いまたは444単に近くに接続し、戻り何もすることをnginxの特定のHTTPレスポンスであります

server {
    listen       80  default_server;
    server_name  _; # some invalid name that won't match anything
    return       444;
}

nginx 1.8.0のために私のために働きました。server_name _;私はnginxのための以前のバージョンではありませんでしたが、それが働きました。新しいnginxバージョンでは、が必要なようですserver_name _;。ありがとう
ダニエル、2015年

解決しました。セミコロンを忘れました; _;
user1201917 2016

2
@iTech:何らかの理由で、すべてのリクエストに対して444を返しています。手がかりはありますか?
Divick 2017年

に関するすばらしいヒント444であり、エラーコードを返すよりもはるかに明確な解決策です。
qqilihq 2017年

1
証明書/キーを指定することが重要です。そうしないと、以下の回答で@AndreyTが指摘しているように、すべてのSSL接続が一致して失敗します。
Mark Fletcher、

35

他のどの回答でも問題を解決できませんでした。ホストが一致するかどうかを確認し、一致しない場合は403を返すことで問題を解決しました。(Webサーバーのコンテンツを指すランダムなWebサイトがありました。検索ランクを乗っ取ろうとしていると思います)

server {
    listen 443;
    server_name example.com;

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

    ...
}


1
同等のディレクティブを持たない変数をテストする必要がある場合など、ifの使用を避けられない場合があります。
エドワード

4
@Esolitos文字通りその記事の3行目は、このユースケースは問題ないと言っています。注意が必要なことは理解していますが、合理的なユースケースで指を振らないでください。
mpowered

私の意見では、最も簡単で最も簡潔な解決策です。3行のコードしか必要ないため、vhostファイルに貼り付けて、比較した$ hostを後で変更するだけです。
Akito

28

あなたの質問に答えるために-一致しない場合、nginxは最初のサーバーを選びます。ドキュメントを参照してください:

その値がどのサーバー名とも一致しない場合、またはリクエストにこのヘッダーフィールドがまったく含まれていない場合、nginxはこのポートのデフォルトサーバーにリクエストをルーティングします。上記の設定では、デフォルトのサーバーが最初のサーバーです...

ここで、たとえばすべてのリクエストに対して404で応答するデフォルトのキャッチオールサーバーが必要な場合は、次のようにします。

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_certificate <path to cert>
    ssl_certificate_key <path to key>
    return 404;
}

証明書/キー(自己署名可能)を指定する必要があることに注意してください。そうしないと、nginxがこのdefault_serverを使用して接続を受け入れようとし、証明書/キーが見つからないため、すべてのSSL接続が失敗します。


3
なぜこの回答がリストのはるか下にあるのか、私にはわかりません。これは、途中で光沢のあるものに気を取られることなく質問に答えるものです。
mmc 2018年

これは、www以外からwwwへのリダイレクトを試みていたときに、このリダイレクトルートにssl証明書を含める必要があったという問題を解決するのに役立ちました。
endyourif

1
これはほとんどの構成にとって最良の答えのようです...最近SSLなしでnginxを使用している人はわかりませんが、これがSSLをカバーする唯一のものであるという事実は非常に分かります。
mpowered

それserver_name _;も必要ないようです。
ジュリアンサリナス

26

デフォルトのサーバーを指定する方法はいくつかあります。

最初の方法 -サーバーの構成を上記のDayoのように1つの構成ファイルに保存する場合は、リストの最初にデフォルトサーバーを指定します。

2番目の方法(より良い)より柔軟- 命令のdefault_serverパラメーターを提供します。listen例:

server {
    listen  *:80 default_server;
    root /www/project/public/;
}

詳細はこちら:Nginx doc / Listen

この方法は、サーバー構成を別々のファイルに保持し、それらのファイルにアルファベット順に名前を付けたくない場合に、より便利です。


3
これが正解です。受け入れられた答えは誤解を招くものです。別のサーバーがデフォルトのサーバーとして構成されている場合、構成に別のサーバーを追加するだけでは問題は解決しません。
2014

1
@Pavel提供された回答が複数の個別のvhostファイルで機能しない理由はありません。また、これにより、私のデフォルトサーバーは常にメインのnginx.confファイルにあり、多くの個別のvhostファイルのどれにこれが含まれているのかを覚える必要はありません。
Dayo

sslについても443を聞くことを忘れないでください(下記の@AndreyTの応答を参照)。
コンスタンチノス

8

回答する少しのコメント:

sites-available /のいくつかの設定ファイルのいくつかのIPに複数の仮想ホストがある場合、IPの「デフォルト」ドメインはアルファベット順で最初のファイルから取得されます。

そしてPavelが言ったように、「listen」ディレクティブhttp://nginx.org/en/docs/http/ngx_http_core_module.html#listenには「default_server」引数があります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.