为了尊重用户的隐私,我试图在nginx日志文件中匿名化他们的IP地址。
执行此操作的一种方法是定义自定义日志格式,如下所示:
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配置脚本实现此目的?
感谢。
答案 0 :(得分:32)
即使已经接受了答案,解决方案似乎也无效。
nginx具有 log_format 指令,该指令具有上下文。这意味着,log_format只能在配置文件的http {}部分内(有效)设置,而不能在服务器部分内设置!
另一方面,我们有 if 指令,该指令具有服务器和位置的上下文。
所以我们不能在服务器部分中使用“if”和“log_format”(在已接受的解决方案中完成)
所以 if 在这里没有帮助,如果是邪恶的(http://wiki.nginx.org/IfIsEvil)!我们需要在 http上下文中工作的东西,因为只有log_format才能以有效的方式定义,而这是服务器上下文之外唯一的位置,我们的虚拟主机被定义...
幸运的是,nginx中有一个地图功能! map将一些值重新映射到新值(可在log_format指令中使用的变量中访问)。好消息:这也适用于正则表达式。
因此,让我们将IPv4和IPv6地址映射到匿名地址。这必须分三步完成,因为map不能累积返回的值,它只能返回字符串或变量,而不是两者的组合。
因此,首先我们在日志文件中获取我们想要的IP部分,第二个地图返回表示匿名部分的部分,第3个地图规则将它们再次映射到一起。
以下是进入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指令的格式参数),您的日志文件现在应该包含anoymized IP地址。
答案 1 :(得分:15)
接受的答案似乎有点臃肿。从nginx版本1.11开始,它可以这样做:
map $remote_addr $remote_addr_anon {
~(?P<ip>\d+\.\d+\.\d+)\. $ip.0;
~(?P<ip>[^:]+:[^:]+): $ip::;
default 0.0.0.0;
}
答案 2 :(得分:1)
我认为,一个好的和切实可行的解决方案是在旋转日志文件之前对IP进行匿名化(你应该每天都这样做)。这个任务有许多脚本可用于Apache,并且由于日志格式至少非常相似,所以它们应该开箱即用或者可以轻松调整。当然,您仍然可以将完整的IP存储24小时或更短时间,但这比让它们存放多年更好。
答案 3 :(得分:1)
这是一个基本上执行此操作的nginx模块(在日志中匿名化IP地址):https://github.com/masonicboom/ipscrub。它生成IP地址的哈希值为$ remote_addr_ipscrub。哈希盐经常循环(可配置),因此您可以在不记录用户IP地址的情况下链接请求。