文档章节

Nginx下编写c模块来阻止HTTP代理服务器的访问

mickelfeng
 mickelfeng
发布于 2015/10/12 18:35
字数 801
阅读 304
收藏 11

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://www.linuxboy.net/

共有 人打赏支持
mickelfeng

mickelfeng

粉丝 231
博文 2688
码字总数 572169
作品 0
成都
高级程序员
私信 提问
加载中

评论(1)

ZmmFly
ZmmFly
已收藏
构建高效安全的Nginx Web服务器

摘要:Web服务是在互联网上暴露最多的服务。选择合适的软件搭建Web服务器,让自己的Web服务器支持高并发服务和抵御外部攻击的能力,是提供互联网服务所需要长期面对的问题。本文作者根据自己...

引鸩怼孑
2016/03/08
869
2
Nginx server之Nginx作为反向代理服务器

一:Nginx介绍 1.Nginx简介:nginx [engine x]是一个俄罗斯人编写的HTTP和反向代理服务器,另外它也可以作为邮件代理服务器。 它已经在众多流量很大的俄罗斯网站上使用了很长时间,这些网站包...

fighting-cluber
2014/03/11
0
0
初识nginx helloworld模块

1.nginx模块 首先nginx和apache最大的不同就是nginx的模块 不能够动态添加,需要在编译时,指定要添加的模块路径,与nginx源码一起编译。 nginx模块的处理流程: a.客户端发送http请求道ngi...

独钓渔
2016/12/01
23
0
linux nginx安装与nginx配置详解

1.什么是Nginx Nginx(发音同 engine x)是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev所开...

saulc
07/02
0
0
使用Nginx+Lua进行Web开发

Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。Lua由标准C编写而成,几乎在...

醉人的笑容你有没有
2016/04/17
613
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周二乱弹 —— 其实我在地板也睡不着

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @witt-z :分享歌词: 阴天 在不开灯的房间,当所有思绪都一点一点沉淀。 分享莫文蔚的单曲《阴天》: 《阴天》- 莫文蔚 手机党少年们想听歌,...

小小编辑
21分钟前
20
3
微服务分布式事务实现

https://www.processon.com/view/link/5b2144d7e4b001a14d3d2d30

WALK_MAN
今天
3
0
《大漠烟尘》读书笔记及读后感文章3700字

《大漠烟尘》读书笔记及读后感文章3700字: 在这个浮躁的社会里,你有多久没有好好读完一本书了? 我们总觉得自己和别人不一样,所以当看到别人身上的问题时,很少有“反求诸己”,反思自己。...

原创小博客
今天
4
0
大数据教程(9.5)用MR实现sql中的jion逻辑

上一篇博客讲解了使用jar -jar的方式来运行提交MR程序,以及通过修改YarnRunner的源码来实现MR的windows开发环境提交到集群的方式。本篇博主将分享sql中常见的join操作。 一、需求 订单数据表...

em_aaron
今天
3
0
十万个为什么之什么是resultful规范

起源 越来越多的人开始意识到,网站即软件,而且是一种新型的软件。这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency)、高并发等特点...

尾生
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部