Логи Apache (ч. 1): Виды и модули журналов. Формат логов доступа Apache


Оглавление: Всё о логах Apache — от настройки до анализа

1. Виды и модули журналов. Формат логов доступа Apache

1.1 Виды логов Apache

1.2 Модули логов Apache

1.3 Модуль mod_log_config

1.4 Access Log (журнал доступа)

1.5 Как настроить формат логов Apache. Пользовательские форматы журналов

1.6 Директива BufferedLogs

1.7 Директива CustomLog

1.8 Директива GlobalLog

1.9 Директива LogFormat

1.10 Директива TransferLog

1.11 Форматы журналов Apache

1.11.1 Common Log Format (общий формат журнала)

1.11.2 Combined Log Format (Формат комбинированного журнала)

1.11.3 Multiple Access Logs (Журналы множественного доступа)

1.11.4 Conditional Logs (логи с условиями)

1.12 Ротация логов

1.13 Конвейерная обработка (Piped Logs)

1.14 Виртуальные Хосты

1.15 Вопросы безопасности


2. Формат логов ошибок. Журнал событий модулей

3. Программы для анализа логов Apache

4. Криминалистические логи

5. Дополнительные настраиваемые журналы отладки. Журналы выполнения CGI скриптов


Примечание: данный цикл статей посвящён файлам журналов (логам) веб-сервера Apache, рассматривается их настройка, формат, команды, а также специальные программы для анализа журналов веб-сервера. Информация изложена подробно для глубокой проработки темы, а также для использования в качестве справочного материала. Если вам нужна более краткая информация, то рекомендуется обратиться к статье «Apache log (логи): как настроить и анализировать журналы веб-сервера».

Чтобы эффективно управлять веб-сервером, необходимо получать отзывы об активности и производительности сервера, а также о любых проблемах, которые могут возникнуть. HTTP-сервер Apache предоставляет очень широкие и гибкие возможности ведения журналов.

HTTP-сервер Apache предоставляет множество различных механизмов для регистрации всего, что происходит на вашем сервере, от первоначального запроса и процесса сопоставления URL-адресов, до окончательного разрешения соединения, включая любые ошибки, которые могли возникнуть в процессе. В дополнение к этому сторонние модули могут предоставлять возможности ведения журналов или вставлять записи в существующие файлы журналов, а приложения, такие как программы CGI, сценарии PHP или другие обработчики, тоже могут отправлять сообщения в журнал ошибок сервера.

Журналы веб-сервер содержат массу интересной информации! По логам доступа сервера можно составить собирательный портрет аудитории: в каких странах и городах живут, какими операционными системами пользуются, какими браузерами просматривают сайт, в какое время активны больше всего, с каких сайтов пришли к вам, какие поисковые системы предпочитают, сколько страниц просматривают за каждое посещение сайта. И не менее важны логи для мониторинга состояния веб-сервера и сайтов: какие страницы не были найдены, ошибки веб-сервера, степень загруженности, выявление активности ботов, выявление вредоносной активности, поиск следов взлома, выявление путей взлома.

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

Первая часть посвящена настройке формата журналов в веб-сервере Apache. Эта информация пригодится вам даже если даже если у вас нет сайтов и вы не занимаетесь обслуживанием веб-сервера. Она понадобится чтобы уметь анализировать веб журналы с помощью инструментов (как правило в них нужно указать формат анализируемого журнала, для указания которых используются те же спецификаторы, что и в конфиге Apache).

Виды логов Apache

Различные виды журналов Apache управляются разными модулями веб-сервера и имеют разные управляющие директивы и возможности указать формат строки лога.

Имеются следующие виды логов веб-сервера Apache:

  • Error Log (журнал ошибок)
  • Per-module logging (журналирование событий модулей)
  • Access Log (журнал доступа)
  • Additional configurable debug logging (Дополнительные настраиваемые журналы отладки)
  • Forensic (криминалистические логи)
  • Журналы выполнения CGI скриптов

Далее дана краткая характеристика каждого вида журнала, а затем в этой первой части будет подробно рассмотрен Журнал доступа. В последующих частях будут подробно рассмотрены другие виды логов.

Error Log (Журнал ошибок)

Журнал ошибок сервера является наиболее важным файлом журнала. Это место, куда Apache httpd будет отправлять диагностическую информацию и записывать любые ошибки, с которыми он сталкивается при обработке запросов. Это первое место, где нужно посмотреть, когда возникает проблема с запуском сервера или работой сервера, поскольку он часто содержит подробности о том, что пошло не так и как это исправить.

Per-module logging (журналирование событий модулей)

Директива LogLevel позволяет вам указывать уровень важности журнала для каждого модуля. Таким образом, если вы устраняете проблему только с одним конкретным модулем, вы можете увеличить его объем в журнале, при этом не получая лишней информации о других модулях, которые вас не интересуют. Это особенно полезно для таких модулей, как mod_proxy или mod_rewrite где вы хотите узнать подробности о том, что он пытается сделать.


Access Log (Журнал доступа)

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

Additional configurable debug logging (Дополнительные настраиваемые журналы отладки)

Эта директива заставляет пользовательское сообщение регистрироваться в журнале ошибок. Сообщение может использовать переменные и функции из синтаксиса ap_expr. Ссылки на заголовки HTTP не приводят к добавлению имён заголовков в заголовок Vary. Сообщения регистрируются на уровне лога.

Forensic (криминалистические логи)

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

Журналы выполнения CGI скриптов

Если ScriptLog не указан, журнал ошибок не создаётся. Если ScriptLog установлен, то любые ошибки CGI регистрируются в файле, указанном в качестве аргумента.

Модули логов Apache

В Apache есть несколько модулей, которые отвечают за веб журналы:

  • mod_log_config. Ведёт журнал запросов, сделанных к серверу. Это основной модуль, который включён по умолчанию и именно он сохраняет информацию о запросах. В основном, здесь мы будем рассматривать именно этот модуль и его настройки. Обеспечивает работу Access Log (журнал доступа).
  • mod_log_debug. Дополнительные настраиваемые журналы отладки. Обеспечивает работу Additional configurable debug logging (Дополнительные настраиваемые журналы отладки). Имеет экспериментальный статус.
  • mod_log_forensic. Криминалистическая регистрация запросов к серверу. Обеспечивает работу Forensic (криминалистические логи).
  • mod_logio. Регистрация входных и выходных байтов каждого запроса. Этот модуль должен быть включён в конфигурации Apache, если вы хотите в журнале сохранять информацию о количестве переданных и/или полученных данных. Обеспечивает работу некоторых возможностей формата Access Log (журнал доступа).
  • Apache Core Features — Основные функции Apache HTTP Server, которые всегда доступны. В том числе обеспечивает работу Error Log (журнала ошибок) и Per-module logging (журналирование событий модулей).
  • mod_cgi и mod_cgid. Обеспечивают работу Журнала выполнения CGI скриптов.

Модуль mod_log_config

Модуль mod_log_config обеспечивает гибкое журналирование клиентских запросов. Логи пишутся в настраиваемом формате и могут быть записаны непосредственно в файл или во внешнюю программу. Предоставляется запись логов под условием, то есть индивидуальные запросы могут быть включены или исключены из журнала на основе характеристики запроса. Этот модуль является ключевым для обеспечения работы Access Log (журнал доступа).

Этот модуль поддерживает следующие директивы:

  • TransferLog для создания файла журнала,
  • LogFormat для установки пользовательского формата. После данной директивы указывается строка формата логов, а также имя, которое можно использовать в качестве псевдонима для данной строки. После установления псевдонима этой директивой, его можно указать в CustomLog.
  • CustomLog для определения файла и формата журнала за один шаг. Устанавливает способ сохранения файла журнала (например, в файл), а также используемый формат. В качестве формата может принимать псевдоним, установленный с помощью директивы LogFormat, либо строку формата.
  • BufferedLogs. Сохранять записи журнала в памяти перед записью на диск
  • GlobalLog. Устанавливает имя файла и формат файла журнала

Директивы TransferLog и CustomLog на каждом сервере могут использоваться несколько раз, чтобы каждый запрос регистрировался в нескольких файлах.

Access Log (журнал доступа)

Журнал доступа к серверу записывает все запросы, обработанные сервером. Расположение и содержимое журнала доступа контролируются директивой CustomLog. Директива LogFormat может быть использована для упрощения выбора содержимого журналов. В этом разделе описывается, как настроить сервер для записи информации в журнал доступа.

Конечно, хранение информации в журнале доступа — это только начало управления журналом. Следующим шагом является анализ этой информации для получения полезной статистики. Анализ журналов в целом выходит не является частью работы самого веб-сервера, но будет рассмотрен в одной из последующих статей данного цикла.

Различные версии Apache httpd использовали другие модули и директивы для управления журналом доступа, включая mod_log_referer, mod_log_agent и директиву TransferLog. Директива CustomLog теперь включает в себя функциональность всех старых директив.

Формат журнала доступа легко настраивается. Формат указывается с использованием строки формата, которая очень похожа на строку формата printf(1) в стиле C. Некоторые примеры представлены далее. Полный список возможного содержимого строки формата смотрите в следующем разделе «Как настроить формат логов доступа Apache. Пользовательские форматы журналов».

То есть с практической точки зрения, Access Log (журнал доступа) это то же самое, что и mod_log_config, поскольку именно этот модуль обеспечивает функциональность Access Log. Дополнительно Access Log используют модули mod_logio и mod_setenvif для расширения функциональность. Например, модуль mod_logio позволяет записывать в журнал точный размер переданных и(или) полученных данных во время запроса пользователя и ответа ему.

Поскольку это одно и то же, то директивы у Access Log и mod_log_config одинаковые. Дальнейшая информация в этом разделе относится к Access Log и mod_log_config.


Как настроить формат логов доступа Apache. Пользовательские форматы журналов

Аргументом формата для директив LogFormat и CustomLog является строка. На основе этой строки будет сформированы записи в файл журнала для каждого запроса. Данная строка может содержать буквальные символы, которые будут скопированные в файлы журнала такими, как они есть, и управляющие символы в стиле C "\n" и "\t" для записи символов new-line (новая строка) и tab (табуляция). Буквальные кавычки и обратные слэши следует экранировать с помощью обратной косой черты (\).

Различные характеристики запроса обозначаются строками, которые начинаются с символа «%». В файле журнала такие строки будут заменены следующими значениями:

Строка формата Описание
%% Буквальный знак процента.
%a Клиентский IP адрес запроса (смотрите также модуль mod_remoteip).
%{c}a Лежащий в основе IP-адрес соединения (см. модуль mod_remoteip).
%A Локальный IP-адрес.
%B Размер ответа в байтах, исключая HTTP заголовки.
%b Размер ответа в байтах, исключая HTTP заголовки. В формате CLF, то есть когда баты не отправлены, то будет '-', а не 0.
%{VARNAME}C Содержимое куки VARNAME в запросе, отправленном серверу. Полностью поддерживается только куки версии 0.
%D Время, затраченное на обработку запроса в микросекундах. Дополнительные подробности смотрите в описании %T.
%{VARNAME}e Содержимое переменной окружения VARNAME.
%f Имя файла.
%h Имя удалённого хоста. Запишет IP адрес, если HostnameLookups установлена на Off, это является значением по умолчанию. Если регистрируется имя хоста только для нескольких хостов, возможно, у вас есть директивы контроля доступа, в которых они упоминаются по имени. См. документацию Require host. На этот формат влияют модификации имени удалённого хоста такими модулями, как mod_remoteip.
%{c}h Как %h, но всегда сообщает об имени хоста лежащего в основе TCP-соединения, а не о каких-либо модификациях в имени удалённого хоста такими модулями, как mod_remoteip.
%H Протокол запроса.
%{VARNAME}i Содержимое VARNAME: строка(и) заголовка в запросе, отправленном на сервер. Изменения, сделанные другими модулями (например, mod_headers), влияют на это. Если вас интересует, какой заголовок запроса был до того, когда большинство модулей изменили бы его, используйте mod_setenvif, чтобы скопировать заголовок во внутреннюю переменную среды и запишите в журнал значение описанной выше %{VARNAME}e. Примеры таких переменных: %{Referer}i (реферер), %{User-agent}i (пользовательский агент, браузер).
%k Количество запросов keepalive, обработанных для этого соединения. Интересно, если используется KeepAlive, например, «1» означает первый запрос keepalive после исходного, «2» — второй и т. д.; в противном случае это всегда 0 (указывает на начальный запрос).
%l Имя удалённого журнала (от identd, если есть). Это вернёт тире, если не присутствует mod_ident и для IdentityCheck не установлено значение On.
%L Идентификатор журнала запросов из журнала ошибок (или «-», если в журнал ошибок для этого запроса ничего не было занесено). Найдите соответствующую строку журнала ошибок, чтобы узнать, какой запрос вызвал какую ошибку.
%{c}L Идентификатор журнала подключений из журнала ошибок (или «-», если в журнал ошибок для этого запроса ничего не записано). Найдите соответствующую строку журнала ошибок, чтобы узнать, какой запрос вызвал какую ошибку.
%m Метод запроса.
%{VARNAME}n Содержимое заметки VARNAME из другого модуля.
%{VARNAME}o Содержимое VARNAME: строки заголовка в ответе.
%p Канонический порт сервера, обслуживающего запрос.
%{формат}p Канонический порт сервера, обслуживающего запрос, или фактический порт сервера, или фактический порт клиента. Допустимые форматы: canonical, local или remote.
%P Идентификатор дочернего процесса, который обслуживал запрос.
%{формат}P Идентификатор процесса или идентификатор дочернего потока, который обслуживал запрос. Допустимые форматы: pid, tid и hextid. hextid требует APR 1.2.0 или выше.
%q Строка запроса (с префиксом ? если строка запроса существует, в противном случае — пустая строка).
%r Первая строка запроса
%R Обработчик, генерирующий ответ (если есть).
%s Статус. Для запросов, которые были внутренне перенаправлены, это статус исходного запроса. Используйте %>s для окончательного статуса.
%t Время получения запроса в формате [18/Sep/2011:19:18:28 -0400]. Последнее число указывает на смещение часового пояса от GMT
%{format}t

Время в форме, заданной форматом, которое должно быть в расширенном формате strftime(3) (возможно, локализовано). Если формат начинается с begin: (по умолчанию) время берётся в начале обработки запроса. Если он начинается с end: это время записи в журнал, близкое к концу обработки запроса. В дополнение к форматам, поддерживаемым strftime(3), поддерживаются следующие маркеры формата:

sec количество секунд с начала Эпохи

msec число миллисекунд с начала Эпохи

usec микросекунд с начала Эпохи

msec_frac доли миллисекунд

usec_frac доли микросекунд

Эти токены в одной строке формата нельзя объединять друг с другом или форматированием strftime(3). Вместо этого вы можете использовать несколько токенов %{format}t.

Пример: %{%d/%b/%Y %T}t.%{msec_frac}t %{%z}t

%T

Время, затраченное на обслуживание запроса, в секундах. Измеренное время начинается, когда HTTP-сервер читает первую строку HTTP-запроса из операционной системы хоста, и заканчивается, когда последний байт ответа записывается HTTP-сервером в операционную систему хоста.

Измеренное время не включает в себя ничего из следующего:

  • Время, потраченное на TCP или TLS рукопожатия.
  • Время до того, как поток веб-сервера сможет прочитать первую строку запроса.
  • Задержки в выдаче операционной системы данных ответа в сеть.
  • Время, необходимое для получения ответа на хосте клиента.
  • Время, затраченное пользовательским агентом на чтение и обработку ответа.
%{UNIT}T Время, затраченное на обслуживание запроса, в единицах времени, указанных UNIT. Допустимые единицы измерения — ms для миллисекунд, us для микросекунд и s для секунд. Использование s даёт тот же результат, что и %T без какого-либо формата; использование us даёт тот же результат, что и %D. Объединение %T с юнитом доступно в 2.4.13 и более поздних версиях.
%u Удаленный пользователь, если запрос был аутентифицирован. Может быть поддельным, если статус возврата (%s) равен 401 (не авторизован).
%U Запрошенный путь URL, не включая строку запроса.
%v Каноническое ServerName сервера, обслуживающего запрос.
%V Имя сервера в соответствии с настройкой UseCanonicalName.
%X

Состояние соединения, когда ответ завершён:

X = Соединение прервано до завершения ответа.

+ = Соединение может оставаться активным после отправки ответа.

— = Соединение будет закрыто после отправки ответа.

%I Получено байтов, включая запрос и заголовки. Не может быть ноль. Вы должны включить mod_logio, чтобы использовать это.
%O Отправлено байтов, включая заголовки. Может быть в редких случаях нулём, например, когда запрос прерывается перед отправкой ответа. Вы должны включить mod_logio, чтобы использовать это.
%S Переданные (полученные и отправленные) байты, включая запрос и заголовки, не могут быть равны нулю. Это комбинация %I и %O. Вы должны включить mod_logio, чтобы использовать это.
%{VARNAME}^ti Содержимое VARNAME: трейлерные строки в запросе, отправленном на сервер.
%{VARNAME}^to Содержимое VARNAME: трейлерные строки в запросе, отправленном с сервера.

Модификаторы

Отдельные элементы могут быть ограничены для печати только для ответов с определёнными кодами состояния HTTP, помещая разделённый запятыми список кодов состояния сразу после "%". Списку кодов состояния может предшествовать "!" чтобы указать отрицание.

Строка формата Значение
%400,501{User-agent}i Регистрирует User-agent только при возникновении ошибок 400 и ошибок 501. Для других кодов состояния будет записана буквальная строка «-».
%!200,304,302{Referer}i Регистрирует Referer всех запросов, которые не возвращают один из трёх указанных кодов, в противном случае будет записано "-".

Модификаторы «<» и «>» нужны чтобы выбирать, следует ли записывать исходный или окончательный запрос. Это можно использовать для запросов, которые были перенаправлены внутри. По умолчанию % директивы %s, %U, %T, %D и %r смотрят на исходный запрос, а все остальные смотрят на окончательный запрос. Так, например, %>s можно использовать для записи окончательного состояния запроса, а %<u можно использовать для записи исходного аутентифицированного пользователя по запросу, внутренне перенаправленному на неаутентифицированный ресурс.

Примечания к форматам

По соображениям безопасности, начиная с версии 2.0.46, непечатаемые и другие специальные символы в %r, %i и %o экранируются с помощью последовательностей \xhh, где hh обозначает шестнадцатеричное представление необработанного байта. Исключениями из этого правила являются " и \, которые экранируются путём добавления обратной косой черты и всех пробельных символов, которые записываются с использованием нотации в стиле C (\n, \t и т. Д.). В версиях, предшествующих 2.0.46, для этих строк экранирование не выполнялось, поэтому вы должны быть достаточно осторожны при работе с необработанными лог-файлами в этих версиях.

Поскольку в httpd 2.0, в отличие от 1.3, строки формата %b и %B представляют не количество байтов, отправленных клиенту, а просто размер в байтах ответа HTTP (который будет отличаться, например, если соединение прервано) или если используется SSL). Формат %O, предоставляемый mod_logio, регистрирует фактическое количество байтов, отправленных по сети.

Примечание: mod_cache реализован как быстрый обработчик, а не как стандартный обработчик. Следовательно, строка формата %R не будет возвращать никакой информации обработчика, когда задействовано кэширование содержимого.

Примечание. Символ «^» в начале трёхсимвольных форматов не имеет значения, но он должен быть первым символом любого вновь добавленного трёхсимвольного формата, чтобы избежать потенциальных конфликтов с форматами журналов, в которых используются буквальные строки, смежные со спецификатором формата, такие как "%Dus".

Примеры

Некоторые часто используемые строки формата журнала:


  • Common Log Format (CLF) — обычный формат журнала
"%h %l %u %t \"%r\" %>s %b"
  • Common Log Format with Virtual Host — обычный формат журнала с виртуальными хостами
"%v %h %l %u %t \"%r\" %>s %b"
  • NCSA extended/combined log format — NCSA расширенный/комбинированный формат журнала
"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
  • Referer log format — формат записи Referer
"%{Referer}i -> %U"
  • Agent (Browser) log format — формат записи пользовательского агента (браузера)
"%{User-agent}i"

Вы можете использовать директиву %{format}t несколько раз для построения формата времени, используя расширенные маркеры формата, такие как msec_frac:

  • Метка времени, включающая миллисекунды:
"%{%d/%b/%Y %T}t.%{msec_frac}t %{%z}t"

Директива BufferedLogs

Описание: Сохраняет записи журнала в памяти перед записью на диск.

Синтаксис:

BufferedLogs On|Off

Значение по умолчанию:

BufferedLogs Off

Контекст: server config

Директива BufferedLogs заставляет mod_log_config хранить несколько записей журнала в памяти и записывать их вместе на диск, а не записывать их после каждого запроса. В некоторых системах это может привести к более эффективному доступу к диску и, следовательно, к более высокой производительности. Он может быть установлен только один раз для всего сервера; его нельзя настроить для каждого виртуального хоста.

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

Директива CustomLog

Описание: устанавливает имя файла и формат файла журнала.

Синтаксис:

CustomLog file|pipe|provider format|nickname [env=[!]environment-variable| expr=expression]

Контекст: server config, виртуальные хосты

Директива CustomLog используется для регистрации запросов к серверу. Указывается формат журнала, способ записи в журнал, здесь же можно указать условие на основе характеристиками запроса с использованием переменных среды при котором будет сделана запись в журнале.

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

file

Имя файла относительно ServerRoot.

pipe

Символ трубы "|", за которым следует путь к программе которая получит записи логов на её стандартном вводе. Для получения дополнительной информации смотрите ниже раздел Piped Logs (конвейерная обработка).

Безопасность: если используется программа, она будет запущена от имени пользователя, запустившего httpd. Это будет root, если сервер был запущен от root; убедитесь, что программа безопасна.

Примечание: при вводе пути к файлу на платформах, отличных от Unix, необходимо следить за тем, чтобы использовались только прямые косые черты, даже если платформа может разрешать использование обратных косых черт. Как правило, рекомендуется всегда использовать прямые косые черты в файлах конфигурации.

provider

Модули, реализующие поставщиков ErrorLog, также могут использоваться в качестве цели для сообщений CustomLog. Чтобы использовать провайдера ErrorLog в качестве цели, необходимо использовать синтаксис «provider:argument». Например, вы можете использовать mod_journald или mod_syslog в качестве провайдера:

# Журналирование CustomLog к journald
CustomLog "journald" "%h %l %u %t \"%r\" %>s %b"

# Журналирование CustomLog к syslog с объектом "user"
CustomLog "syslog:user" "%h %l %u %t \"%r\" %>s %b"

Второй аргумент указывает, что будет записано в файл журнала. Он может указывать либо псевдоним, определённый предыдущей директивой LogFormat, либо это может быть явная строка формата, как описано в разделе «Как настроить формат логов Apache. Пользовательские форматы журналов».

Например, следующие два набора директив имеют абсолютно одинаковый эффект:

1.

# CustomLog с указанием псевдонима формата
LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog "logs/access_log" common

2.

# CustomLog с явно указанной строкой формата
CustomLog "logs/access_log" "%h %l %u %t \"%r\" %>s %b"

Третий аргумент является необязательным и определяет, регистрировать или нет конкретный запрос. Условием может быть наличие или отсутствие (в случае предложения 'env=!name') определённой переменной в среде сервера. Альтернативно, условие может быть выражено как произвольное логическое выражение. Если условие не выполнено, запрос не будет зарегистрирован. Ссылки на заголовки HTTP в выражении не приводят к добавлению имён заголовков в заголовок Vary.

Переменные среды могут быть установлены для каждого запроса с использованием модулей mod_setenvif и/или mod_rewrite (смотрите здесь и здесь). Например, если вы хотите записать запросы для всех изображений GIF на вашем сервере в отдельный файл журнала, но не в свой основной журнал, вы можете использовать:

SetEnvIf Request_URI \.gif$ gif-image
CustomLog "gif-requests.log" common env=gif-image
CustomLog "nongif-requests.log" common env=!gif-image

Или, чтобы воспроизвести поведение старой директивы RefererIgnore, вы можете использовать следующее:

SetEnvIf Referer example\.com localreferer
CustomLog "referer.log" referer env=!localreferer

Директива GlobalLog

Описание: Устанавливает имя файла и формат файла журнала.

Синтаксис:

GlobalLog file|pipe|provider format|nickname [env=[!]environment-variable| expr=expression]

Контекст: server config

Совместимость: Доступна в Apache HTTP Server 2.4.19 и более поздних.

Директива GlobalLog определяет журнал, общий для конфигурации основного сервера и всех настроенных виртуальных хостов.

Директива GlobalLog идентична директиве CustomLog, за исключением следующих отличий:

  • GlobalLog недопустима в контексте виртуального хоста.
  • GlobalLog используется виртуальными хостами, которые определяют свой собственный CustomLog, а не глобально определённый CustomLog.

Директива LogFormat

Описание: описывает формат для использования в файле журнала.

Синтаксис:

LogFormat формат|псевдоним [псевдоним]

Значение по умолчанию:

LogFormat "%h %l %u %t \"%r\" %>s %b"

Контекст: server config, виртуальные хосты.

Эта директива определяет формат файла журнала доступа.

Директива LogFormat может принимать одну из двух форм. В первой форме, где указан только один аргумент, эта директива устанавливает формат журнала, который будет использоваться журналами, указанными в последующих директивах TransferLog. Один аргумент может указывать явный формат, как обсуждалось в разделе о пользовательских форматах журналов выше. Кроме того, он может использовать псевдоним для ссылки на формат журнала, определённый в предыдущей директиве LogFormat, как описано ниже.

Вторая форма директивы LogFormat связывает явный формат с псевдонимом. Этот псевдоним можно затем использовать в последующих директивах LogFormat или CustomLog, а не повторять всю строку формата. Директива LogFormat, определяющая псевдоним, больше ничего не делает, то есть определяет только псевдоним, фактически не применяет формат и не устанавливает его по умолчанию. Следовательно, это не повлияет на последующие директивы TransferLog. Кроме того, LogFormat не может использовать один псевдоним для определения другого псевдонима. Обратите внимание, что псевдоним не должен содержать знаки процента (%).

Пример:

LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common

Директива TransferLog

Описание: определяет размещение файла журнала.

Синтаксис:

TransferLog файл|труба

Контекст: server config, виртуальные хосты

Эта директива имеет те же аргументы и эффект, что и директива CustomLog, за исключением того, что она не позволяет явно указывать формат журнала или регистрировать запросы на основе условий. Вместо этого формат журнала определяется самой последней указанной директивой LogFormat, которая не определяет псевдоним. Общий формат журнала используется, если не указан другой формат.

Пример:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
TransferLog "logs/access_log"

Форматы журналов Apache

Common Log Format (общий формат журнала)

Типичная конфигурация для журнала доступа может выглядеть следующим образом.

LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog "logs/access_log" common

Она задаёт псевдоним common и связывает его с определённой строкой формата журнала. Строка формата состоит из директив со знаком процента, каждая из которых указывает серверу регистрировать определённый фрагмент информации. Буквальные символы также могут быть помещены в строку формата и будут скопированы непосредственно в вывод журнала. Символ кавычки (") должен быть экранирован путём размещения обратной косой черты перед ним, чтобы он не интерпретировался как конец строки формата. Строка формата также может содержать специальные управляющие символы "\n" для новой строки и "\t" для табуляции.

Директива CustomLog устанавливает новый файл журнала, используя определённый псевдоним. Имя файла для журнала доступа определяется относительно ServerRoot, если оно не начинается с косой черты.

Приведённая выше конфигурация будет записывать записи журнала в формате, известном как Common Log Format (CLF). Этот стандартный формат может создаваться многими различными веб-серверами и считываться многими программами анализа журналов. Записи файла журнала, созданные в CLF, будут выглядеть примерно так:

95.152.63.100 - frank [18/Aug/2019:08:58:34 +0300] "GET /ru/?act=myip HTTP/1.1" 200 25858

Каждая часть этой записи журнала описана ниже.

95.152.63.100 (%h)

Это IP-адрес клиента (удалённого хоста), который сделал запрос к серверу. Если для HostnameLookups установлено значение On, сервер попытается определить имя хоста и записать его вместо IP-адреса. Однако такая конфигурация не рекомендуется, поскольку она может значительно замедлить работу сервера. Вместо этого лучше всего использовать постпроцессор журнала, такой как logresolve, для определения имён хостов. Указанный здесь IP-адрес не обязательно является адресом машины, на которой сидит пользователь. Если между пользователем и сервером существует прокси-сервер, этот адрес будет адресом прокси, а не исходной машины.

— (%l)

«Дефис» в выходных данных указывает на то, что запрошенная часть информации недоступна. В этом случае информация, которая недоступна, является идентификационной информацией клиента RFC 1413, определённой с помощью identd на клиентском компьютере. Эта информация крайне ненадёжна и почти никогда не должна использоваться, кроме как в жёстко контролируемых внутренних сетях. Apache httpd даже не будет пытаться определить эту информацию, если для IdentityCheck не установлено значение On.

frank (%u)

Это идентификатор пользователя, запрашивающего документ, как он был определён HTTP-аутентификацией. Такое же значение обычно предоставляется сценариям CGI в переменной среды REMOTE_USER. Если код состояния для запроса равен 401, то этому значению не следует доверять, поскольку пользователь ещё не аутентифицирован. Если документ не защищён паролем, эта часть будет "-", как и предыдущая.

[18/Aug/2019:08:58:34 +0300] (%t)

Время получения запроса. Формат такой:

[день/месяц/год:час:минута:секунда зона]

день = 2*цифры

месяц = 3*буквы

год = 4*цифры

час = 2*цифры

минута = 2*цифры

секунда = 2*цифры

зона = (`+' | `-') 4*цифры

Можно отобразить время в другом формате, указав %{format}t в строке формата журнала, где формат такой же, как в strftime(3) из стандартной библиотеки C, или один из поддерживаемых специальных маркеров. Подробности смотрите выше в разделе «Как настроить формат логов Apache. Пользовательские форматы журналов».

"GET /ru/?act=myip HTTP/1.1" (\"%r\")

Строка запроса от клиента указанная в двойных кавычках. Строка запроса содержит много полезной информации. Во-первых, клиент использует метод GET. Во-вторых, клиент запросил ресурс /ru/?act=myip, и в-третьих, клиент использовал протокол HTTP/1.1. Также возможно зарегистрировать одну или несколько частей строки запроса независимо. Например, строка формата "%m %U%q %H" будет регистрировать метод, путь, строку запроса и протокол, что приведёт к точно такому же выводу, что и "%r".

200 (%>s)

Это код состояния, который сервер отправляет обратно клиенту. Эта информация очень ценна, поскольку она показывает, привёл ли запрос к успешному ответу (коды начинаются с 2), к перенаправлению (коды начинаются с 3), к ошибке, вызванной клиентом (коды начинаются с 4), или к ошибкам на сервере (коды начинаются с 5). Полный список возможных кодов состояния можно найти в спецификации HTTP (RFC2616 раздел 10).

25858 (%b)

Последняя часть указывает размер объекта, возвращаемого клиенту, не включая заголовки ответа. Если контент не был возвращён клиенту, это значение будет "-". Чтобы записывался «0» при отсутствии содержимого, используйте %B.

Combined Log Format (Формат комбинированного журнала)

Другая широко используемая строка формата называется Combined Log Format. Может использоваться следующим образом.

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
CustomLog "log/access_log" combined

Этот формат точно такой же, как Common Log Format, с добавлением ещё двух полей. Каждое из дополнительных полей использует директиву с процентом %{header}i, где header может быть любым заголовком HTTP-запроса. Журнал доступа в этом формате будет выглядеть так:

2a02:2168:a13:430b::1 - - [18/Aug/2019:09:38:53 +0300] "POST /ru/?act=locatepicture HTTP/1.1" 200 25627 "https://suip.biz/ru/?act=locatepicture" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"

Обратите внимание, что в качестве IP адреса также может быть IPv6 как в примере выше.

Дополнительными полями являются:

"https://suip.biz/ru/?act=locatepicture" (\"%{Referer}i\")

Это заголовок HTTP запроса "Referer". В этой строке клиент сообщает сайту, с какого сайта и какой страницы он пришёл (это должна быть страница, на которой размещена ссылка на запрошенный адрес, либо страница, которая включает в себя запрошенный файл (например, изображение).

"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" (\"%{User-agent}i\")

Заголовок HTTP-запроса User-Agent. Это идентифицирующая информация, которую клиентский браузер сообщает о себе.

Multiple Access Logs (Журналы множественного доступа)

Журналы множественного доступа могут быть созданы просто путём указания нескольких директив CustomLog в файле конфигурации. Например, следующие директивы создадут три журнала доступа. Первый содержит основную информацию CLF, а второй и третий содержат информацию о реферере и браузере. Последние две строки CustomLog показывают, как имитировать эффекты директив ReferLog и AgentLog.

LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog "logs/access_log" common
CustomLog "logs/referer_log" "%{Referer}i -> %U"
CustomLog "logs/agent_log" "%{User-agent}i"

Этот пример также показывает, что нет необходимости определять псевдоним с помощью директивы LogFormat. Вместо этого формат журнала может быть указан непосредственно в директиве CustomLog.

Conditional Logs (логи с условиями)

Есть моменты, когда удобно исключать определённые записи из журналов доступа на основе характеристик клиентского запроса. Это легко сделать с помощью переменных среды. Во-первых, необходимо установить переменную среды, чтобы указать, что запрос удовлетворяет определенным условиям. Обычно это достигается с помощью SetEnvIf. Затем условие env= директивы CustomLog используется для включения или исключения запросов, в которых установлена переменная среды. Некоторые примеры:

# Пометить запросы из loop-back (петлевого) интерфейса
SetEnvIf Remote_Addr "127\.0\.0\.1" dontlog
# Пометить запросы на файл robots.txt
SetEnvIf Request_URI "^/robots\.txt$" dontlog
# Записать то, что осталось
CustomLog "logs/access_log" common env=!dontlog

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

SetEnvIf Accept-Language "en" english
CustomLog "logs/english_log" common env=english
CustomLog "logs/non_english_log" common env=!english

В сценарии кеширования хотелось бы узнать об эффективности кеша. Очень простой способ выяснить это будет:

SetEnv CACHE_MISS 1
LogFormat "%h %l %u %t "%r " %>s %b %{CACHE_MISS}e" common-cache
CustomLog "logs/access_log" common-cache

mod_cache будет запущен до mod_env и, в случае успеха, доставит контент без него. В этом случае кеш приведёт к появлению записи -, а если кеш отсутствует, то будет записано 1.

В дополнение к синтаксису env=, LogFormat поддерживает значения регистрации переменных, зависящие от кода ответа HTTP:

LogFormat "%400,501{User-agent}i" browserlog
LogFormat "%!200,304,302{Referer}i" refererlog

В первом примере User-agent будет записан в журнал, если код состояния HTTP равен 400 или 501. В других случаях вместо него будет записана буквальная строка «-». Аналогично, во втором примере Referer будет записан в журнал, если код состояния HTTP не равен 200, 204 или 302. (обратите внимание на «!» перед кодами состояния).

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

Ротация логов

Даже на умеренно загруженном сервере количество информации, хранящейся в файлах журнала, очень велико. Файл журнала доступа обычно увеличивается на 1 МБ или более на 10 000 запросов. Следовательно, необходимо периодически ротировать файлы журналов, перемещая или удаляя существующие журналы. Это невозможно сделать во время работы сервера, поскольку Apache httpd продолжит запись в старый файл журнала, пока он удерживает этот файл открытым. Вместо этого сервер должен быть перезапущен после перемещения или удаления файлов журнала, чтобы открыть новые файлы журнала.

Используя graceful перезапуск, сервер может получить команду открывать новые файлы журнала, не теряя ни существующих, ни ожидающих соединений от клиентов. Однако для этого сервер должен продолжать запись в старые файлы журнала, пока он завершает обслуживание старых запросов. Поэтому необходимо подождать некоторое время после перезапуска, прежде чем выполнять какую-либо обработку файлов журнала. Типичный сценарий, который просто ротирует журналы и сжимает старые журналы для экономии места:

mv access_log access_log.old
mv error_log error_log.old
apachectl graceful
sleep 600
gzip access_log.old error_log.old

Другой способ выполнения ротации журналов — это использование конвейерной обработки, как описано в следующем разделе.

Конвейерная обработка (Piped Logs)

Apache httpd способен записывать файлы журналов доступа и ошибок по трубе (через канал) к другому процессу, а не напрямую в файл. Эта возможность значительно повышает гибкость ведения журнала без добавления кода на главный сервер. Чтобы записывать журналы в трубу, просто замените имя файла на символ трубы «|», за которым следует имя исполняемого файла, который должен принимать записи журнала на своём стандартном входе. Сервер при старте сервера запустит процесс piped-log и перезапустит его, если он выйдет из строя во время работы сервера (эта последняя функция позволяет назвать эту технику "надёжная передача журнала по трубе".)

Процессы конвейерного журнала порождаются родительским процессом Apache httpd и наследуют идентификатор пользователя этого процесса. Это означает, что программы логов по конвейеру обычно запускаются с правами root. Поэтому очень важно, чтобы программы были простыми и безопасными.

Одно из важных применений конвейерных журналов — разрешить ротацию журналов без перезагрузки сервера. HTTP-сервер Apache включает в себя простую программу rotatelogs для этой цели. Например, чтобы ротировать журналы каждые 24 часа, вы можете использовать:

CustomLog "|/usr/local/apache/bin/rotatelogs /var/log/access_log 86400" common

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

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

По умолчанию процесс передаваемого по трубе журнала порождается без вызова оболочки. Используйте "|$" вместо "|" для запуска с оболочкой (обычно с /bin/sh -c):

# Вызов "rotatelogs" используя оболочку
CustomLog "|$/usr/local/apache/bin/rotatelogs /var/log/access_log 86400" common

Это было поведение по умолчанию для Apache 2.2. В зависимости от специфики оболочки это может привести к дополнительному процессу оболочки на время жизни программы канала журнала и проблемам с обработкой сигналов при перезапуске. По причинам совместимости с Apache 2.2 обозначение «||» также поддерживается и эквивалентно использованию «|».

Примечание для Windows: обратите внимание, что в Windows вы можете столкнуться с проблемами при запуске многих процессов журналирования, особенно когда HTTPD работает как служба. Это вызвано нехваткой heap space рабочего стола. Пространство heap space рабочего стола, предоставляемое каждой службе, задаётся третьим аргументом параметра SharedSection в значении реестра HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SessionManager\SubSystems\Windows. Измените это значение с осторожностью; применяются обычные предостережения для изменения реестра Windows, но вы можете также исчерпать пул heap space рабочего стола, если число будет установлено слишком высоко.

Виртуальные Хосты

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

Если директивы CustomLog или ErrorLog помещаются в раздел <VirtualHost>, все запросы или ошибки для этого виртуального хоста будут записываться только в указанный файл. Любой виртуальный хост, у которого нет директив журналирования, все равно будет отправлять свои запросы в журналы главного сервера. Этот метод очень полезен для небольшого количества виртуальных хостов, но если количество хостов очень велико, им может быть сложно управлять. Кроме того, это может часто создавать проблемы с недостаточным количеством файловых дескрипторов.

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

LogFormat "%v %l %u %t \"%r\" %>s %b" comonvhost
CustomLog "logs/access_log" comonvhost

%v используется для записи в журнал имени виртуального хоста, который обслуживает запрос. Затем такую программу, как split-logfile, можно использовать для последующей обработки журнала доступа, чтобы разделить его на один файл для каждого виртуального хоста.

Вопросы безопасности

Любой, кто может писать в каталог, где Apache httpd пишет файл журнала, почти наверняка может получить доступ к uid, с которого запущен сервер, который обычно является пользователем root. НЕ предоставляйте людям доступ для записи в каталог, в котором хранятся журналы, не зная о последствиях.

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

Разрешения на каталоги ServerRoot

В обычной работе Apache запускается пользователем root и переключается на пользователя, определённого в директиве User, для обслуживания обращений. Как и в случае с любой командой, выполняемой пользователем root, вы должны позаботиться о том, чтобы она была защищена от изменения пользователями без полномочий root. Не только сами файлы должны быть доступны для записи только root, но и каталоги, и родители всех каталогов. Например, если вы решите поместить ServerRoot в /usr/local/apache, то рекомендуется создать этот каталог как root с помощью таких команд:

mkdir /usr/local/apache
cd /usr/local/apache
mkdir bin conf logs
chown 0 . bin conf logs
chgrp 0 . bin conf logs
chmod 755 . bin conf logs

Предполагается, что /, /usr и /usr/local могут быть изменены только пользователем root. При установке исполняемого файла httpd вы должны убедиться, что он защищён аналогичным образом:

cp httpd /usr/local/apache/bin
chown 0 /usr/local/apache/bin/httpd
chgrp 0 /usr/local/apache/bin/httpd
chmod 511 /usr/local/apache/bin/httpd

Вы можете создать подкаталог htdocs, который может изменяться другими пользователями — поскольку root никогда не выполняет никаких файлов оттуда и не должен создавать файлы там.

Если вы позволяете пользователям без полномочий root изменять любые файлы, которые root выполняет или выполняет запись, то вы открываете свою систему для компрометации root. Например, кто-то может заменить двоичный файл httpd, чтобы при следующем запуске он выполнял произвольный код. Если каталог журналов доступен для записи (пользователем без полномочий root), кто-то может заменить файл журнала символической ссылкой на какой-либо другой системный файл, а затем root может перезаписать этот файл произвольными данными. Если сами файлы журнала доступны для записи (пользователем без полномочий root), то кто-то может перезаписать сам журнал поддельными данными.


Рекомендуется Вам:

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *