wenqiang li

Results 130 issues of wenqiang li

### ngx_waf + 编译 ./configure --prefix=/tmp/waf --add-dynamic-module=../ngx-http-waf-module --with-compat --with-cc-opt="-fprofile-arcs -ftest-coverage" --with-ld-opt="-lgcov" + 在nginx目录执行 lcov --directory . --zerocounters + prove . + lcov --directory ./objs/addon/ngx-http-waf-module/ --capture --output-file waf.info --base-directory . +...

### 概述 该模块是个复杂的模块,11个执行阶段其中3个阶段是为该模块设置的。rewrite模块强依赖pcre这个正则表达式库。 该模块提供了个简单的脚本执行引擎,可以在配置文件中写一些简单的脚本语言,该模块也是ngx_http_script.c的对外表现。 脚本引擎分为2个阶段,编译和执行。编译是在ngx启动时解析配置文件就开始的,执行是在请求处理过程中。 ### 代码分析 通过ngx_http_rewrite_create_loc_conf函数分配一个下面的结构体保存配置。 其中,codes是保存脚本编译后的执行回调函数。 也就是说编译阶段是向codes数组中添加执行函数和变量,执行阶段是遍历codes数组调用函数。 ```c typedef struct { ngx_array_t *codes; /* uintptr_t */ ngx_uint_t stack_size; ngx_flag_t log; ngx_flag_t uninitialized_variable_warn; } ngx_http_rewrite_loc_conf_t; ``` 通过ngx_http_rewrite_merge_loc_conf合并配置。其中codes并不会合并。 会用到的结构体:...

nginx

### 概述 去年遇到nginx的一个core问题,跟踪的结果是堆内存写乱了,导致glibc free的时候merge错误。 最终是看了glibc 的代码,跟踪了core信息在对应调用函数打日志解决的。大概的做法是:捕获了SIGABRT信号,输出动态分配的内存和在glibc中紧挨着的下一块内存的内容定位到的问题。 最近,别人碰到了栈空间写乱的情况,觉的挺有意思的,顺便就查了一些资料。 ### 过程调用的栈帧(stack frame)空间 在了解帧栈之前,要先了解一下进程内存空间分布,栈帧是栈上的一部分。 那什么是栈帧呢?为单个过程(函数调用)分配的那部分栈称为栈帧。 栈帧其实是两个指针寄存器之间的栈空间,寄存器%ebp为帧指针,而寄存器%esp为栈指针。%ebp 总是大于 %esp。 一个过程调用包括将数据和控制从代码的一部分传递到另一部分。进入时为过程的局部变量分配空间,并在退出时释放这些空间。 那么除了Valgrind还有没有工具支持检查呢? [sanitizers](https://github.com/google/sanitizers) 是google开源的一个项目,最早是在llvm中支持,gcc4.8以后的版本也支持了。面向c、c++,可以支持以下检查: 1. 使用已释放内存(野指针) 2. 堆内存越界(读写) 3. 栈内存越界(读写) 4. 全局变量越界(读写) 5. 函数返回局部变量 6....

Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。然而,lua的协程和多线程系统中的线程不同,协程只在显式的调用了`yield`函数时才会挂起。同一时间也只有一个协程在运行。 + 协程函数: - coroutine.create(f): 接受一个函数,该函数是协程的主函数,返回一个thread的对象。 - coroutine.resume (co [, val1, ···]):接受一个thread的对象(`coroutine.create`的返回)和多个变量。首次运行时,变量被赋予`coroutine.create`的参数f这个函数,作为入参。如果上次是从`coroutine.yield`返回的,再次被调度是从`coroutine.yield`赋值开始执行,因此入参是被赋值到`coroutine.yield`的赋值开始运行。 - coroutine.yield(...) :接受多个参数,把参数从协程返回并挂起协程。再此调用`coroutine.resume`时,会把该函数的参数赋值到接受`coroutine.yield`的变量,并从挂起处继续执行。 看云风写的这个例子就明白多了: ```lua function foo (a) print("foo", a) return coroutine.yield(2*a) end co = coroutine.create(function (a,b)...

nginx中该模块用来限制请求速度。 例如限制单ip每秒1个请求,超过5个则返回错误码,没超过则降低处理请求的速度。 配置如下: ``` http { limit_req_zone $binary_remote_addr zone=one:10m rate=3r/s; limit_req_zone $host zone=two:10m rate=2r/s; limit_req_zone ${host}_$binary_remote_addr zone=three:10m rate=1r/s; ... server { ... location /search/ { limit_req zone=one burst=5; limit_req zone=two...

nginx

### 概述 Hyperscan是Intel开发的正则表达式匹配库,基于X86平台以PCRE为原型而开发的。以BSD协议开源。通常被用于网络防护上。 代码:https://github.com/intel/hyperscan 例子:https://github.com/intel/hyperscan/blob/develop/examples/simplegrep.c 文档:http://intel.github.io/hyperscan/dev-reference/ 相关介绍:https://www.sdnlab.com/18773.html ### 安装 macOSX: 直接brew install hyperscan ```sh ~ brew list hyperscan /usr/local/Cellar/hyperscan/5.0.0/include/hs/ (4 files) /usr/local/Cellar/hyperscan/5.0.0/lib/libhs.5.0.0.dylib /usr/local/Cellar/hyperscan/5.0.0/lib/libhs_runtime.5.0.0.dylib /usr/local/Cellar/hyperscan/5.0.0/lib/pkgconfig/libhs.pc /usr/local/Cellar/hyperscan/5.0.0/lib/ (6 other files) /usr/local/Cellar/hyperscan/5.0.0/share/doc/ (4...

### 概述 httpd 作为全球部署量最多的web 服务器。 代码模块化使得有大量的第三方功能模块。然而有时候我们自己也需要了解一下httpd的运行机制。了解下httpd的模块开发。 ### 代码分析 #### 代码编译脚本 #### 一些宏定义 + hook函数的定义 ```c // apr_tables.h /** @see apr_array_header_t */ typedef struct apr_array_header_t apr_array_header_t; /** An opaque array type...

### 概述 php 有很多功能都是通过扩展实现的。自己也可以按照php提供的接口实现自己的模块。 也可以通过php-src目录下的ext/ext_skel 生成一个扩展所需要的框架。 ### 扩展接口 #### 生成扩展模块框架 例子: https://github.com/php/php-src/blob/master/ext/zend_test/test.c #### 接口 ```c /******************************* * zend_modules.h */ // 扩展模块结构体定义 // typedef struct _zend_module_entry zend_module_entry; struct _zend_module_entry { unsigned...

### 概述 看了下nginx的模块化设计应该是借鉴了[httpd](https://github.com/apache/httpd)的设计思想。 通过编写一些模块实现了定制化的功能。 ### 模块编写 #### 模块生成 + 生成模版 ```sh # /usr/sbin/apxs -g -n hello_world ``` + 模版文件包含 ``` # tree ./hello_world/ ./hello_world/ ├── Makefile ├── mod_hello_world.c └── modules.mk...

### 概述 最近在搞一个基于nginx的应用防火墙。通过开源的语义分析的库实现一些拦截,新的CVE也可以快速的通过添加规则实现拦截。 检测的点有URL、ARGS 、HEADERS、BODY。检测的方式通过开源库结合自制配置的规则实现。 前面几部分的检测都简单,因为格式是固定的。 BODY的检测就麻烦多了,格式不固定,检测内容多。 ### 思路 1. raw body 字符串过滤。 2. 表单解析 字符串过滤,上传文件过滤 [multipart/form-data 协议](https://www.ietf.org/rfc/rfc1867.txt) 文件上传可以通过[文件头魔数](http://www.cnblogs.com/relucent/p/6412548.html)先做一次检测 例如: ``` // ELF 文件的魔数0x7F454C4602010100 od -tx a.out |head -3 0000000...