ДВС.
freebsd 11.1, nginx,php - последние на начало апреля.
nginx отдаёт 400 вместо 444 при запросе.
т.е. фактически задача - отброс всех стран, кроме указанных.
И это работает, но до тех пор, пока не встречается странный запрос.
собственно, ВОПРОС: что это за дрянь и как с ней бороться. Должен уходить 444.
Подробности:
в конфиге стоит прямой редирект с http на https, но до https дело не доходит.
в логе вот такое:
51.38.12.21 - FR - [24/Apr/2018:06:05:44 +0500] my.domain.ru \x16\x03\x01\x02\x00\x01\x00\x01
\xFC\x03\x03Q\x15\xA6{7\x0E\xC3U\xD7\x044\x97T\xE0u\x13\xFB\xA5\x1E\x19\xA6b\xA9J\xF6\x13\x04
\xFA\x80\x01}\xF8\x00\x00\xDA\x00\x05\x00\x04\x00\x02\x00\x01\x00\x16\x003\x009\x00:\x00\x18
\x005\x00 400 166 "-" "-" "-" 0.032--
в запросах с get post - то, что и должно быть:
167.99.82.115 - GB - [24/Apr/2018:03:48:35 +0500] my.domain.ru GET / HTTP/1.0 444 0 "-"
"Mozilla/5.0" "-" 0.000--nginx.conf:
worker_processes 1;
pid /var/run/nginx.pid;error_log /var/log/n-error.log notice;
load_module /usr/local/libexec/nginx/ngx_http_geoip_module.so;events { worker_connections 1024;}
http {
server_tokens off;
include country.conf;
include mime.types;
default_type application/octet-stream;
log_format vhf '$remote_addr - $geoip_country_code $remote_user [$time_local]
$host $request ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent"
"$http_x_forwarded_for" $request_time-$upstream_response_time';
log_format vhfs '$remote_addr - $geoip_country_code $remote_user [$time_local]
https://$host $request ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent"
"$http_x_forwarded_for" $request_time-$upstream_response_time';
access_log /var/log/n-access.log vhf;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
gzip on;
error_page 403 404 500 502 503 504 = /err.html;
proxy_intercept_errors on;
recursive_error_pages on;
#################### my.domain.ru 80 ###################################
server {
include guard.conf;
listen x.x.x.x:80;
server_name my.domain.ru;
rewrite ^/(.*)$ https://my.domain.ru/ permanent;
location ~ /\.ht {
deny all;
}
}
#################### my.domain.ru 443 ###
server {
server_name my.domain.ru;
include guard.conf;
include err.conf;
include ssl.conf;
location / {
root /var/db/web/te/www;
include rootloc.conf;
}
}
}guard.conf:
add_header X-Frame-Options "SAMEORIGIN";
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; object-src 'none'";
add_header Strict-Transport-Security 'max-age=631138519; includeSubDomains; preload' always;
add_header X-Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' blob data:";
add_header X-WebKit-CSP "default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' blob data:";
add_header X-Xss-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Proxy-Cache "EXPIRED" always;
add_header 'Referrer-Policy' 'origin';
server_tokens off;
add_header 'X-powered-by' "DDG";
set $a zero$http_user_agent;
if ($allowed_country = 2) {return 444;}
if ($request_method !~ ^(GET|POST)$ ) {return 444;}
if ($host !~ ^(my.domain.ru)$ ) {return 444;}
if ($a = "zero") {return 444;}
if ($http_user_agent ~* "Bot|zgrab"){return 444;}
if ($http_referer ~* "yandex|Yandex|Googl|googl"){return 444;}country.conf
geoip_country /usr/local/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
default 2;
RU 1;
AB 1;
AZ 1;
AM 1;
BY 1;
KZ 1;
MD 1;
TJ 1;
TM 1;
UZ 1;
}инклуды ssl err не привожу - специфичные соответствующие настройки.
Работает всё так, как мне нужно, за исключением этих нестандартных запросов с хексами.
Не могу понять, почему ошибка отрабатывает раньше реврайта.
Как из победить? Надо, чтобы вместо отдачи кода 400 сервер разрывал связь (444).
>[оверквотинг удален]
> уходить 444.
> Подробности:
> в конфиге стоит прямой редирект с http на https, но до https
> дело не доходит.
> в логе вот такое:
> 51.38.12.21 - FR - [24/Apr/2018:06:05:44 +0500] my.domain.ru \x16\x03\x01\x02\x00\x01\x00\x01
> \xFC\x03\x03Q\x15\xA6{7\x0E\xC3U\xD7\x044\x97T\xE0u\x13\xFB\xA5\x1E\x19\xA6b\xA9J\xF6\x13\x04
> \xFA\x80\x01}\xF8\x00\x00\xDA\x00\x05\x00\x04\x00\x02\x00\x01\x00\x16\x003\x009\x00:\x00\x18
> \x005\x00 400 166 "-" "-" "-"
> 0.032--Если это не результат кривого редиректа где-то на вашей стороне, то эта дрянь больше похожа на кривой софт у клиента. Возможно, специально кривой — т.е., проверка сервера на вшивость. Ваш nginx абсолютно корректно возвращает код 400, так как тоже офигевает и сделать более ничего не может.
Код 444 он возвратит когда будет прочитана и распознана хотя бы первая строка HTTP-запроса. А в вашем случае в первой строке какая-то хрень, там ни HTTP-метода, ни запрашиваемого пути, ни версии протокола, поэтому nginx просто сразу прощается. Мог бы, кстати, и 505 отвечать, но 400 всё же подходит больше в такой ситуации, согласитесь.
Попробуйте отправить мусор на сервер и посмотрите на результат на экране и в логах:
printf "ad asdad ljalsjdlaj lsjdljs lfasljf ljslfd\r\nlalalala\r\n" | nc address 80P.S.: Если интересно, раскодируйте переданную байтовую строку из текстового представления и засуньте в дизассемблер — не удивлюсь, если там окажется что-то осмысленное. :)
> Попробуйте отправить мусор на сервер и посмотрите на результат на экране и
> в логах:
>printf "ad asdad ljalsjdlaj lsjdljs lfasljf ljslfd\r\nlalalala\r\n" | nc address
> 80Да, результат - 400
>Код 444 он возвратит когда будет прочитана и распознана хотя бы первая строка HTTP-запроса.
Да, жаль. Я полагал что обработка правилами происходит до отдачи кода.
Но и причины "тестирования" понятны - мой nginx не признаётся, что он nginx :)
> Да, жаль. Я полагал что обработка правилами происходит до отдачи кода.
> Но и причины "тестирования" понятны - мой nginx не признаётся, что он
> nginx :)Вы просто не умеете в nginx. "Обработка правилами" происходит на разных стадиях.
server {
listen 80;
server_name _ default_server;
return 444;
access_log "/tmp/1.log";
error_page 400 = /drop;
location = /drop { return 0; }
}server {
listen 80;
server_name real.server.name;
return 301 https://$server_name$request_uri;
}----
lca:~ $ printf "ad asdad ljalsjdlaj lsjdljs lfasljf ljslfd\r\nlalalala\r\n" | nc stage.rukuku.com 80
lca:~ $
----
[root@stage data]# cat /tmp/1.log
1.1.151.209 - - [27/Apr/2018:07:13:35 +0000] "ad asdad ljalsjdlaj lsjdljs lfasljf ljslfd" 444 0 "-" "-"
> Вы просто не умеете в nginx. "Обработка правилами" происходит на разных стадиях....
> server_name _ default_server;...
> return 301 https://$server_name$request_uri;О! Спасибо!
Я действительно не особо его умею.
Прошу пояснить в Вашем примере:
1. default_server - это ключевое слово, или тут подразумевается ip сервера?
2. return 301 https://$server_name$request_uri;
- Это замена моего rewrite ^/(.*)$ https://my.domain.ru//$1 permanent; ?
чем return 301 лучше rewrite ?
> 1. default_server - это ключевое слово, или тут подразумевается ip сервера?Сервер по умолчанию можно задать явно с помощью параметра default_server в директиве listen.
http://nginx.org/ru/docs/http/request_processing.html> 2. return 301 https://$server_name$request_uri;
> - Это замена моего rewrite ^/(.*)$ https://my.domain.ru//$1 permanent; ?Да.
> чем return 301 лучше rewrite ?
Эффективнее. В том числе тем, что не производится обработка регулярного выражения.