文章目录
1. 动态模块概述
可以加载到NGINX中的模块是用C编写的。NGINX有一个庞大的第三方模块生态系统,从语言解释器到安全解决方案。
您自己创建的模块和其他第三方模块需要在运行时独立编译并动态加载到NGINX中。具体步骤如下:
- 获取匹配的NGINX开源版本
- 获取模块源,并在必要时更改模块的配置文件
- 使用configure命令的--add-dynamic-module参数针对NGINX开源版本构建动态模块
- 将生成的动态模块(.so文件)加载到NGINX中,并像使用内置模块一样使用它
您可以按照以下两个示例所示,通过NGINX构建它们。
2. 示例:一个简单的“ Hello World”模块
本示例使用一个简单的Hello World模块来展示如何更新模块源并将其加载到NGINX Plus中。“ Hello World”模块实现了一个简单的指令(hello_world),该指令以简单的消息响应请求。
2.1 步骤1:获取NGINX开源版本
- 下载相应的NGINX开源软件包nginx.org/download
# wget https://nginx.org/download/nginx-1.17.7.tar.gz
# tar zxf nginx-1.17.7.tar.gz
2.2 步骤2:获取模块源
- 从GitHub获取“ Hello World” NGINX模块的源代码:
# git clone https://github.com/perusio/nginx-hello-world-module.git
- 模块的config shell文件定义了它的构建方式,动态模块的格式与静态构建模块的格式不同。
确认文件nginx-hello-world-module/config包含以下内容:
ngx_addon_name=ngx_http_hello_world_module
if test -n "$ngx_module_link"; then
ngx_module_type=HTTP
ngx_module_name=ngx_http_hello_world_module
ngx_module_srcs="$ngx_addon_dir/ngx_http_hello_world_module.c"
. auto/module
else
HTTP_MODULES="$HTTP_MODULES ngx_http_hello_world_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_world_module.c"
fi
2.3 步骤3:编译动态模块
- 首先通过运行带有--add-dynamic-module参数的configure脚本来编译模块,这将创建NGINX支持的标准构建环境。然后运行make modules以构建模块:
# cd nginx-1.17.7/
# ./configure --add-dynamic-module=../nginx-hello-world-module
...
nginx path prefix: "/usr/local/nginx"
nginx binary file: "/usr/local/nginx/sbin/nginx"
nginx modules path: "/usr/local/nginx/modules"
nginx configuration prefix: "/usr/local/nginx/conf"
nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
nginx pid file: "/usr/local/nginx/logs/nginx.pid"
nginx error log file: "/usr/local/nginx/logs/error.log"
nginx http access log file: "/usr/local/nginx/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
# make modules
- 将模块库(.so文件)复制到 /usr/local/nginx/modules。
# cp objs/ngx_http_hello_world_module.so /usr/local/nginx/modules
2.4 步骤4:加载和使用模块
- 要将模块加载到NGINX,请将load_module指令添加到nginx.conf配置文件的主上下文中(不在http 或 stream上下文中):
load_module modules/ngx_http_hello_world_module.so;
- 在http上下文中,增加一个location块,该location块使用Hello World模块提供的hello_world指令。用户请求到该location块时,返回响应hello world。
server {
listen 80;
location / {
hello_world;
}
}
- 重新加载您的NGINX配置并通过一个简单的请求对其进行测试:
# curl http://localhost
hello world
注意:
- 在本例中,实验前已经将nginx编译安装到/usr/local/nginx目录了,从2.3节configure的结果可以看到,NGINX模块路径为/usr/local/nginx/modules。模块复制之前一定要确认存在/usr/local/nginx/modules文件夹,没有就新建。
- 如果在重新加载配置的过程中出现报错:
# ./nginx -t
nginx: [emerg] module "/usr/local/nginx/modules/ngx_http_hello_world_module.so" is not binary compatible in /usr/local/nginx/conf/nginx.conf:11
nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed
这是因为configure的时候添加--with-compat了,去掉重新编译模块即可。
3. 示例:NAXSI Web应用程序防火墙
NAXSI是一种易于使用的高性能Web应用程序防火墙(WAF),它使用启发式方法和评分系统来识别可疑请求,例如XSS和SQL注入攻击。
NAXSI源已更新为符合config shell文件的新格式,因此为NGINX构建动态模块非常简单,与上面hello world模块的构建过程相同。该过程如下:
$ git clone https://github.com/nbs-system/naxsi.git
$ cd nginx-1.17.7/
$ ./configure --add-dynamic-module=../naxsi/naxsi_src
$ make modules
$ sudo cp objs/ngx_http_naxsi_module.so /usr/local/nginx/modules
通过在nginx.conf文件中添加load_module指令来加载该模块:
load_module modules/ngx_http_naxsi_module.so;
添加虚拟主机便于测试:
# Edit this 'include' directive to point to your naxsi_core.rules file
include /usr/local/src/naxsi/naxsi_config/naxsi_core.rules;
server {
listen 80;
location / {
root /usr/local/nginx/html;
# Enable NAXSI
SecRulesEnabled;
# Define where blocked requests go
DeniedUrl "/50x.html";
# CheckRules, determining when NAXSI needs to take action
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;
# Don’t forget the error_log, where blocked requests are logged
error_log /tmp/naxsi.log;
}
error_page 500 502 503 504 /50x.html;
}
可以通过一对简单的HTTP请求来验证NAXSI的正确操作:
- curl http://localhost/ 返回存储在 /usr/local/nginx/html 中的主页;
- curl "http://localhost/?a=<>"触发NAXSI的XSS检测并阻止请求,从 /usr/local/nginx/html返回标准的50x.html错误页面。它还会将消息记录到error_log。在本例中就是 /tmp/naxsi.log。
# tail -3 /tmp/naxsi.log
2020/01/01 00:31:02 [error] 7566#0: *1 NAXSI_FMT: ip=192.168.198.1&server=192.168.198.133&uri=/&vers=0.56&total_processed=3&total_blocked=1&config=block&cscore0=$XSS&score0=8&zone0=ARGS&id0=1302&var_name0=a, client: 192.168.198.1, server: , request: "GET /?a=%3C%3E HTTP/1.1", host: "192.168.198.133"
2020/01/01 00:32:37 [error] 7566#0: *4 NAXSI_FMT: ip=192.168.198.1&server=192.168.198.133&uri=/&vers=0.56&total_processed=4&total_blocked=2&config=block&cscore0=$XSS&score0=8&zone0=ARGS&id0=1302&var_name0=a, client: 192.168.198.1, server: , request: "GET /?a=%3C%3E HTTP/1.1", host: "192.168.198.133"
2020/01/01 00:39:18 [error] 7566#0: *11 NAXSI_FMT: ip=192.168.198.1&server=192.168.198.133&uri=/&vers=0.56&total_processed=8&total_blocked=3&config=block&cscore0=$XSS&score0=8&zone0=ARGS&id0=1302&var_name0=a, client: 192.168.198.1, server: , request: "GET /?a=%3C%3E HTTP/1.1", host: "192.168.198.133"
参考文档
https://www.nginx.com/blog/compiling-dynamic-modules-nginx-plus