NJS旨在成为NGINX的通用脚本框架。
NJS允许用户用脚本的方式给复杂业务场景下的流量负载添加处理逻辑。
它是扩展NGINX 应用的一把利刃。
编者注:
文本所涉及源码均可通过访问以下github 代码仓库获得。
https://github.com/zongzw-nginx/nginx-njs-usecases
“2016年10月,欧盟法院裁定IP地址为“个人信息”,因此属于数据保护指令和通用数据保护条例(GDPR)的管辖范围。对于许多网站所有者而言,如果数据离开欧盟,这对归档和分析日志文件提出了挑战。对于进入美国的数据,“欧盟-美国隐私保护盾”提供了一些保护,但是面临隐私组织和政府的法律挑战,他们认为保护水平不够。
但是,保护日志文件中的个人数据不仅仅是欧盟的问题。对于具有安全认证(例如ISO / ICE 27001)的组织,将日志文件移动到生成它们的安全领域之外(例如,从网络操作到市场营销),可能会损害证书的范围和合规性。”
(Reference: https://www.nginx.com/blog/data-masking-user-privacy-nginscript/)
在本文中,我们通过一个简单的示例了解用于清理NGINX Plus和NGINX日志文件的简单解决方案,以便可以安全地导出它们,而无需暴露通常称为个人身份信息(PII)的内容。
“保护个人数据的最简单方法是在导出日志之前将IP地址从日志中剥离。 使用标准的Linux命令行工具很容易实现这一点,但是日志分析系统可能期望日志文件采用标准格式,并且无法导入省略IP地址字段的日志。 即使成功导入了日志,如果分析系统依靠IP地址来跟踪站点中的用户,则日志处理的价值可能会大大降低。
另一种可能的方法是用假值或随机值代替实际IP地址,这会使日志文件看起来完整,但是由于每个日志条目似乎都源自不同的随机生成的IP地址,因此日志分析的质量受到了损害。”
(Reference: https://www.nginx.com/blog/data-masking-user-privacy-nginscript/)
“最有效的解决方案是使用一种称为数据屏蔽的技术将实际IP地址转换为一个不能识别最终用户但仍允许特定用户进行网站活动关联的地址。 数据屏蔽算法始终为给定输入值生成相同的伪随机值,以确保不能将其转换回原始输入值。 IP地址的每次出现总是转换为相同的伪随机值。
我们可以使用NJS在NGINX和NGINX Plus中实现IP地址掩码。在这种情况下,我们将执行少量JavaScript代码以在记录每个请求时屏蔽客户端IP地址。”
如图所示,我们看到,上下两份日志实际来自同一次请求访问,但ip不同,真实的IP 127.0.0.1 替换成了8.163.209.30,导出被替换的log文件是安全的,当然这里说的IP地址安全。
在以上截图中,可以看到我们使用js_set 设置了一个新的变量$remote_addr_masked,变量$remote_uri_masked类似。并使用这个变量在自定义的log格式中。新格式的log被写入access_masked.log中。
注释是combined 日志格式的内容,以作对比。
指令 js_set 会触发执行maskRemoteAddress 函数,完成对变量的设置。
这里我们看下maskRemoteAddress函数的实现。
数据屏蔽解决方案的实质是使用单向哈希算法来转换客户端IP地址。 在此示例中,我们使用的是FNV-1a哈希算法,该算法紧凑,快速且具有良好分布特性。它返回一个正的32位整数(与IPv4地址相同的大小),这使其很容易显示为IP地址。 fnv32a函数是FNV-1a算法的JavaScript实现。
i2ipv4函数将32位整数转换为四点符号的IPv4地址。 它从fnv32a()获取散列值,并提供在访问日志中“看起来正确”的表示形式。
IPv6地址和IPv4地址都以IPv4格式表示。
同样,对请求uri中的敏感信息的处理也可以采用单向哈希的方式,具体实现下图所示:
图中我们使用了NJS 对zip 和email两个query参数做了fnv32a 单向哈希操作。使用同样的方式我们可以为更多类型的数据做处理。
总结:
NJS 具有丰富的计算能力, ECMAScript 5.1 规范中的类型在NJS中都得以实现。
“njs is created in compliance with ECMAScript 5.1 (strict mode) with some ECMAScript 6 and later extensions. The compliance is still evolving. ”
另外对于Math集合,目前可以支持的函数有:
ES6: abs, acos, acosh, asin, asinh, atan, atan2, atanh, cbrt, ceil, clz32, cos, cosh, exp, expm1, floor, fround, hypot, imul, log, log10, log1p, log2, max, min, pow, random, round, sign, sin, sinh, sqrt, tan, tanh, trunc
Reference: http://nginx.org/en/docs/njs/compatibility.html