Nginx的filter开发,功能:依据客户端地址放行或阻断请求

温柔魔君 发布于 2014/12/04 10:03
阅读 674
收藏 0


功能:依据客户端地址,放行或阻断请求。

语法:web_acl_rule allow | deny ip;
例如:web_acl_rule deny all;       阻断所有ip的请求
自我分析:现在问题在于,指令处理函数ngx_http_acl_rule_filter的参数ngx_conf_t *cf,无法得到配置文件中指令项的参数,利用ngx_log_error输出是空,是什么原因导致的cf为空?
        
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>


typedef struct {
    ngx_uint_t      deny;
    in_addr_t       mask;
    in_addr_t       addr;
    ngx_str_t       host;
    ngx_str_t       method;
    ngx_str_t       uri;
}ngx_http_acl_rule_t;


typedef struct {
    ngx_array_t     *rules;
}ngx_http_acl_loc_conf_t;


static ngx_int_t ngx_http_acl_header_filter(ngx_http_request_t *r);
static char *ngx_http_acl_rule_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static void *ngx_http_acl_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_acl_merge_loc_conf(ngx_conf_t *cf, void *parent, void* child);
static ngx_int_t ngx_http_acl_filter_init(ngx_conf_t *cf);


static ngx_command_t ngx_http_acl_filter_commands[] = {
    { ngx_string ("web_acl_rule"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
                        |NGX_CONF_TAKE1234,
      ngx_http_acl_rule_filter,
      NGX_HTTP_LOC_CONF_OFFSET,
      0,
      NULL },


    ngx_null_command
};


static ngx_http_module_t ngx_http_acl_filter_module_ctx = {
    NULL,                               /* preconfiguration */
    ngx_http_acl_filter_init,           /* postconfiguration */


    NULL,                               /* create main configuration */
    NULL,                               /* init main configuration */


    NULL,                               /* create server configuration */
    NULL,                               /* merge server configuration */


    ngx_http_acl_create_loc_conf,       /* create location configuration */
    ngx_http_acl_merge_loc_conf         /* merge location configuration */
};




  
ngx_module_t ngx_http_acl_filter_module = {


    NGX_MODULE_V1,
    &ngx_http_acl_filter_module_ctx,    /* module context */
    ngx_http_acl_filter_commands,       /* module directives */


    NGX_HTTP_MODULE,                    /* module type */
    NULL,                               /* init master */


    NULL,                               /* init module */
    NULL,                               /* init process */


    NULL,                               /* init thread */
    NULL,                               /* exit thread */


    NULL,                               /* exit process */
    NULL,                               /* exit master */


    NGX_MODULE_V1_PADDING


};




static ngx_http_output_header_filter_pt ngx_http_next_header_filter;




static ngx_int_t
ngx_http_acl_header_filter(ngx_http_request_t *r)
{
    ngx_uint_t                      i;
    struct sockaddr_in           *sin;
    ngx_http_acl_loc_conf_t     *alcf;
    ngx_http_acl_rule_t         *rule;


    ngx_log_error (NGX_LOG_ALERT, r->connection->log, 0, "qijian - ngx_http_acl_header_filter\n");


    alcf = ngx_http_get_module_loc_conf(r, ngx_http_acl_filter_module);


    if (r->connection->sockaddr->sa_family == AF_INET) {


        if (alcf->rules) {


            sin = (struct sockaddr_in *) r->connection->sockaddr;
            rule = alcf->rules->elts;


            for(i = 0; i < alcf->rules->nelts; i++) {


                ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                                "acl: %08XD %08XD %08XD",
                                sin->sin_addr.s_addr, rule[i].mask, rule[i].addr);


                if ((sin->sin_addr.s_addr & rule[i].mask) == rule[i].addr) {


                    if (rule[i].deny) {


                        return NGX_HTTP_FORBIDDEN;


                    }


                }


            }


        }


    }


    return ngx_http_next_header_filter(r);
}


static char *
ngx_http_acl_rule_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_acl_loc_conf_t *alcf = conf;


    ngx_int_t               rc;
    ngx_uint_t             all;
    ngx_str_t           *value;
    ngx_cidr_t            cidr;
    ngx_http_acl_rule_t  *rule;


    ngx_log_error (NGX_LOG_ALERT, cf->log, 0, "qijian - ngx_http_acl_rule_filter\n");


    ngx_memzero(&cidr, sizeof(ngx_cidr_t));


    value = cf->args->elts;


    all = (value[2].len == 3 && ngx_strcmp(value[2].data, "all") == 0);


    if (!all) {


        rc = ngx_ptocidr(&value[2], &cidr);


        if (rc == NGX_ERROR) {


            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                    "invalid parameter \"%V\"", &value[2]);


            return NGX_CONF_ERROR;
        }


        if (rc == NGX_DONE) {


            ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                    "low address bits of %V are meaningless", &value[2]);
        }


    if (alcf->rules == NULL) {


        alcf->rules = ngx_array_create(cf->pool, 4, sizeof(ngx_http_acl_rule_t));


        if (alcf->rules == NULL) {


            return NGX_CONF_ERROR;
        }
    }


    rule = ngx_array_push(alcf->rules);


    if (rule == NULL) {


        return NGX_CONF_ERROR;
    }


    rule->mask = cidr.u.in.mask;
    rule->addr = cidr.u.in.addr;
    rule->deny = (value[1].data[1] == 'd') ? 1 : 0;


    return NGX_CONF_OK;
}


static void *
ngx_http_acl_create_loc_conf (ngx_conf_t *cf)


{
    ngx_http_acl_loc_conf_t *alcf;


    ngx_log_error (NGX_LOG_ALERT, cf->log, 0, "qijian - ngx_http_create_loc_conf\n");


    alcf = (ngx_http_acl_loc_conf_t *)ngx_pcalloc(cf->pool, sizeof(ngx_http_acl_loc_conf_t));


    if (alcf == NULL) {


        return NULL;
    }


    return alcf;
}




static char*
ngx_http_acl_merge_loc_conf(ngx_conf_t *cf, void *parent, void* child)
{
    ngx_log_error (NGX_LOG_ALERT, cf->log, 0, "qijian - ngx_http_acl_merge_loc_conf\n");


    ngx_http_acl_loc_conf_t *prev = (ngx_http_acl_loc_conf_t *)parent;


    ngx_http_acl_loc_conf_t *conf = (ngx_http_acl_loc_conf_t *)child;


    if (conf->rules == NULL) {


        conf->rules = prev->rules;
    }


    return NGX_CONF_OK;
}


static ngx_int_t
ngx_http_acl_filter_init(ngx_conf_t *cf)
{
    ngx_http_next_header_filter = ngx_http_top_header_filter;


    ngx_http_top_header_filter = ngx_http_acl_header_filter;


    ngx_log_error (NGX_LOG_ALERT, cf->log, 0, "qijian - ngx_http_acl_filter_init\n");


    return NGX_OK;
}

















加载中
0
温柔魔君
温柔魔君
晕,怎么删除这条帖子。。。
返回顶部
顶部