基于nginx的waf方案naxsi源码理解(8)_检测处理结果处理

检测结果处理的入口

模块处理函数ngx_http_naxsi_access_handler 最后调用的ngx_http_output_forbidden_page函数即是对检测结果处理的入口函数。

    if (ctx->block || ctx->drop) {
      cf->request_blocked++;
      rc = ngx_http_output_forbidden_page(ctx, r);
      // nothing:      return (NGX_OK);
      // redirect : return (NGX_HTTP_OK);
      return rc;
    } else if (ctx->log) {
      rc = ngx_http_output_forbidden_page(ctx, r);
    }

ngx_http_output_forbidden_page

函数关键点一

  // 会为 ostr 及 tmp_uri 赋值
  if (ngx_http_nx_log(ctx, r, ostr, &tmp_uri) != NGX_HTTP_OK)
    return (NGX_ERROR);

函数关键点二

  // 字符串日志输出
  if (!ctx->json_log) {
    for (i = 0; i < ostr->nelts; i++) {
      ngx_log_error(
        NGX_LOG_ERR, r->connection->log, 0, "NAXSI_FMT: %s", ((ngx_str_t*)ostr->elts)[i].data);
    }
  }
  // json 日志输出 
  else {

函数关键点三

  /*
  ** add headers with original url
  ** and arguments, as well as
  ** the first fragment of log
  */

#define NAXSI_HEADER_ORIG_URL  "x-orig_url"
#define NAXSI_HEADER_ORIG_ARGS "x-orig_args"
#define NAXSI_HEADER_NAXSI_SIG "x-naxsi_sig"

  // 给请求header添加 key/value键值对
  if (r->headers_in.headers.last) {

    /*
    调用ngx_list_push表示添加新的元素,传入的参数是ngx_list_t链表。
    正常情况下,返回的是新分配的元素首地址。如果返回NULL空指针,则表示添加失败。
    在使用它时通常先调用ngx_list_push得到返回的元素地址,再对返回的地址进行赋值。
    */
    h = ngx_list_push(&(r->headers_in.headers));    // 头部链表 key value
    if (!h)
      return (NGX_ERROR);
    h->key.len  = strlen(NAXSI_HEADER_ORIG_URL);
    h->key.data = ngx_pcalloc(r->pool, strlen(NAXSI_HEADER_ORIG_URL) + 1);
    if (!h->key.data)
      return (NGX_ERROR);
    memcpy(h->key.data, NAXSI_HEADER_ORIG_URL, strlen(NAXSI_HEADER_ORIG_URL));
    h->lowcase_key = ngx_pcalloc(r->pool, strlen(NAXSI_HEADER_ORIG_URL) + 1);
    memcpy(h->lowcase_key, NAXSI_HEADER_ORIG_URL, strlen(NAXSI_HEADER_ORIG_URL));
    h->value.len  = tmp_uri->len;
    h->value.data = ngx_pcalloc(r->pool, tmp_uri->len + 1);
    memcpy(h->value.data, tmp_uri->data, tmp_uri->len);

    h = ngx_list_push(&(r->headers_in.headers));
    if (!h)
      return (NGX_ERROR);
    h->key.len  = strlen(NAXSI_HEADER_ORIG_ARGS);
    h->key.data = ngx_pcalloc(r->pool, strlen(NAXSI_HEADER_ORIG_ARGS) + 1);
    if (!h->key.data)
      return (NGX_ERROR);
    memcpy(h->key.data, NAXSI_HEADER_ORIG_ARGS, strlen(NAXSI_HEADER_ORIG_ARGS));
    h->lowcase_key = ngx_pcalloc(r->pool, strlen(NAXSI_HEADER_ORIG_ARGS) + 1);
    memcpy(h->lowcase_key, NAXSI_HEADER_ORIG_ARGS, strlen(NAXSI_HEADER_ORIG_ARGS));
    h->value.len  = r->args.len;
    h->value.data = ngx_pcalloc(r->pool, r->args.len + 1);
    memcpy(h->value.data, r->args.data, r->args.len);

    h = ngx_list_push(&(r->headers_in.headers));
    if (!h)
      return (NGX_ERROR);
    h->key.len  = strlen(NAXSI_HEADER_NAXSI_SIG);
    h->key.data = ngx_pcalloc(r->pool, strlen(NAXSI_HEADER_NAXSI_SIG) + 1);
    if (!h->key.data)
      return (NGX_ERROR);
    memcpy(h->key.data, NAXSI_HEADER_NAXSI_SIG, strlen(NAXSI_HEADER_NAXSI_SIG));
    h->lowcase_key = ngx_pcalloc(r->pool, strlen(NAXSI_HEADER_NAXSI_SIG) + 1);
    memcpy(h->lowcase_key, NAXSI_HEADER_NAXSI_SIG, strlen(NAXSI_HEADER_NAXSI_SIG));
    h->value.len  = denied_args.len;
    h->value.data = denied_args.data;
  }

函数关键点四

  if (ctx->learning && !ctx->drop) {
    if (ctx->post_action) {
      ngx_http_core_loc_conf_t* clcf;
      clcf                   = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
      clcf->post_action.data = cf->denied_url->data;
      clcf->post_action.len  = cf->denied_url->len;
    }
    return (NGX_DECLINED);
  } else {
    ngx_http_internal_redirect(r, cf->denied_url, &empty);   // 将请求重定向到一个新的location
    return (NGX_HTTP_OK);
  }

相关知识点

nginx 的相关宏定义及对应处理

#define  NGX_OK          0   // 表示该阶段已经处理完成,需要转入下一个阶段
#define  NGX_ERROR      -1   // 表示发生了错误,需要结束该请求。
#define  NGX_AGAIN      -2   // 表示需要等待某个事件发生才能继续处理(比如等待网络IO),此时Nginx为了不阻塞其他请求的处理,必须中断当前请求的执行链,等待事件发生之后继续执行该handler
#define  NGX_BUSY       -3
#define  NGX_DONE       -4   // 表示需要等待某个事件发生才能继续处理(比如等待网络IO),此时Nginx为了不阻塞其他请求的处理,必须中断当前请求的执行链,等待事件发生之后继续执行该handler
#define  NGX_DECLINED   -5   // 表示需要转入本阶段的下一个handler继续处理
#define  NGX_ABORT      -6

ngx_escape_uri函数

uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type);
对src进行编码,根据type来按不同的方式进行编码,如果dst为NULL,则返回需要转义的字符的数量,由此可得到需要的空间大小。type的类型可以是:

#define NGX_ESCAPE_URI            0
#define NGX_ESCAPE_ARGS           1
#define NGX_ESCAPE_URI_COMPONENT  2
#define NGX_ESCAPE_HTML           3
#define NGX_ESCAPE_REFRESH        4
#define NGX_ESCAPE_MEMCACHED      5
#define NGX_ESCAPE_MAIL_AUTH      6

你可能感兴趣的:(#,naxsi,nginx,naxsi,web应用防火墙,waf,api安全)