alibek Опубликовано 30 сентября, 2022 · Жалоба Возникла у меня тут специфичная задача. Есть веб-сервер с 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. Не ткнете в ссылку, где был бы пример подобной конфигурации? Я пока не понимаю, как мне декодировать заголовки (имя пользователя) и как логгировать ответы. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
boco Опубликовано 1 октября, 2022 · Жалоба http://nginx.org/ru/docs/varindex.html $remote_user $arg_ $http_ https://mailman.nginx.org/mailman3/lists/ Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
sirmax Опубликовано 2 октября, 2022 · Жалоба Я решал задачу логгирования для дебага https://noname.com.ua/mediawiki/index.php/Nginx_Log_RequestHeaders Штатными средствами нельзя залоггировать заголовки о которых вы не знаете заранее Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
Ivan_83 Опубликовано 2 октября, 2022 · Жалоба У меня nginx заменял сквид долгое время, цель была фильтровать некоторые запросы к определённым сайтам а так же проксировать через спрокси сободного мира если возвращалась ошибка (провайдер одно время держал сквид для заблоченых сайтов, и нгинх это ловил и сразу перезапрашивал сам через прокси). Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
naves Опубликовано 2 октября, 2022 (изменено) · Жалоба Вы хотите полный дебаг включая ответы от сервера. nginx тут не поможет. простой вариант запустить tcpdump и писать в файл. Более продвинутый вариант начать использовать log-коллекторы. Можно взять тот же elasticsearch с агентами filebeat (файловые логи), packetbeat (сетевой трафик). Выглядят страшно, но на самом деле несложно там. Изменено 2 октября, 2022 пользователем naves Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
alibek Опубликовано 3 октября, 2022 · Жалоба В 03.10.2022 в 01:58, naves сказал: Вы хотите полный дебаг включая ответы от сервера. Это пожелание. В первую очередь нужны все же запросы. В 02.10.2022 в 15:49, sirmax сказал: Штатными средствами нельзя залоггировать заголовки о которых вы не знаете заранее Заголовки я знаю, но заголовки могут отсутствовать, тогда нужно писать в лог что-нибудь понятное (например прочерк). Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
st_re Опубликовано 3 октября, 2022 · Жалоба дата/время, 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 НО должны быть права у воркера на создание файлов с логами. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
alibek Опубликовано 3 октября, 2022 · Жалоба В 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 А вот это отлично, спасибо. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
st_re Опубликовано 3 октября, 2022 · Жалоба лог пишется в момент окончания обработки запроса.. если в пути на лог файл есть переменные. то он открывается (создаётся) в момент записи лога перебирая имена юзеров можно будет забить ФС околопустыми файлами... Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
ixi Опубликовано 3 октября, 2022 · Жалоба В 30.09.2022 в 09:26, alibek сказал: Я пока не понимаю, как мне декодировать заголовки (имя пользователя) и как логгировать ответы. Если именно нгинкс, можно посмотреть в сторону lua. Или написать свой прокси на знакомом языке Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
sirmax Опубликовано 3 октября, 2022 · Жалоба 19 часов назад, naves сказал: Вы хотите полный дебаг включая ответы от сервера. nginx тут не поможет. простой вариант запустить tcpdump и писать в файл. Более продвинутый вариант начать использовать log-коллекторы. Можно взять тот же elasticsearch с агентами filebeat (файловые логи), packetbeat (сетевой трафик). Выглядят страшно, но на самом деле несложно там. Все делается на нжинксе с луа дам пример как дойду до компа, с телефона неудобно Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
edo Опубликовано 10 октября, 2022 · Жалоба зачем тут lua? идём на http://nginx.org/en/docs/varindex.html всё есть, кроме «содержимое некоторых узлов в возвращаемом XML» Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
alibek Опубликовано 11 октября, 2022 · Жалоба Частично заработало, но никак не получается решить один момент. Речь идет про проксирование сервера Макроскоп. Проксирование нужно для того, чтобы контролировать использование учетных записей — штатных инструментов в Макроскопе для этого нет. Поэтому прокси-сервер будет логгировать доступ, а отдельный скрипт будет анализировать логи и выдавать уведомления при срабатывании. Для проксирования использую 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 ... Видимо это и есть видеопоток, который постоянно передается в незакрываемой сессии. Но в моем случае он не передается. Не подскажите, что нужно исправить, чтобы проксирование заработало? Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
Ivan_83 Опубликовано 11 октября, 2022 · Жалоба Посмотрите в отладочной консоли браузера что происходит и станет всё понятно. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
st_re Опубликовано 11 октября, 2022 · Жалоба В 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 ... Видимо это и есть видеопоток, который постоянно передается в незакрываемой сессии. Но в моем случае он не передается. Не подскажите, что нужно исправить, чтобы проксирование заработало? ДО этого должен быть запрос.. (ну и убедиться, что запрос идёт туда же, куда и остальной трафик.) ну и да, открыть нетворк монитор в браузере, и смотреть что посылается и что в ответ. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
alibek Опубликовано 11 октября, 2022 · Жалоба Это не через браузер происходит, а через мобильное приложение. Посмотреть будет сложно, разве что трафик сниффером записать. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
edo Опубликовано 12 октября, 2022 · Жалоба В 11.10.2022 в 11:58, alibek сказал: так и веб-версией В 12.10.2022 в 00:46, alibek сказал: Это не через браузер происходит что-то не сходится В 12.10.2022 в 00:46, alibek сказал: разве что трафик сниффером записать тоже вариант Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
ixi Опубликовано 13 октября, 2022 · Жалоба В 11.10.2022 в 11:58, alibek сказал: Не подскажите, что нужно исправить, чтобы проксирование заработало? попробуйте proxy_http_version 1.1; Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
st_re Опубликовано 13 октября, 2022 · Жалоба ну для начала понять откуда всётаки льётся видео. во многих системах, типа камер, видео льётся не по http и с другого порта, причем имя хоста может оказаться придётся подделать, чтобы за потоком оно пошло куда надо.. даже если отсю да же, то возможно не хватает локейшнов.. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
Ivan_83 Опубликовано 14 октября, 2022 · Жалоба Наиболее вероятно что откуда лится видео - отдаётся отдельной ссылкой, целиком url, и там либо ip либо хост, который разумеется за пределами локалки не достижим. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
boco Опубликовано 14 октября, 2022 · Жалоба В 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; } } Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
alibek Опубликовано 14 октября, 2022 · Жалоба В 14.10.2022 в 14:26, boco сказал: вся ваша куча локаций различается тока форматом лога. используйте вложенные локации О, спасибо, так намного удобнее. В 14.10.2022 в 14:26, boco сказал: для начала настройте самое тупое проксирование и убедитесь что оно работает Так оно и не работает. Возможно потому, что сервер отдает потоки в бесконечной сессии. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
alibek Опубликовано 14 октября, 2022 · Жалоба Обновленный конфиг: Скрытый текст 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), я не вижу, чтобы шли какие-то обращения. Как бы проверить, почему проксирование не работает? Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
alibek Опубликовано 14 октября, 2022 · Жалоба В 14.10.2022 в 16:01, alibek сказал: одновременно смотреть их через tcpdump нельзя -i any До чего техника дошла. Да, судя по трафику, все что соответствует вложенным location — не проксируется. Все что под них не попадает (то есть соответствует корневому location /) проксируется нормально. P.S. Если продублировать proxy_pass в каждом вложенном location, то возвращаюсь к тому, с чего начал — подключаюсь, получаю конфигурацию с сервера, но видеопотоки не работают. Но зато увидел в tcpdump, что нужно проксировать веб-сокет. Хотя бы ясно теперь, в какую сторону копать. P.P.S. Йес! Правда изображение тупит, но это уже настройки и тюнинг. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
boco Опубликовано 15 октября, 2022 · Жалоба В 14.10.2022 в 18:01, alibek сказал: Такое впечатление, как будто proxy_pass не срабатывает. я был неправ. нужно добавлять proxy_pass во вложенные локации, эта директива не наследуется, в отличие от proxy_set_header Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...