Jump to content

Recommended Posts

Posted

Возникла у меня тут специфичная задача.

Есть веб-сервер с REST API, на котором потребовалось контролировать его использование (внешними пользователями), а штатные логи нужную информацию не сохраняют.

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

Мне нужно перехватывать обращения к ресурсу /method1?p1=v1&p2=v2 и писать в логи следующую информацию:

- дата/время, IP-адрес посетителя, адрес ресурса (method1);

- параметры запроса p1 и p2 (точнее значения этих параметров);

- заголовок User-Agent;

- декодированное имя пользователя из заголовка Authorization;

- значения заголовков ClientType и ClientId;

- если возможно, то ответный status code;

- если возможно, то содержимое некоторых узлов в возвращаемом XML;

- было бы хорошо, если логи писать не в один общий файл, а в файл с именем пользователя (из заголовка авторизации)

Возможно, нужно будет также подменять Host в запросе, пересылаемом на проксируемый сервер.

 

Насколько я понимаю, это все реализуемо штатными возможностями nginx, директивами proxy_pass и access_log.

Не ткнете в ссылку, где был бы пример подобной конфигурации?

Я пока не понимаю, как мне декодировать заголовки (имя пользователя) и как логгировать ответы.

Posted

У меня nginx заменял сквид долгое время, цель была фильтровать некоторые запросы к определённым сайтам а так же проксировать через спрокси сободного мира если возвращалась ошибка (провайдер одно время держал сквид для заблоченых сайтов, и нгинх это ловил и сразу перезапрашивал сам через прокси).

Posted (edited)

Вы хотите полный дебаг включая ответы от сервера. nginx тут не поможет.

простой вариант запустить tcpdump и писать в файл.

Более продвинутый вариант начать использовать log-коллекторы. Можно взять тот же elasticsearch с агентами filebeat (файловые логи), packetbeat (сетевой трафик). Выглядят страшно, но на самом деле несложно там. 

Edited by naves
Posted
В 03.10.2022 в 01:58, naves сказал:

Вы хотите полный дебаг включая ответы от сервера.

Это пожелание.

В первую очередь нужны все же запросы.

 

В 02.10.2022 в 15:49, sirmax сказал:

Штатными средствами нельзя залоггировать заголовки о которых вы не знаете заранее

Заголовки я знаю, но заголовки могут отсутствовать, тогда нужно писать в лог что-нибудь понятное (например прочерк).

Posted

дата/время, IP-адрес посетителя, адрес ресурса (method1);

$time_local $remote_addr $uri

- параметры запроса p1 и p2 (точнее значения этих параметров);

$arg_p1 $arg_p2

- заголовок User-Agent;

$http_user_agent

- декодированное имя пользователя из заголовка Authorization;

$remote_user

- значения заголовков ClientType и ClientId;

$http_clienttype $http_clientid

- если возможно, то ответный status code;

$status

- если возможно, то содержимое некоторых узлов в возвращаемом XML;

 

- было бы хорошо, если логи писать не в один общий файл, а в файл с именем пользователя (из заголовка авторизации)

 

access_log "/logs/blablabla/custom_${remote_user}_log";

но тут могут попихать всяких ../../..//etc/passwd тоесть надо бы сначала прогнать через фильтр

 

map $remote_user $t_remote_user {

 default 'unknown';

 ~^$[a-zA-Z0-9_-]{1,99}  $remote_user;

}

 

и в имени уже $t_remote_user

 

НО должны быть права у воркера на создание файлов с логами.

Posted
В 03.10.2022 в 17:28, st_re сказал:

access_log "/logs/blablabla/custom_${remote_user}_log"

Не был уверен, что на этот момент известны заголовки запроса.

 

В 03.10.2022 в 17:28, st_re сказал:

map $remote_user $t_remote_user

А вот это отлично, спасибо.

 

 

Posted

лог пишется в момент окончания обработки запроса..

если в пути на лог файл есть переменные. то он открывается (создаётся) в момент записи лога

 

перебирая имена юзеров можно будет забить ФС околопустыми файлами...

Posted
В 30.09.2022 в 09:26, alibek сказал:

Я пока не понимаю, как мне декодировать заголовки (имя пользователя) и как логгировать ответы.

Если именно нгинкс, можно посмотреть в сторону lua. Или написать свой прокси на знакомом языке

Posted
19 часов назад, naves сказал:

Вы хотите полный дебаг включая ответы от сервера. nginx тут не поможет.

простой вариант запустить tcpdump и писать в файл.

Более продвинутый вариант начать использовать log-коллекторы. Можно взять тот же elasticsearch с агентами filebeat (файловые логи), packetbeat (сетевой трафик). Выглядят страшно, но на самом деле несложно там. 

Все делается на нжинксе с луа

 

дам пример как дойду до компа, с телефона неудобно 

Posted

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

 

Речь идет про проксирование сервера Макроскоп.

Проксирование нужно для того, чтобы контролировать использование учетных записей — штатных инструментов в Макроскопе для этого нет.

Поэтому прокси-сервер будет логгировать доступ, а отдельный скрипт будет анализировать логи и выдавать уведомления при срабатывании.

Для проксирования использую nginx примерно с такой конфигурацией:

proxy_max_temp_file_size  0;
proxy_pass_request_headers  on;
proxy_buffering  off;

server {
    listen       80;
    listen       8080;

    location / {
        proxy_pass http://10.102.0.41:8080;
    }

    location = /configex {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.connect.$logdate.log  macroscop_connect;
        proxy_pass http://10.102.0.41:8080/configex?$query_string;
    }

    location = /command {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.command.$logdate.log  macroscop_command;
        proxy_pass http://10.102.0.41:8080/command?$query_string;
    }

    location = /connecttosmartassistant {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.assistant.$logdate.log  macroscop_assistant;
        proxy_pass http://10.102.0.41:8080/connecttosmartassistant?$query_string;
    }

    location = /mobile {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.mobile.$logdate.log  macroscop_mobile;
        proxy_pass http://10.102.0.41:8080/mobile?$query_string;
    }

    location = /mobilepush {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.push.$logdate.log  macroscop_push;
        proxy_pass http://10.102.0.41:8080/mobilepush?$query_string;
    }

    location = /ptz {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.ptz.$logdate.log  macroscop_ptz;
        proxy_pass http://10.102.0.41:8080/ptz?$query_string;
    }

}

 

При такой конфигурации я успешно подключаюсь к Макроскопу (как мобильным приложением, так и веб-версией), получаю список камер. Но ни одна из камер не работает, не отдает видеопоток.
Скорее всего это связано с тем, что видеопотоки тоже должны проксироваться.
 
В дампе трафика (при нормальном подключении к Макроскопу, не через прокси) происходит следующее.
 
Вначале выполняется авторизация через configex и запрашиваются серверные данные (списки серверов и камер).
 
Затем выполняется mobilepush, если это мобильное устройство.
 
Затем к каждой камере (из ранее полученного списка) отправляется запрос mobile и в ответ приходит примерно такое содержание:
HTTP/1.1 200 OK
Cache-Control: no-cache,no-store,max-age=0,must-revalidate
Pragma: no-cache
Transfer-Encoding: chunked
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Server: Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Date: Thu, 29 Sep 2022 11:23:39 GMT

1000
--myboundary
Content-Type: image/jpeg
Timestamp: 29.09.2022 11:23:40
BinaryTimestamp: 5249686492630663846
ZonedTimeStamp: 29.09.2022 11:23:40.327 ZZZZ
Content-Length: 45396
...

 

 

Видимо это и есть видеопоток, который постоянно передается в незакрываемой сессии.
Но в моем случае он не передается.
Не подскажите, что нужно исправить, чтобы проксирование заработало?
Posted
В 11.10.2022 в 11:58, alibek сказал:

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

 

Речь идет про проксирование сервера Макроскоп.

Проксирование нужно для того, чтобы контролировать использование учетных записей — штатных инструментов в Макроскопе для этого нет.

Поэтому прокси-сервер будет логгировать доступ, а отдельный скрипт будет анализировать логи и выдавать уведомления при срабатывании.

Для проксирования использую nginx примерно с такой конфигурацией:

proxy_max_temp_file_size  0;
proxy_pass_request_headers  on;
proxy_buffering  off;

server {
    listen       80;
    listen       8080;

    location / {
        proxy_pass http://10.102.0.41:8080;
    }

    location = /configex {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.connect.$logdate.log  macroscop_connect;
        proxy_pass http://10.102.0.41:8080/configex?$query_string;
    }

    location = /command {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.command.$logdate.log  macroscop_command;
        proxy_pass http://10.102.0.41:8080/command?$query_string;
    }

    location = /connecttosmartassistant {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.assistant.$logdate.log  macroscop_assistant;
        proxy_pass http://10.102.0.41:8080/connecttosmartassistant?$query_string;
    }

    location = /mobile {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.mobile.$logdate.log  macroscop_mobile;
        proxy_pass http://10.102.0.41:8080/mobile?$query_string;
    }

    location = /mobilepush {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.push.$logdate.log  macroscop_push;
        proxy_pass http://10.102.0.41:8080/mobilepush?$query_string;
    }

    location = /ptz {
        access_log /data/cybereye/log/macroscop.$remote_user_filter.ptz.$logdate.log  macroscop_ptz;
        proxy_pass http://10.102.0.41:8080/ptz?$query_string;
    }

}

 

При такой конфигурации я успешно подключаюсь к Макроскопу (как мобильным приложением, так и веб-версией), получаю список камер. Но ни одна из камер не работает, не отдает видеопоток.
Скорее всего это связано с тем, что видеопотоки тоже должны проксироваться.
 
В дампе трафика (при нормальном подключении к Макроскопу, не через прокси) происходит следующее.
 
Вначале выполняется авторизация через configex и запрашиваются серверные данные (списки серверов и камер).
 
Затем выполняется mobilepush, если это мобильное устройство.
 
Затем к каждой камере (из ранее полученного списка) отправляется запрос mobile и в ответ приходит примерно такое содержание:
HTTP/1.1 200 OK
Cache-Control: no-cache,no-store,max-age=0,must-revalidate
Pragma: no-cache
Transfer-Encoding: chunked
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Server: Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Date: Thu, 29 Sep 2022 11:23:39 GMT

1000
--myboundary
Content-Type: image/jpeg
Timestamp: 29.09.2022 11:23:40
BinaryTimestamp: 5249686492630663846
ZonedTimeStamp: 29.09.2022 11:23:40.327 ZZZZ
Content-Length: 45396
...

 

 

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

ДО этого должен быть запрос.. (ну и убедиться, что запрос идёт туда же, куда и остальной трафик.)

 

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

Posted

Это не через браузер происходит, а через мобильное приложение.

Посмотреть будет сложно, разве что трафик сниффером записать.

Posted
В 11.10.2022 в 11:58, alibek сказал:

так и веб-версией

 

В 12.10.2022 в 00:46, alibek сказал:

Это не через браузер происходит

что-то не сходится

 

В 12.10.2022 в 00:46, alibek сказал:

разве что трафик сниффером записать

тоже вариант

Posted
В 11.10.2022 в 11:58, alibek сказал:

Не подскажите, что нужно исправить, чтобы проксирование заработало?

попробуйте proxy_http_version 1.1;

Posted

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

Posted

Наиболее вероятно что откуда лится видео - отдаётся отдельной ссылкой, целиком url, и там либо ip либо хост, который разумеется за пределами локалки не достижим.

Posted
В 11.10.2022 в 13:58, alibek сказал:

Не подскажите, что нужно исправить, чтобы проксирование заработало?

1. для начала настройте самое тупое проксирование и убедитесь что оно работает

 

   location / {
        proxy_pass http://10.102.0.41:8080;
    }
 

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

 

2. строчка   "proxy_pass http://10.102.0.41:8080/configex?$query_string;" избыточна и неверна, достаточно "proxy_pass http://10.102.0.41:8080;". uri и request_uri подставляются автомагически:

 

If proxy_pass is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI

 

3. вся ваша куча локаций различается тока форматом лога. используйте вложенные локации и тот факт, что директивы (в т.ч. proxy_pass) переходит во вложенную локацию из родительской

location / {

  proxy_pass http://10.102.0.41:8080;

  location /blabla {
    access_log blablabla;
  }
}

Posted
В 14.10.2022 в 14:26, boco сказал:

вся ваша куча локаций различается тока форматом лога. используйте вложенные локации

О, спасибо, так намного удобнее.

 

В 14.10.2022 в 14:26, boco сказал:

для начала настройте самое тупое проксирование и убедитесь что оно работает

Так оно и не работает.

Возможно потому, что сервер отдает потоки в бесконечной сессии.

Posted

Обновленный конфиг:

Скрытый текст
    proxy_max_temp_file_size  0;
    proxy_pass_request_headers  on;
    proxy_buffering  off;

    map $remote_user $remote_user_filter {
        default '_unknown';
        ~^[a-zA-Z0-9_-]+$  $remote_user;
        * '_invalid';
    }

    map $time_iso8601 $logdate {
        default '0000-00-00';
        "~^(\d{4})-(\d{2})-(\d{2})" $1-$2-$3;
    }

    log_format macroscop
    '$time_iso8601: '
    '#$status '
    '$remote_addr ($remote_user) '
    '[$connection_requests:$connection] '
    '"$request"'
    ' ua="$http_user_agent"'
    ' recv=$request_length'
    ' sent=$bytes_sent'
    ' body=$body_bytes_sent'
    ;
...
server {
...
    error_log   /log/error.log notice;
    access_log  off;

    location / {
        root   /site;
        proxy_pass http://10.102.0.41:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        access_log /log/macroscop.log  macroscop;

        location = /configex {
            access_log /log/macroscop.$remote_user_filter.connect.$logdate.log  macroscop_connect;
        }
        location = /command {
            access_log /log/macroscop.$remote_user_filter.command.$logdate.log  macroscop_command;
        }
        location = /connecttosmartassistant {
            access_log /log/macroscop.$remote_user_filter.assistant.$logdate.log  macroscop_assistant;
        }
        location = /mobile {
            access_log /log/macroscop.$remote_user_filter.mobile.$logdate.log  macroscop_mobile;
        }
        location = /mobilepush {
            access_log /log/macroscop.$remote_user_filter.push.$logdate.log  macroscop_push;
        }
        location = /ptz {
            access_log /log/macroscop.$remote_user_filter.ptz.$logdate.log  macroscop_ptz;
        }

    }

}

 

Вложенные location срабатывают, потому что запросы пишутся в соответствующие файлы.

Но почему-то везде сервер возвращает ошибку 404.

В error.log примерно так:

Цитата

2022/10/14 15:48:26 [error] 27240#27240: *11 open() "/site/configex" failed (2: No such file or directory), client: xx.xx.xx.80, server: xxxx, request: "GET /configex?responsetype=json HTTP/1.1", host: "xxxx", referrer: "http://xxxx/web/index.html?v=3.6.69"

Такое впечатление, как будто proxy_pass не срабатывает.

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

Если запускать tcpdump на внешнем интерфейсе, то вижу то же, что в логах — внешний http-запрос, на который сервер отвечает кодом 404.

Если запускать tcpdump на интерфейсе 10.102.0.41, то там тишина (на порту 8080), я не вижу, чтобы шли какие-то обращения.

Как бы проверить, почему проксирование не работает?

Posted
В 14.10.2022 в 16:01, alibek сказал:

одновременно смотреть их через tcpdump нельзя

-i any

До чего техника дошла.

 

Да, судя по трафику, все что соответствует вложенным location — не проксируется.

Все что под них не попадает (то есть соответствует корневому location /) проксируется нормально.

 

P.S. Если продублировать proxy_pass в каждом вложенном location, то возвращаюсь к тому, с чего начал — подключаюсь, получаю конфигурацию с сервера, но видеопотоки не работают.

Но зато увидел в tcpdump, что нужно проксировать веб-сокет.

Хотя бы ясно теперь, в какую сторону копать.

 

P.P.S. Йес! Правда изображение тупит, но это уже настройки и тюнинг.

Posted
В 14.10.2022 в 18:01, alibek сказал:

Такое впечатление, как будто proxy_pass не срабатывает.

я был неправ. нужно добавлять proxy_pass во вложенные локации, эта директива не наследуется, в отличие от proxy_set_header

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...
На сайте используются файлы cookie и сервисы аналитики для корректной работы форума и улучшения качества обслуживания. Продолжая использовать сайт, вы соглашаетесь с использованием файлов cookie и с Политикой конфиденциальности.