Почему nginx отвечает на любое доменное имя? - PullRequest
128 голосов
/ 22 марта 2012

У меня nginx работает с приложением Ruby / Sinatra и все хорошо. Однако сейчас я пытаюсь запустить второе приложение с того же сервера, и я заметил нечто странное. Во-первых, вот мой 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?

Ответы [ 6 ]

183 голосов
/ 22 марта 2012

Первый блок сервера в конфигурации nginx используется по умолчанию для всех запросов, поступающих на сервер, для которого нет конкретного блока сервера.

Так что в вашей конфигурации предполагается, что ваш реальный домен - REAL.COM,когда пользователь вводит его, он разрешается на ваш сервер, и, поскольку для этой настройки нет серверного блока, серверный блок для FAKE.COM, являющийся первым серверным блоком (только серверный блок в вашем случае), будет обрабатывать этотrequest.

Вот почему в правильных конфигах 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/ будет содержать domain_1.conf, domain_2.conf ...domain_n.conf, который будет включен после блока сервера в основной файл nginx.conf, который всегда будет первым и всегда будет значением по умолчанию, если только он не переопределен с помощью директивы default_server в другом месте.

Алфавитный порядокв этом случае имена файлов conf-файлов для других серверов становятся неактуальными.

Кроме того, это расположение дает большую гибкость в том смысле, что можно определить несколько значений по умолчанию.

В моем конкретном случае у меня Apache прослушивает порт 8080 только на внутреннем интерфейсе, и я передаю скрипты PHP и Perl в Apache.

Однако я запускаю два отдельных приложения, которые оба возвращают ссылки с «: 8080» в прикрепленном html-файле, поскольку они обнаруживают, что Apache не работает на стандартном порту 80, и пытаюсь «помочь» мне.

Это вызывает проблему в том, что ссылки становятся недействительными, так как 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.

На самом деле у меня есть четыре таких серверных блока, и это упрощенный вариант использования.

56 голосов
/ 24 ноября 2014

У вас должен быть сервер по умолчанию для catch-all , вы можете вернуть 404 или лучше, чтобы вообще не отвечать (сэкономит некоторую пропускную способность), возвращая 444, который является HTTP-ответом, специфичным для nginxкоторые просто закрывают соединение и ничего не возвращают

server {
    listen       80  default_server;
    server_name  _; # some invalid name that won't match anything
    return       444;
}
31 голосов
/ 13 августа 2014

Мне не удалось решить мою проблему ни с одним из других ответов.Я решил проблему, проверив, подходит ли хост, и вернул 403, если это не так.(У меня был какой-то случайный веб-сайт, указывающий на содержимое моих веб-серверов. Я угадываю рейтинг поиска)

server {
    listen 443;
    server_name example.com;

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

    ...
}
26 голосов
/ 13 февраля 2014

Существует несколько способов указать сервер по умолчанию.

Первый способ - Укажите сервер по умолчанию первым в списке, если вы храните конфигурации вашего сервера в одном файле конфигурации, как показано выше в Dayo.

Второй способ (лучше) Более гибкий - укажите default_server параметр для listen инструкции, например:

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

Более подробная информация здесь: Nginx doc / Listen

Этот способ более полезен, когда вы храните конфигурации сервера в отдельных файлах и не хотите называть эти файлы в алфавитном порядке.

15 голосов
/ 30 марта 2017

Чтобы ответить на ваш вопрос - 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;
}

Обратите внимание, что вам нужно указать сертификат / ключ (который может быть самозаверяющим), в противном случае все SSL-соединения не будут работать, так как nginx попытается принять соединение с помощью этого сервера по умолчанию и не найдет сертификат / ключ.

8 голосов
/ 24 августа 2013

Небольшой комментарий к ответу:

если у вас есть несколько виртуальных хостов на нескольких IP-адресах в нескольких конфигурационных файлах на сайтах-доступных /, то домен «по умолчанию» для IP будет взят из первого файла в алфавитном порядке.

И, как сказал Павел, для директивы listen есть аргумент "default_server" http://nginx.org/en/docs/http/ngx_http_core_module.html#listen

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...