Блокировка доступа к локации NGINX и перенаправление на пользовательскую страницу с ошибкой

Вопрос или проблема

У меня есть проблема с настройкой NGINX для перенаправления на пользовательскую страницу ошибки в другом месте (включая css, изображения, js), если должна быть вызвана страница ошибки.

Сначала я хотел бы заблокировать доступ к папке (например, .git). Это можно легко сделать с помощью (внутри блока сервера)

location ~ /(.git) {
    deny all;
    return 404;
}

Затем я создал элемент error_page с пользовательским файлом 404.html в другом месте, чем корневая директория веб-сайта.

error_page 404 /404.html;
location = /404.html {
    root /var/data/websites/error-page;
    internal;
}

После этих изменений моя пользовательская страница 404 будет отображаться, но без css, js и изображений.

Если я проверяю сайт, причина проста: путь к файлам неверен – они основаны на местоположении (в моем примере .git).
https://it.dmetzler1988.io/.git/css/main.css net::ERR_ABORTED 404.

Вот полный файл конфигурации NGINX для этой страницы (удалены только пути к сертификатам ssl):

server {
    listen 443 ssl;
    listen [::]:443 ssl http2;

    ssl_certificate <path>;
    ssl_certificate_key <path>;

    server_name it.dmetzler1988.io;
    root /var/data/websites/dmetzler1988.io/it.dmetzler1988.io;
    index index.html index.php;

    error_page 404 /404.html;
    location = /404.html {
        root /var/data/websites/error-page;
        internal;
    }

    location ~ /(.git) {
        deny all;
        return 404;
    }
}

Итак, мои вопросы на этом месте:

  1. Как я могу исправить проблему с неверным путем (удалить .git из пути)?
  2. Это правильный способ для такого случая использования, или есть лучшее решение?

Во-первых, об ошибках в вашей конфигурации.

location ~ /(.git) { ... }

Похоже, вы не совсем знакомы с регулярными выражениями PCRE. Нет необходимости использовать здесь группу захвата – группы захвата используются, когда позже нужно использовать ее содержимое. Однако это не критическая ошибка. Самое плохое в том, что вы используете незашитый символ точки, который работает как подстановочный знак в шаблонах регулярных выражений. Таким образом, вы эффективно блокируете любой URI, содержащий строку, где вторым, третьим и четвертым символами являются git (например, /agitation/index.html, /any/prefix/agitation/index.html и т. д.). Правильный шаблон регулярного выражения здесь будет /\.git (блокировка всего, что начинается с .git, включая .gitignore и т. д. на любом уровне вложенности каталогов).

Далее, вы используете две директивы в этом местоположении – deny all и return 404. Достаточно будет любой из них – либо deny all (возвращает HTTP 403 Forbidden), либо return 404 (возвращает HTTP 404 Not Found). Причина, по которой вы получаете 404, а не 403, заключается в том, что директива return выполняется на этапе обработки запроса REWRITE, а deny на более позднем этапе ACCESS (фазы обработки запросов описаны в руководстве по разработке).

Теперь вернемся к вашему вопросу. Похоже, вы ссылаетесь на свои ресурсы, используя относительные пути URI, например

<link rel="stylesheet" type="text/css" href="css/main.css">

Некоторые из ваших вариантов (но не ограничены):

  • включите каждый актив в HTML обработчика ошибок (включая изображения, вы можете сделать это, закодировав свои изображения до BASE64 и используя Data URIs);

  • переместите все активы в некоторую папку под вашим основным веб-каталогом сайта (скажем, /var/data/websites/dmetzler1988.io/it.dmetzler1988.io/assets/errors) и указывайте на них, используя полный путь:

    <link rel="stylesheet" type="text/css" href="/assets/errors/css/main.css">
    

Как я могу это сделать на своем сервере:

Структура директорий:

/var/www/example.com/public

/var/www/internal
/var/www/internal/400-nginx.html
...
/var/www/internal/504-nginx.html

И внутри моего server{...} блока:

# Страницы ошибок

# HTTP 400: Неверный запрос
error_page 400 /400-nginx.html;
    location = "/400-nginx.html" {
    root var/www/internal;
    internal;
}

# HTTP 403: Запрещено
error_page 403 /403-nginx.html;
    location = "/403-nginx.html" {
    root var/www/internal;
    internal;
}

# HTTP 404: Не найдено
error_page 404 /404-nginx.html;
    location = "/404-nginx.html" {
    root var/www/internal;
    internal;
}

# HTTP 405: Метод не разрешен
error_page 405 /405-nginx.html;
    location = "/405-nginx.html" {
    root var/www/internal;
    internal;
}

# HTTP 413: Слишком большой объем данных
error_page 413 /413-nginx.html;
    location = "/413-nginx.html" {
    root var/www/internal;
    internal;
}

# HTTP 415: Неподдерживаемый медиа тип
error_page 415 /415-nginx.html;
    location = "/415-nginx.html" {
    root var/www/internal;
    internal;
}

# HTTP 429: Слишком много запросов
error_page 429 /429-nginx.html;
    location = "/429-nginx.html" {
    root var/www/internal;
    internal;
}

# HTTP 501: Метод не реализован
error_page 501 /501-nginx.html;
    location = "/501-nginx.html" {
    root var/www/internal;
    internal;
}

# HTTP 502: Плохой шлюз
error_page 502 /502-nginx.html;
    location = "/502-nginx.html" {
    root var/www/internal;
    internal;
}

# HTTP 503: Сервис недоступен
error_page 503 /503-nginx.html;
    location = "/503-nginx.html" {
    root var/www/internal;
    internal;
}

# HTTP 504: Тайм-аут шлюза
error_page 504 /504-nginx.html;
    location = "/504-nginx.html" {
    root var/www/internal;
    internal;
}

.

Ответ или решение

Решение проблемы с доступом и переадресацией на пользовательскую страницу ошибки в NGINX может быть более сложным, чем кажется на первый взгляд. Основная задача заключается в правильной настройке серверного блока, чтобы обеспечить корректное отображение страницы ошибки с подключенными стилями и скриптами. Давайте проведем детальный разбор.

Ваша текущая конфигурация

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

Ошибки в настройках:

  1. Регулярное выражение: Вы используете необработанный символ . в выражении /(.git), который в PCRE (Perl Compatible Regular Expressions) обозначает любой символ. Поэтому ваше правило может срабатывать не так, как ожидается. Используйте безопасный вариант — \.git, чтобы блокировать только каталоги, начинающиеся с .git.

  2. Двойная инструкция в блоке: У вас одновременно используются deny all; и return 404;. Это избыточно. Достаточно оставить только return 404; для возвращения ошибки 404 Not Found, или же оставить deny all;, если хотите возвращать 403 Forbidden.

Исправление путей на странице ошибки

Ошибки с неправильными путями к файлам возникают из-за относительной адресации. Чтобы исправить это, у вас есть несколько возможностей:

  • Использование абсолютных путей: Переместите необходимые ресурсы (CSS, изображения, JS) в отдельную директорию под основным корнем сайта и замените относительные пути на абсолютные. Например, если ваши ресурсы перемещены в /assets/errors, то путь будет таким: <link rel="stylesheet" type="text/css" href="/assets/errors/css/main.css">.

  • Инлайн-стили и скрипты: Вы можете инлайнить CSS и JavaScript непосредственно в HTML-код страницы ошибки. Для изображений можно использовать Data URIs, что позволит избежать проблемы с путями вообще.

Общий подход к настройке страниц ошибок

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

Пример структуры директорий:

/var/www/example.com/public
/var/www/internal
/var/www/internal/errors
/var/www/internal/errors/404.html

Настройка серверного блока:

server {
    listen 443 ssl;
    listen [::]:443 ssl http2;

    server_name it.dmetzler1988.io;
    root /var/data/websites/dmetzler1988.io/it.dmetzler1988.io;
    index index.html index.php;

    error_page 404 /errors/404.html;

    location = /errors/404.html {
        root /var/www/internal;
        internal;
    }

    location ~ /\.git {
        return 404;
    }

    location ~* \.(css|js|png|jpg|jpeg|gif|ico)$ {
        expires 1M;
        add_header Cache-Control "public";
    }
}

Заключение

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

Удачи в настройке! Если возникнут дополнительные вопросы, всегда готов помочь.

Оцените материал
Добавить комментарий

Капча загружается...