Как настроить nginx для отправки запросов сразу на 2 адреса
У нас nginx работает как прокси сервер для онлайн хранилища файлов. Как можно настроить, что бы при скачивании файла (или при прохождении любого трафика через этот прокси), nginx передавал файл как пользователю, который его запрашивает, так и другому серверу (у нас там антивирус)? Тоесть сразу в 2 места.
Ответы (1 шт):
Насколько мне известно, Nginx такое не умеет. Но есть варианты
Первый вариант: X-Accel-Redirect
X-Accel-Redirect используется для контролируемых скачиваний.
Как должно работать:
1. Пишем скрипт на любом языке
down.php:
<?php
// Публичная ссылка на файл
$path = $_GET["path"];
// Тут тем или иным способом отправляем запрос или ссылку на файл в антивирус.
// Если эта операция долгая, то лучшее решение - в этом месте пишем в очередь,
// а отдельный воркер кидает из очереди в антивирус
// Это-заголовок для Nginx, откуда брать файл
header("X-Accel-Redirect: /files/" . $path);
2. Настраиваем Nginx
Доработайте конфиг под свои особенности и защитите /files от прямого доступа из браузера.
http {
....
server {
listen 80;
server_name your-domain.com;
location / {
rewrite ^/download/(.*) /down.php?path=$1 last;
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
location /files {
root /var/www;
internal;
}
}
}
Получается такой путь:
Запрашивается файл
/download/file.zip, Nginx переписывает адрес и кидает в скрипт/down.php?path=file.zip.Скрипт отправляет файл в антивирус (реализацию напишите сами)
Скрипт отдает Nginx заголовок
X-Accel-Redirect: /files/file.zipи Nginx уже отправляет файл в браузер.
По сути, файл на проверку отправляет написанный скрипт. Если отправка - медленный процесс, используйте очереди.
Ссылки:
Второй вариант: auth_request
По сути похож на первый вариант.
1. Пишем скрипт на любом языке
В скрипте отправляем файл на проверку, в конце отдаем 2xx код.
2. Настраиваем Nginx
Поправьте пути и порты под свои реалии. Документация.
server {
listen 80;
server_name your-domain.com;
# сюда поступает запрос на скачивание
location /download/ {
# если аутентификации нет, дальше запросы не пойдут
auth_request /auth;
# проксируем на даунлоад-сервер с файлами
proxy_pass http://download-server;
}
# тут проводим проверку
location = /auth {
internal;
proxy_pass http://127.0.0.1:8080;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
}
Путь такой:
Запрашивается файл
/download/file.zip, Nginx идет на внутренний адрес/auth, который проксируется наhttp://127.0.0.1:8080, где находится скриптСкрипт отправляет файл в антивирус (реализацию напишите сами)
Скрипт отдает Nginx любой код из 2xx, Nginx воспринимает это как успешную авторизацию и отдает в браузер файл из
http://download-server
Третий вариант: Lua
Есть проект OpenResty который позволяет писать программы на Lua прямо в конфигах Nginx. Обычный Nginx также позволяет это делать, но нужно будет в него добавить модуль Lua.
А способ похож на предыдущие два: получаем запрос, ставим в очередь проверки, а клиенту отдаем файл.
Самый интересный на мой взгляд способ, но требует изучения Lua и OpenResty.
Четвертый способ: через логи
В location, с которого скачиваются файлы, пишите access_log в отдельный файл. А отдельный скрипт читает этот файл и отправляет на проверку. Может быть, даже это будет не файл, а сокет, тогда не придется следить за файлом, а сразу вычитывать из сокета, но я не уверен, что Nginx может писать в сокеты. Попробуйте.