即使已经有一个公认的答案,该解决方案似乎也无效。
nginx 有log_format指令,它的上下文是 http。这意味着,log_format 只能(有效)在配置文件的 http {} 部分中设置,而不是在服务器部分中!
另一方面,我们有一个if指令,它有一个server 和 location 的上下文。
所以我们不能在服务器部分中使用“if”和“log_format”(这是在公认的解决方案中完成的)
所以if在这里没有帮助,如果是邪恶的(http://wiki.nginx.org/IfIsEvil)!我们需要在http 上下文中工作的东西,因为只有在那里才能以有效的方式定义 log_format,这是服务器上下文之外唯一定义我们的虚拟主机的地方……</p>
幸运的是,nginx中有一个地图功能!map 将一些值重新映射为新值(可在可用于 log_format 指令的变量中访问)。好消息:这也适用于正则表达式。
因此,让我们将 IPv4 和 IPv6 地址映射到匿名地址。这必须分 3 步完成,因为 map 不能累积返回值,它只能返回字符串或变量,而不是两者的组合。
因此,首先我们在日志文件中获取我们想要拥有的 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。如果您使用“匿名”日志格式(这是 access_log 指令的格式参数),您的日志文件现在应该包含匿名 IP 地址。