Почему 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
?
Ответы
Ответ 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.