内容简介:这是nginScript系列文章的第四篇,将介绍如何使用nginScript掩蔽用户隐私数据。查看第一篇“nginScript简介”,第二篇“2016年10月,欧洲联盟法院不过,保护日志里的隐私数据并不是EU独有的问题。对于像
这是nginScript系列文章的第四篇,将介绍如何使用nginScript掩蔽用户隐私数据。查看第一篇“nginScript简介”,第二篇“ 使用nginScript将客户端重定向到新服务器 ”,查看第三篇“ 通过TCP负载均衡和Galera集群来扩展MySQL ”。
2016年10月,欧洲联盟法院 规定 将IP地址归为“个人信息”,于是IP地址进入了 数据保护指令 和 一般性数据保护条例 的保护范围。对于很多网站来说,这意味着如果数据离开了欧盟管辖的地区,那么对这些数据进行归档和分析就面临着法规上的挑战。对于进入美国的数据, 西欧隐私盾协议 提供了一定程度的保护,但仍然面临 私权组织 和 政府 的法律质疑。
不过,保护日志里的隐私数据并不是EU独有的问题。对于像 IOS/ICE 27001 这样的安全认证组织,将数据移出安全区域也会破坏认证的合规性。
在这篇文章里,我们介绍一些简单的方案用于处理NGINX Plus和NGINX的日志文件,这样它们就可以安全地导出到外部,不会暴露所谓的个人识别信息(Personal Identification Information)。
无效的方式
保护数据最简单的办法是在导出数据之前把IP地址信息剔除掉。通过标准的 Linux 命令行 工具 就能做到这点,不过日志分析系统希望日志文件具有标准的格式,缺少IP字段会导致无法导入日志。即使日志成功导入,如果分析系统依赖IP地址来追踪用户行为,那么分析结果的准确性就会大打折扣。
另外一种可能的办法是,使用随机的假IP地址替换原来的值,这样就可以保持完整的日志文件,但是这样仍然会影响日志分析结果的质量,因为IP地址是假的。
掩蔽客户端IP地址
最好的解决方案是使用一种叫作数据掩蔽的技术对真实的IP地址进行转换,既不会暴露用户身份信息,又能够用于分析用户网站活动行为。数据掩蔽算法为给定值生成不可逆的伪随机值,同一个IP地址总是能被转换成同样的伪随机值。
你可以在NGINX和NGINX Plus中使用 nginScript模块 来实现IP地址掩蔽。nginScript是为NGINX和NGINX Plus专门实现的JavaScript,专门为服务器端的使用场景而设计。在记录请求消息时,我们通过执行一小段JavaScript代码来掩蔽客户端的IP地址。
为掩蔽IP地址配置NGINX和NGINX Plus
log_format指令指定了哪些信息会显示在访问日志里。NGINX和NGINX Plus提供了默认的日志格式,叫作 combined ,用它生成的日志可以被大多数日志处理工具处理。
我们创建一个新的日志格式 masked ,除了第一个字段与 combined 不一样,其他的都一样,我们使用$remote_addr_masked代替$remote_addr。我们的JavaScript代码会计算这个变量,为每一个客户端IP地址生成一个掩蔽值。
log_format masked '$remote_addr_masked - $remote_user [$time_local]' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"';
为了让NGINX和NGINX Plus以这种格式生成访问日志,我们在server配置块里使用access_log指令指定了 masked 格式。
js_include mask_ip_uri.js; js_set $remote_addr_masked maskRemoteAddress; server { listen 80; access_log /var/log/nginx/access.log; access_log /var/log/nginx/access_masked.log masked; location / { return 200 "$remote_addr -> $remote_addr_masked\n"; #只用于测试 } }
因为我们打算使用nginScript掩蔽客户端IP地址,所以我们使用js_include指令指定JavaScript代码的位置。js_set指令指定了一个JavaScript函数,这个函数会在计算$remote_addr_masked变量时被调用。
我们使用了两个access_log指令。第一个使用了默认的日志格式,它生成的访问日志是给管理员使用的,用于日常的运维。第二个指定了 masked 格式。于是,我们为每个请求生成两个访问日志——一个用于系统管理和运维,一个用于导出。
最后,location配置块使用return指令定义了一个非常简单的返回结果,表示数据掩蔽功能是有效的。在生产环境,这里一般会包含一个proxy_pass指令,将请求重定向到后端的服务器上。
用于IP地址掩蔽的nginScript代码
我们使用了三个简单的JavaScript函数来生成掩蔽过的IP地址。被依赖的函数要出现在前面,所以我们按照它们的先后顺序逐个说明。
数据掩蔽的本质在于使用一种单向的散列算法来转换客户端IP地址。在我们的例子里,我们使用 FNV-1a散列算法 ,这种算法紧凑、快速,而且具有很好的 分布特征 。它返回32位的整数(与IPv4地址一样的大小),非常适合用于表示IP地址。fnv32a函数实现了FNV-1a算法。
i2ipv4函数将32位整数转换成IPv4格式。它接收由fnv32a()生成的散列值,并将其转换成适当的格式。IPv4地址和IPv6地址都用IP4v的格式来表示。
最后,我们使用js_set指令指定了maskRemoteAddress()函数,它接受一个单独的参数req,req表示HTTP请求对象。req的remoteAddress属性包含了客户端IP地址。
function fnv32a(str) { var hval = 2166136261; for (var i = 0; i < str.length; ++i ) { hval ^= str.charCodeAt(i); hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); } return hval >>> 0; } function i2ipv4(i) { var octet1 = (i >> 24) & 255; var octet2 = (i >> 16) & 255; var octet3 = (i >> 8) & 255; var octet4 = i & 255; return octet1 + "." + octet2 + "." + octet3 + "." + octet4; } function maskRemoteAddress(req) { return i2ipv4(fnv32a(req.remoteAddress)); }
IP地址掩蔽
做好配置之后,我们向服务器发出一个简单的请求,然后检查返回的响应并查看访问日志。
$ curl http://localhost/ 127.0.0.1 -> 8.163.209.30 $ sudo tail --lines=1 /var/log/nginx/access*.log ==> /var/log/nginx/access.log <== 127.0.0.1 - - [16/Mar/2017:19:08:19 +0000] "GET / HTTP/1.1" 200 26 "-" "curl/7.47.0" ==> /var/log/nginx/access_masked.log <== 8.163.209.30 - - [16/Mar/2017:19:08:19 +0000] "GET / HTTP/1.1" 200 26 "-" "curl/7.47.0"
掩蔽查询字符串里的敏感数据
日志文件里也可能包含除IP地址之外的敏感数据。比如邮件地址、邮政编码,或者其他通过查询字符串传递过来的信息。如果你的应用是通过这种方式传递数据的,那么你可以通过扩展之前的IP地址掩蔽方案来处理查询字符串里的敏感数据。
为掩蔽查询字符串配置NGINX和NGINX Plus
与默认的 combined 格式类似,之前定义的 masked 日志格式记录了$request变量,通过这个变量可以捕捉到三个request组件:HTTP方法、URI(包含了查询字符串)和HTTP版本。我们只需要掩蔽查询字符串,但是为了代码的可读性,我们分别使用了三个独立的变量来表示这三个组件:$request_uri_masked变量表示请求URI,$request_method表示HTTP方法,$server_protocol表示HTTP版本。
log_format masked '$remote_addr_masked - $remote_user [$time_local]' '"$request_method $request_uri_masked $server_protocol" ' '$status $body_bytes_sent "$http_referer" "$http_user_agent"';
server配置块需要另一个js_set指令,用于定义如何计算$request_url_masked变量。
js_include mask_ip_uri.js; js_set $request_uri_masked maskRequestURI; server { listen 80; access_log /var/log/nginx/access.log; access_log /var/log/nginx/access_masked.log masked; location / { return 200 "$remote_addr -> $remote_addr_masked\n"; # 只用于测试 } }
掩蔽查询字符串的nginScript代码
我们在logmask.js文件里增加了maskRequestURI()函数。与maskRemoteAddress()函数类似,maskRequestURI()也需要调用fnv32a()散列函数,所以它出现在fnv32a()函数的下面。
function maskRequestURI(req) { var query_string = req.variables.query_string; if (query_string.length) { // 如果有查询字符串就继续 var kvpairs = query_string.split('&'); // 转换成键值数组 for (var i = 0; i < kvpairs.length; i++) { // 遍历键值 var kvpair = kvpairs[i].split('='); // 将键值对拆分成一个数组 if (kvpair[0] == "zip") { // 掩蔽邮政编码 // 使用前5个数字作为掩蔽值 kvpairs[i] = kvpair[0] + "=" + fnv32a(kvpair[1]).toString().substr(5); } else if (kvpair[0] == "email") { // Mask email // 使用散列值作为前缀 kvpairs[i] = kvpair[0] + "=" + fnv32a(kvpair[1]) + "@example.com"; } } return req.uri + "?" + kvpairs.join('&'); // 构建掩蔽过的URI } return req.uri; // 没有查询字符串,返回URI }
maskRequestURI()函数遍历查询字符串里的每一个键值对,找出包含敏感数据的键,并掩蔽这些键所对应的值。
根据使用日志的不同情况,掩蔽过的值需要能够反映真实的数据。在上面的例子里,我们将邮政编码掩蔽成5个数字,邮件地址被掩蔽成符合RFC 821的格式。其他键可能要求更复杂的格式,需要使用特定的函数来生成。
查询字符串掩蔽
经过这些额外的配置,我们就可以看到掩蔽过的查询字符串。
$ curl "http://localhost/index.php?foo=bar&zip=90210&email=liam@nginx.com" 127.0.0.1 -> 8.163.209.30 $ sudo tail --lines=1 /var/log/nginx/access*.log ==> /var/log/nginx/access.log <== 127.0.0.1 - - [16/Mar/2017:20:05:55 +0000] "GET /index.php?foo=bar&zip=90210&email=liam@nginx.com HTTP/1.1" 200 26 "-" "curl/7.47.0" ==> /var/log/nginx/access_masked.log <== 8.163.209.30 - - [16/Mar/2017:20:05:55 +0000] "GET /index.php?foo=bar&zip=38643&email=2852675791@example.com HTTP/1.1" 200 26 "-" "curl/7.47.0"
总结
NGINX和NGINX Plus为自定义处理请求提供了一种简单而强大的方案。在这篇文章里,我们演示了如何使用nginScript来掩蔽敏感数据,在不违反数据安全合规的情况下,让日志文件可以被导出并用于离线分析。
以上所述就是小编给大家介绍的《nginScript系列:使用nginScript掩蔽用户隐私数据》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 隐私保护新突破:高斯差分隐私框架与深度学习结合
- Android 隐私安全更新一览
- 日志中的用户隐私安全
- 日志中的用户隐私安全
- 【PPT分享】德国信息技术安全、隐私及责任中心张阳博士——现代隐私权:“社交网络与机器学习模式”案例研究
- [译] 聚焦 Android 11 : 隐私和安全
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Linux内核完全注释
赵炯 / 机械工业出版社 / 2005-8 / 42.00元
Linux内核完全注释,ISBN:9787111149682,作者:赵炯编著一起来看看 《Linux内核完全注释》 这本书的介绍吧!
JS 压缩/解压工具
在线压缩/解压 JS 代码
html转js在线工具
html转js在线工具