Анонимный IP-журнал в nginx?

Чтобы уважать конфиденциальность моих пользователей, я пытаюсь анонимизировать их IP-адреса в файлах журнала nginx.

Одним из способов сделать это будет определение пользовательского формата журнала, например:

log_format noip '127.0.0.1 - [$time_local]  '
    '"$request" $status $body_bytes_sent '
    '"$http_referer" "$http_user_agent" $request_time';

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

Лучше всего было бы "сократить" ip-адрес (87.12.23.55 станет 87.12.23.1).

Есть ли возможность достичь этого с помощью скриптов конфигурации nginx?

Спасибо.

Ответ 1

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

nginx имеет директиву log_format, которая имеет контекст http. Это означает, что log_format может быть только (действительным), установленным в разделе http {} конфигурационного файла, а не в пределах разделов сервера!

С другой стороны, мы имеем директиву if, которая имеет контекст сервера и местоположения.

Поэтому мы не можем использовать "if" и "log_format" в разделе сервера (что делается в рамках принятого решения)

Так что , если здесь не полезно, также if is evil (http://wiki.nginx.org/IfIsEvil)! Нам нужно что-то, что работает в контексте http, потому что только там log_format может быть определен корректно, и это единственное место вне контекста сервера, где определены наши виртуальные хосты...

К счастью, в nginx есть функция map! map переназначает некоторые значения в новые значения (доступные в переменных, которые могут использоваться в директиве log_format). И хорошее сообщение: Это также работает с регулярными выражениями.

Так что давайте сопоставим наши адреса IPv4 и IPv6 с анонимными адресами. Это нужно сделать в 3 этапа, так как карта не может скопировать возвращаемые значения, она может возвращать только строки или переменные, а не комбинацию обоих.

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

Вот правила, которые входят в контекст http {}:

map $remote_addr $ip_anonym1 {
 default 0.0.0;
 "~(?P<ip>(\d+)\.(\d+)\.(\d+))\.\d+" $ip;
 "~(?P<ip>[^:]+:[^:]+):" $ip;
}

map $remote_addr $ip_anonym2 {
 default .0;
 "~(?P<ip>(\d+)\.(\d+)\.(\d+))\.\d+" .0;
 "~(?P<ip>[^:]+:[^:]+):" ::;
}

map $ip_anonym1$ip_anonym2 $ip_anonymized {
 default 0.0.0.0;
 "~(?P<ip>.*)" $ip;
}

log_format anonymized '$ip_anonymized - $remote_user [$time_local] ' 
   '"$request" $status $body_bytes_sent ' 
   '"$http_referer" "$http_user_agent"';

access_log /var/log/nginx/access.log anonymized;

После добавления этого файла в файл конфигурации nginx.conf не забудьте перезагрузить nginx. Теперь ваши файлы журналов должны содержать анонимные IP-адреса, если вы используете формат анонимного журнала (это параметр формата директивы access_log).

Ответ 2

Принятый ответ кажется немного раздутым. Текущая версия nginx позволяет сделать это следующим образом:

map $remote_addr $remote_addr_anon {
    ~(?P<ip>\d+\.\d+\.\d+)\.    $ip.0;
    ~(?P<ip>[^:]+:[^:]+):       $ip::;
    default                     0.0.0.0;
}

Ответ 3

Вы можете использовать оператор if с регулярными выражениями внутри блока сервера для анонимных IP-адресов без каких-либо дополнительных модулей perl или lua.

внутри nginx.conf

server {   
    if ($remote_addr ~ (\d+).(\d+).(\d+).(\d+)) {
      set $ip_anym $1.$2.0.1;
    } 
    log_format  main  '[$time_local] $ip_anym "$request" $status $body_bytes_sent $request_time "$http_referer" "$http_user_agent"';    

    access_log  /var/log/access.log  main;
    ....
}

Мы анонизируем ip и назначаем его новой переменной с именем $ip_anym, которую затем мы можем использовать внутри формата журнала вместо исходного $remote_addr. В приведенном выше примере мы сохраняем первую и вторую часть IP-адреса, вы также можете использовать $1. $2. $3.1, если вы предпочитаете заменять последнюю часть ip.

Ответ 4

Я думаю, что хорошим и практичным решением является анонимность IP-кода перед вращением файлов журнала (что вы должны делать ежедневно). Есть много сценариев для этой задачи, доступных для Apache, и поскольку формат журнала по крайней мере очень похож, они должны работать из коробки или легко настраиваться. Разумеется, вы по-прежнему сохраняете полный IP-адрес в течение 24 часов или менее, но это лучше, чем укладывать их на долгие годы.