LINUX.ORG.RU
ФорумAdmin

Хождение по URL'у — RFC 3986 Вопрос

 , , , ,


0

1

Привет!

Итак, есть сайт, на сайте nginx + php-fpm + bitrix

На сайте есть урл, например такой


https://site.ua/catalog/fototekhnika/../tovar/chekhol-sumdex-imagemaster-iii-noc-221rd-35793.html

Который при вставке его в браузер (да и просто curl'ом, когда пошлёшь GET ) преобразуется в

https://site.ua/catalog/tovar/chekhol-sumdex-imagemaster-iii-noc-221rd-35793.html

Я так понимаю, на это есть стандарт RFC

Проблема в том, что не каждый UserAgent, судя по логам,выполняет нужное преобразование. В результате nginx отдает по двум точкам в урле 403-й ответ.

Что можно с этим сделать?

Если нужно скину конфиги nginx'а

Вот конфиг

★★★★★

Последнее исправление: Twissel (всего исправлений: 2)

Вообще Nginx вполне способен разрулить эти две точки, и даже это делает по умолчанию. Возможно, проблема в том, что эти две точки пытаются выйти за пределы location?

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Да, ХЗ.

Вот кусок лога с запросом

[03/May/2018:17:12:43 +0300] "GET /catalog/otdykh-turizm-zdorove/../tovar/fljaga-herevin-paris-hanger-0-75l-161405-200-59345.html HTTP/1.1" 403 112 "https://site.ua/catalog/otdykh-turizm-zdorove/../tovar/herevin-city-bike-0-75l-161506-009-59353.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"

Что меня убивает, что у тупого курла все нормально, а у браузера вот такое вот, что приведено выше.

P.S. Сейчас выложу лог конфиг nginx' а в ОП.

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 2)
Ответ на: комментарий от Twissel

Возможно, у тебя скрипт $document_root/bitrix/urlrewrite.php выписывает ответы с кодом 403. Я попробовал делать такие запросы на nginx с подключенным через fastcgi php, и там всё нормально. Не похоже, что проблема именно в Nginx. Попробуй поснифать трафик на сервере и посмотреть, уходит ли запрос на бекенд. И если да, что отвечает бекенд.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Да посмотрел, 403-го нету.

Но есть такая вот обработка

$urlTmp = strtolower(ltrim($url, "/\\"));
$urlTmp = str_replace(".", "", $urlTmp);
$urlTmp7 = substr($urlTmp, 0, 7);

И еще, так точно парсингом запроса в данном случае занимается веб-сервер, а не браузер?

Да, я туплю, но лучше переспросить.

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 2)
Ответ на: комментарий от i-rinat

Ладно, отставим специфичные вещи.

У меня другой вопрос может ли сам nginx писал в лог GET-запрос уже после внутреннего рерайта и удаление точек?

Меня смущает, что разные тулзы для GET-запросов дают противоположные результаты.

Пойду смотреть заголовки запроса в логах.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от i-rinat

Например, два одинаковых запроса, но один с корректной ссылкой, а второй с неотфильтрованными точками

"GET /catalog/fototekhnika/../tovar/chekhol-sumdex-imagemaster-iii-noc-221rd-35793.html HTTP/1.1" 403 112 "-" "runscope/0.1"

"GET /catalog/tovar/chekhol-sumdex-imagemaster-iii-noc-221rd-35793.html HTTP/1.1" 200 291593 "-" "Codepunker 0.1 / HTTP Requests Tool"

Почему я и спросил, что может юзерагент сам парсит запрос перед отправкой.

Один парсит, другой — нет. Не знаю, пока домыслы...

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 3)
Ответ на: комментарий от Twissel

может ли сам nginx писал в лог GET-запрос уже после внутреннего рерайта и удаление точек?

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

Меня смущает, что разные тулзы для GET-запросов дают противоположные результаты.

Это как раз нормально. Если хочешь в деталях контролировать запрос, надо его слать через echo+netcat.

i-rinat ★★★★★
()
Ответ на: комментарий от Twissel

Почему я и спросил, что может юзерагент сам парсит запрос перед отправкой.

Таки да. cURL, например, нормализует URL. По крайней мере, он разбирается с /../ в пути. Другие утилиты — как повезёт. По идее, эти преобразования считаются эквивалентными, так что тулзы имеют право это делать.

Ты пробовал снифать трафик между Nginx и fastcgi-сервером?

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Ты пробовал снифать трафик между Nginx и fastcgi-сервером?

Нет, т.к. вот так сходу не соображу, чем это сделать, это во-первых.

Во-вторых, не знаю, что это может дать, ибо в nginx'е нигде в конфиге явно не указано, что нужно нормализировать url. А если я увижу, что с юзер-агента приходит уже нормализированный запрос, да это подтвердит мою догадку, но пользы не добавит.

Вот если бы такая настройка была в самом nginx'е, тогда другое дело.

Все равно нужно будет объяснять заказчику, что надо рыться в настройках кривых UA и нормализировать урл. Я пока склоняюсь к этому варианту.

Но все-таки даже для тренировки чем это лучше сделать?

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от i-rinat

нормализация

Вот, вполне закономерно, что cURL с опцией

--path-as-is
тоже получает 403-й ответ.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от i-rinat

Т.е. я бы лучше для конкретного локейшена написал редирект нормализации и проверил.

Я так мыслю...

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

Во-вторых, не знаю, что это может дать

Это позволит выяснить, что выдаёт ответ 403 — сам Nginx или бекенд-сервер. Если Nginx выдаёт 403, и при этом запрос не доходит до бекенда, дело в конфиге Nginx, и надо ковырять его. Если же Nginx отсылает запрос на бекенд, тот отвечает 403, и Nginx просто проксирует его обратно клиенту, Nginx не виноват, и смысла грызть его конфиг нет. В таком случае нужно хмуро смотреть на бекенд.

чем это лучше сделать?

tcpdump -i eth0 -w output.pcap -v

Собранный дамп открывать в wireshark.

i-rinat ★★★★★
()
Ответ на: комментарий от Twissel

Вот если бы такая настройка была в самом nginx'е, тогда другое дело.

Не знаю, может там что-то такое и есть. Я не в курсе.

Есть идея с костылём: поставить ещё один server перед основным, настроить в нём proxy_pass. Это должно нормализовывать uri перед передачей на бекенд.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

ОК, спасибо, Ринат.

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

Только админских костылей не хватало :-)

Есть еще вот такая строка

location ~* /\.\./ { deny all; }

Но я ее комментировал, эффекта ноль.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

это сильно сложно

Почему? Это же не отдельную железку ставить. Просто добавить ещё одну секцию server с location внутри.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

ок, оставлю это как запасной вариант.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от i-rinat

Чисто для общего развития я задал такой вопрос на serverfault. Ответ, конечно, не учитывает, что в данном конкретном случае у CMS есть свой реврайтер, но в целом должно сработать.

P.S. И да, пока мы просто поменяли SEO-сканер и отписали разрабам этого, что они не читали сабжевый RFC :-)

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от i-rinat

поставить ещё один server перед основным, настроить в нём proxy_pass

И да, что-то я уже не соображу как это можно сделать.

Подскажи пожалуйста.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

Как-то так:

    # front server
    server {
        listen       8080;

        location / {
            # Последний слеш в proxy_pass важен. Без него не будет нормализации URL.
            proxy_pass http://127.0.0.1:8081/;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }

    # old server
    server {
        listen       127.0.0.1:8081;

        location / {
            root html;
            index index.html;
        }

        location ~ \.php$ {
            root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            include        fastcgi_params;
        }
    }

Я тут в процессе написания осознал, что теряется IP адрес клиента, поэтому приложению нужно как-то научиться читать поле X-Real-IP заголовка. Возможно, ещё какие-то проблемы могут всплыть.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

что теряется IP адрес клиента

Именно поэтому я и не торопился менять такие вещи на сервере самого ИМ.

Но для расширения кругозора это полезно уметь.

Twissel ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.