AdTech AI PostgreSQL О компании
Web · nginx 14 февраля, 2025 Сергей Томулевич

Быстрая капча

Реализация быстрой капчи через nginx с использованием ngx_http_secure_link_module и ngx_http_random_index_module. Защита скачивания файлов.

Введение

Защита от ботов посредством капч на критичные действия пользователей. Красивую и сложную капчу генерить довольно ресурсоёмко и не всегда оправдано.

Задача

Защитить скачивание файла введением капчи.

Решение 1 — простое

Структура папок

index.html

<html>
<body>
    <form action="/download" method="GET">
        <!--#include virtual="/capches/"-->
        <input type="text" name="code" value="">
        <input type="submit">
    </form>
</body>
</html>

Файлы в папке capches

<img src="data:image/png;base64,...">
<input type="hidden" name="md5" value="IODn35yg2gLtnSRhyKyK6g">
<input type="hidden" name="key" value="5e12c2002a0370826a9dee5f6a55f5e3">

key — имя файла, md5 — MD5 сумма от комбинации ключа, кода и соли.

Конфиг nginx

server {
    listen                      80;
    server_name                 capcha.local;

    root                        /spool/projects/capcha/;
    index                       index.shtml;

    location / {
        ssi                     on;
    }
    location /capches/ {
        random_index            on;
    }
    location /download {
        proxy_pass              %backend_uri%;
    }
    location /file {
        deny all;
    }
}

Решение 2 — pure nginx

Это решение предлагается исключительно в ознакомительных целях.

Добавляем поле в форму:

<input type="hidden" name="file" value="arch1">

Символьная ссылка:

ln -s /spool/projects/capcha/capches /spool/projects/capcha/dav

Конфигурация nginx

map $file_alias $filename {
    default                         'fail';
    'arch1'                         'archive1.zip';
    'arch2'                         'archive2.zip';
    'arch3'                         'archive3.zip';
}

server {
    listen                      80;
    server_name                 captcha.local;

    root                        /spool/projects/capcha/;
    index                       index.shtml;

    location / { ssi on; }
    location /capches/ { random_index on; }

    location /download {
        if ($request_method != 'GET') { return 301 /fail; }
        if ($arg_key !~ '^\w+$') { return 301 /fail; }
        secure_link             $arg_md5;
        secure_link_md5         "$arg_key $arg_code salt";
        if ($secure_link = "") { return 301 /fail; }
        if ($secure_link = "0") { return 301 /fail; }
        set                     $file_alias $arg_file;
        proxy_intercept_errors  on;
        proxy_pass              http://127.0.0.1/dav/$arg_key.html;
        proxy_method            DELETE;
        proxy_set_header        Host        $host;
        proxy_set_header        X-File      $filename;
    }
    location /dav/ {
        allow                   127.0.0.1;
        deny                    all;
        dav_methods             DELETE;
        add_header              X-Accel-Redirect        "/file/$http_x_file";
        add_header              Content-Disposition     "attachment; filename=\"$http_x_file\"";
        error_page              403 404                 =301 /fail;
    }
    location /file {
        internal;
        try_files               $uri        =204;
    }
    location /fail {
        return                  200         'FAIL CODE';
    }
}

Заключение

Можно сделать статичную капчу и производить её валидацию прямо на уровне nginx, однако существуют трудности:

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

to@prototypes.ventures