标签:
Nginx下编写c模块来阻止HTTP代理服务器的访问
在这篇使用Apache来阻止http代理服务器的访问文章里,我们使用了Apache的mod_rewrite来判断访客的http head头,如果看到了有代理的迹象,就阻止它,能否进一步提高效率呢?于是想到了用nginx来提高效率,为了最快,编写了C模块,这样效率会达至最高。
 下面简单介绍一下nginx模块的编写:
 nginx模块分两种,handle和filter。handle是得到输入后,直接控制输出最终结果;而filter是得到输入后,进行变换,传递给下一个filter依次处理,两种模块稍有区别。 
我们这里是对Header头进行处理,如果不是代理就放行,如果是代理就阻止,所以应该是用filter。
这篇教程很不错http://www.evanmiller.org/nginx-modules-guide.html,建议大家参看。
关键是要先吃透nginx的数据类型,多使用自带的函数,发现LXR真是一个不错的源代码浏览工具撒:
关键函数部分:
遍历整个Header:
        part = &r->headers_in.headers.part;
        header = part->elts;
        for (i = 0; /* void */ ; i++) {
            if (i >= part->nelts) {
                if (part->next == NULL) {
                    break;
                }
                part = part->next;
                header = part->elts;
                i = 0;
            }
        }
比较Header头:
if (ngx_strncasecmp(header[i].key.data, (u_char *) "via", 3) == 0
||ngx_strncasecmp(header[i].key.data, (u_char *) "forwarded", 7) == 0
||ngx_strncasecmp(header[i].key.data, (u_char *) "useragent_via", 13) == 0
||ngx_strncasecmp(header[i].key.data, (u_char *) "useragent-via", 13) == 0
......
||ngx_strncasecmp(header[i].key.data, (u_char *) "mt_proxy_id", 11) == 0
||ngx_strncasecmp(header[i].key.data, (u_char *)"mt-proxy-id",11)== 0) 
 涉及的nginx相关数据结构:
 ngx_str_t
 ngx_table_elt_t
 ngx_list_part_t
 ngx_http_request_t 
源代码下载:ngx_http_proxyblock_module.c.txt
/*
 * Copyright (C) ZhangRanrui , zhangranrui@gmail.com 
 */
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
static ngx_int_t ngx_http_proxyblock_init(ngx_conf_t *cf);
static ngx_http_module_t  ngx_http_proxyblock_module_ctx = {
    NULL,                                  /* preconfiguration */
    ngx_http_proxyblock_init,     /* postconfiguration */
    NULL,                                  /* create main configuration */
    NULL,                                  /* init main configuration */
    NULL,                                  /* create server configuration */
    NULL,                                  /* merge server configuration */
    NULL,                                  /* create location configuration */
    NULL                                   /* merge location configuration */
};
ngx_module_t  ngx_http_proxyblock_module = {
    NGX_MODULE_V1,
    &ngx_http_proxyblock_module_ctx, /* module context */
    NULL,   /* 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_proxyblock(ngx_http_request_t *r)
{
    ngx_int_t     rc;
    char remote_ip[16] = {0};
    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
        return NGX_HTTP_NOT_ALLOWED;
    }
    rc = ngx_http_discard_request_body(r);
    if (rc != NGX_OK) {
        return rc;
    }
    ngx_list_part_t             *part;
    ngx_table_elt_t             *header;
    ngx_uint_t                   i, hash;
        part = &r->headers_in.headers.part;
        header = part->elts;
        for (i = 0; /* void */ ; i++) {
            if (i >= part->nelts) {
                if (part->next == NULL) {
                    break;
                }
                part = part->next;
                header = part->elts;
                i = 0;
            }
            if (ngx_strncasecmp(header[i].key.data, (u_char *) "via", 3) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "forwarded", 7) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "useragent_via", 13) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "useragent-via", 13) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "x_forwarded_for", 15) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "x-forwarded-for", 15) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "xproxy_connection", 17) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "xproxy-connection", 17) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "proxy_connection", 16) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "proxy-connection", 16) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "http_pc_remote_addr", 19) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "http_pc_remote_addr", 19) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "mt_proxy_id", 11) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "mt-proxy-id", 11) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "http_client_ip", 14) == 0
                || ngx_strncasecmp(header[i].key.data, (u_char *) "http-client-ip", 14) == 0 )
            {
                snprintf(remote_ip, r->connection->addr_text.len, "%s", r->connection->addr_text.data);
                fprintf(stderr, "ip %s was blocked by header (%s:%s)\n", remote_ip, header[i].key.data, header[i].value.data);
                goto found;
            }
        }
    return ngx_http_next_header_filter(r);
found:
    return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
static ngx_int_t
ngx_http_proxyblock_init(ngx_conf_t *cf)
{
    ngx_http_next_header_filter = ngx_http_top_header_filter;
    ngx_http_top_header_filter = ngx_http_proxyblock;
    return NGX_OK;
} 
编译过程:
| 
         1 
        
         2 
        
         3 
        
         4 
        
         5 
        
         6 
        
         7 
        
         8 
        
         9 
        
         10 
        
         11 
        
         12 
        
         13 
        
         14 
        |  
        tar  
        zxvf  
        nginx 
        - 
        0.7.58.tar.gz 
         
        cd  
        nginx 
        - 
        0.7.58 
         
        mkdir  
        mo 
         
        #把ngx_http_proxyblock_module.c放入mo目录 
         
        #在mo目录下建立config文件 
         
        vi  
        mo 
        / 
        config 
         
        ngx_addon_name 
        = 
        ngx_http_proxyblock_module 
         
        HTTP_AUX_FILTER_MODULES 
        = 
        "$HTTP_AUX_FILTER_MODULES ngx_http_proxyblock_module" 
         
        NGX_ADDON_SRCS 
        = 
        "$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_proxyblock_module.c" 
         
        CORE_LIBS 
        = 
        "$CORE_LIBS" 
         
        #编译的时候加参数--add-module 
         
        . 
        / 
        configure 
          
        -- 
        without 
        - 
        pcre 
          
        -- 
        add 
        - 
        module 
        = 
        . 
        / 
        mo 
        | 
标签:
原文地址:http://my.oschina.net/mickelfeng/blog/516000