Подтвердить что ты не робот

Почему nginx отвечает на любое доменное имя?

У меня есть 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?

4b9b3361

Ответ 1

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

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

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

# Default server
server {
    return 404;
}

server {
    server_name domain_1;
    [...]
}

server {
    server_name domain_2;
    [...]
}

и т.д.

** РЕДАКТИРОВАТЬ **

Кажется, некоторые пользователи немного смущены этим примером и считают, что он ограничен одним файлом conf 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.

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

Ответ 2

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

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

Ответ 3

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

server {
    listen 443;
    server_name example.com;

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

    ...
}

Ответ 4

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

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

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

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

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

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

Ответ 5

Маленький комментарий для ответа:

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

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

Ответ 6

Чтобы ответить на ваш вопрос - 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 попытается принять соединение с использованием этого файла default_server и не найдет cert/key.