Re: Запрет неправильного host для ipv6
Maxim Dounin
mdounin at mdounin.ru
Tue Aug 26 22:49:52 UTC 2014
Hello!
On Tue, Aug 26, 2014 at 04:40:58PM -0400, iprok wrote:
> Maxim Dounin Wrote:
>
> > Т.е. делать ровно так же:
> >
> > server {
> > listen 80 default_server;
> > listen [::]:80 default_server;
> > return 444;
> > }
>
> Я первым делом попробовал предложенный Вами конфиг. К сожалению вот такой
> вот вариант конфига не работает, если убрать комментарий:
>
> user nginx;
> worker_processes 1;
>
> error_log /var/log/nginx/error.log warn;
> pid /var/run/nginx.pid;
>
>
> events {
> worker_connections 1024;
> }
>
>
> http {
> server {
> listen 8080 default_server;
> listen [::]:8080 default_server;
> return 444;
> }
> server {
> listen XXX.XX.XXX.251:8080;
> # listen [2aXX:X:XXX:XXXX:2::6]:8080 ipv6only=on;
> server_name "test.local";
> }
> }
В блоке server{} с "return 444" нужно перечислять те же
listen-сокеты, что и в других блоках server{}. Перечислять там
другие сокеты - бессмысленно. E.g., в вышеприведённом конфиге все
запросы к XXX.XX.XXX.251:8080 будут обаботаны в сервере
test.local.
Если в существующих серверах используются listen-сокеты
XXX.XX.XXX.251:8080 и [2aXX:X:XXX:XXXX:2::6]:8080, то правильный
конфиг будет выглядеть так:
server {
listen XXX.XX.XXX.251:8080 default_server;
listen [2aXX:X:XXX:XXXX:2::6]:8080 default_server;
return 444;
}
server {
listen XXX.XX.XXX.251:8080;
listen [2aXX:X:XXX:XXXX:2::6]:8080;
server_name "test.local";
}
Отмечу также, что начиная с 1.3.4 ipv6only=on используется по
умолчанию, и явно его писать - не надо.
> Если конфиг с комментарием, то nginx запускается, биндясь на
> netstat -tulpn | grep nginx
> tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN
> 16821/nginx.conf
> tcp6 0 0 :::8080 :::* LISTEN
> 16821/nginx.conf
>
> Если комментарий убираю, то получаю ошибку:
> nginx: [emerg] bind() to [::]:8080 failed (98: Address already in use)
> nginx: [emerg] bind() to [::]:8080 failed (98: Address already in use)
> nginx: [emerg] bind() to [::]:8080 failed (98: Address already in use)
> nginx: [emerg] bind() to [::]:8080 failed (98: Address already in use)
> nginx: [emerg] bind() to [::]:8080 failed (98: Address already in use)
> nginx: [emerg] still could not bind()
> failed!
Linux, в отличие от классических BSD-систем, не разрешает
создавать listen-сокеты одном и том же порту на wildcard-адресе
(0.0.0.0 для ipv4, [::] для ipv6) и на ip-адресе одновременно,
объясняя это соображениями безопасности.
Про эти за^Wнюансы поведения Linux'а nginx знает, и при наличии в
конфиге listen-сокетов на ip-адресах и wildcard-адресах
одновременно - создаёт только один listen-сокет, а для правильного
распределения входящих соединений по ip-based серверам -
использует дополнительный системный вызов getsockname().
С приведённым конфигом, однако, из-за параметра ipv6only nginx
создаёт отдельные сокеты, что в результате приводит к ошибке
"Address already in use". Если убрать параметр ipv6only=on
(ненужный, см. выше), то nginx запустится. Конфиг, впрочем, от
этого правильным не станет - см. выше.
Дополнительно про всё это можно прочитать в описании директивы listen
(в частности, её параметра bind), и в водной статье "Как nginx
обрабатывает запросы" (имеет смысл обратить внимание на раздел
"Определение виртуального сервера по имени и IP-адресу"):
http://nginx.org/ru/docs/http/ngx_http_core_module.html#listen
http://nginx.org/ru/docs/http/request_processing.html#mixed_name_ip_based_servers
--
Maxim Dounin
http://nginx.org/
Подробная информация о списке рассылки nginx-ru