Skip to content

Commit e695492

Browse files
committed
Add variables to hold processing times for modsecurity phases
1 parent 2497e6a commit e695492

6 files changed

+171
-3
lines changed

src/ngx_http_modsecurity_body_filter.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
156156

157157
if (is_request_processed) {
158158
ngx_pool_t *old_pool;
159+
struct timeval start_tv;
160+
ngx_gettimeofday(&start_tv);
159161

160162
old_pool = ngx_http_modsecurity_pcre_malloc_init(r->pool);
161163
msc_process_response_body(ctx->modsec_transaction);
@@ -164,6 +166,7 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
164166
/* XXX: I don't get how body from modsec being transferred to nginx's buffer. If so - after adjusting of nginx's
165167
XXX: body we can proceed to adjust body size (content-length). see xslt_body_filter() for example */
166168
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0);
169+
ctx->resp_body_phase_time = ngx_http_modsecurity_compute_processing_time(start_tv);
167170
if (ret > 0) {
168171
return ret;
169172
}

src/ngx_http_modsecurity_common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ typedef struct {
9999
unsigned processed:1;
100100
unsigned logged:1;
101101
unsigned intervention_triggered:1;
102+
ngx_msec_int_t req_headers_phase_time;
103+
ngx_msec_int_t req_body_phase_time;
104+
ngx_msec_int_t resp_headers_phase_time;
105+
ngx_msec_int_t resp_body_phase_time;
102106
} ngx_http_modsecurity_ctx_t;
103107

104108

@@ -164,5 +168,6 @@ ngx_int_t ngx_http_modsecurity_pre_access_handler(ngx_http_request_t *r);
164168
/* ngx_http_modsecurity_rewrite.c */
165169
ngx_int_t ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r);
166170

171+
ngx_msec_int_t ngx_http_modsecurity_compute_processing_time(struct timeval tv);
167172

168173
#endif /* _NGX_HTTP_MODSECURITY_COMMON_H_INCLUDED_ */

src/ngx_http_modsecurity_header_filter.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,9 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r)
446446
return ngx_http_next_header_filter(r);
447447
}
448448

449+
struct timeval start_tv;
450+
ngx_gettimeofday(&start_tv);
451+
449452
/*
450453
* Lets ask nginx to keep the response body in memory
451454
*
@@ -524,9 +527,12 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r)
524527
#endif
525528

526529
old_pool = ngx_http_modsecurity_pcre_malloc_init(r->pool);
527-
msc_process_response_headers(ctx->modsec_transaction, status, http_response_ver);
530+
msc_process_response_headers(ctx->modsec_transaction, status, http_response_ver);
528531
ngx_http_modsecurity_pcre_malloc_done(old_pool);
529532
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0);
533+
534+
ctx->resp_headers_phase_time = ngx_http_modsecurity_compute_processing_time(start_tv);
535+
530536
if (r->error_page) {
531537
return ngx_http_next_header_filter(r);
532538
}

src/ngx_http_modsecurity_module.c

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,24 @@
2525
#include <ngx_http.h>
2626

2727
static ngx_int_t ngx_http_modsecurity_init(ngx_conf_t *cf);
28+
static ngx_int_t ngx_http_modsecurity_add_variables(ngx_conf_t *cf);
2829
static void *ngx_http_modsecurity_create_main_conf(ngx_conf_t *cf);
2930
static char *ngx_http_modsecurity_init_main_conf(ngx_conf_t *cf, void *conf);
3031
static void *ngx_http_modsecurity_create_conf(ngx_conf_t *cf);
3132
static char *ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child);
3233
static void ngx_http_modsecurity_cleanup_instance(void *data);
3334
static void ngx_http_modsecurity_cleanup_rules(void *data);
3435

36+
static ngx_int_t ngx_http_modsecurity_req_headers_phase_time(ngx_http_request_t *r,
37+
ngx_http_variable_value_t *v, uintptr_t data);
38+
static ngx_int_t ngx_http_modsecurity_req_body_phase_time(ngx_http_request_t *r,
39+
ngx_http_variable_value_t *v, uintptr_t data);
40+
static ngx_int_t ngx_http_modsecurity_resp_headers_phase_time(ngx_http_request_t *r,
41+
ngx_http_variable_value_t *v, uintptr_t data);
42+
static ngx_int_t ngx_http_modsecurity_resp_body_phase_time(ngx_http_request_t *r,
43+
ngx_http_variable_value_t *v, uintptr_t data);
44+
static ngx_int_t ngx_http_modsecurity_time_variable(ngx_http_request_t *r,
45+
ngx_http_variable_value_t *v, uintptr_t data, ngx_msec_int_t usec);
3546

3647
/*
3748
* PCRE malloc/free workaround, based on
@@ -268,6 +279,11 @@ ngx_http_modsecurity_create_ctx(ngx_http_request_t *r)
268279
return NULL;
269280
}
270281

282+
ctx->req_headers_phase_time = -1;
283+
ctx->req_body_phase_time = -1;
284+
ctx->resp_headers_phase_time = -1;
285+
ctx->resp_body_phase_time = -1;
286+
271287
mmcf = ngx_http_get_module_main_conf(r, ngx_http_modsecurity_module);
272288
mcf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity_module);
273289

@@ -490,7 +506,7 @@ static ngx_command_t ngx_http_modsecurity_commands[] = {
490506

491507

492508
static ngx_http_module_t ngx_http_modsecurity_ctx = {
493-
NULL, /* preconfiguration */
509+
ngx_http_modsecurity_add_variables, /* preconfiguration */
494510
ngx_http_modsecurity_init, /* postconfiguration */
495511

496512
ngx_http_modsecurity_create_main_conf, /* create main configuration */
@@ -520,6 +536,27 @@ ngx_module_t ngx_http_modsecurity_module = {
520536
};
521537

522538

539+
static ngx_http_variable_t ngx_http_modsecurity_vars[] = {
540+
{ ngx_string("modsecurity_req_headers_phase_time"), NULL,
541+
ngx_http_modsecurity_req_headers_phase_time, 0,
542+
NGX_HTTP_VAR_NOCACHEABLE, 0 },
543+
544+
{ ngx_string("modsecurity_req_body_phase_time"), NULL,
545+
ngx_http_modsecurity_req_body_phase_time, 0,
546+
NGX_HTTP_VAR_NOCACHEABLE, 0 },
547+
548+
{ ngx_string("modsecurity_resp_headers_phase_time"), NULL,
549+
ngx_http_modsecurity_resp_headers_phase_time, 0,
550+
NGX_HTTP_VAR_NOCACHEABLE, 0 },
551+
552+
{ ngx_string("modsecurity_resp_body_phase_time"), NULL,
553+
ngx_http_modsecurity_resp_body_phase_time, 0,
554+
NGX_HTTP_VAR_NOCACHEABLE, 0 },
555+
556+
ngx_http_null_variable
557+
};
558+
559+
523560
static ngx_int_t
524561
ngx_http_modsecurity_init(ngx_conf_t *cf)
525562
{
@@ -596,6 +633,23 @@ ngx_http_modsecurity_init(ngx_conf_t *cf)
596633
return NGX_OK;
597634
}
598635

636+
static ngx_int_t
637+
ngx_http_modsecurity_add_variables(ngx_conf_t *cf) {
638+
ngx_http_variable_t *var, *v;
639+
640+
for (v = ngx_http_modsecurity_vars; v->name.len; v++) {
641+
var = ngx_http_add_variable(cf, &v->name, v->flags);
642+
if (var == NULL) {
643+
return NGX_ERROR;
644+
}
645+
646+
var->get_handler = v->get_handler;
647+
var->data = v->data;
648+
}
649+
650+
return NGX_OK;
651+
};
652+
599653

600654
static void *
601655
ngx_http_modsecurity_create_main_conf(ngx_conf_t *cf)
@@ -788,4 +842,92 @@ ngx_http_modsecurity_cleanup_rules(void *data)
788842
}
789843

790844

845+
static ngx_int_t
846+
ngx_http_modsecurity_req_headers_phase_time(ngx_http_request_t *r,
847+
ngx_http_variable_value_t *v, uintptr_t data)
848+
{
849+
ngx_http_modsecurity_ctx_t *ctx;
850+
851+
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
852+
if (ctx == NULL) {
853+
return NGX_ERROR;
854+
}
855+
return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_headers_phase_time);
856+
}
857+
858+
859+
static ngx_int_t
860+
ngx_http_modsecurity_req_body_phase_time(ngx_http_request_t *r,
861+
ngx_http_variable_value_t *v, uintptr_t data)
862+
{
863+
ngx_http_modsecurity_ctx_t *ctx;
864+
865+
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
866+
if (ctx == NULL) {
867+
return NGX_ERROR;
868+
}
869+
return ngx_http_modsecurity_time_variable(r, v, data, ctx->req_body_phase_time);
870+
}
871+
872+
873+
static ngx_int_t
874+
ngx_http_modsecurity_resp_headers_phase_time(ngx_http_request_t *r,
875+
ngx_http_variable_value_t *v, uintptr_t data)
876+
{
877+
ngx_http_modsecurity_ctx_t *ctx;
878+
879+
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
880+
if (ctx == NULL) {
881+
return NGX_ERROR;
882+
}
883+
return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_headers_phase_time);
884+
}
885+
886+
887+
static ngx_int_t
888+
ngx_http_modsecurity_resp_body_phase_time(ngx_http_request_t *r,
889+
ngx_http_variable_value_t *v, uintptr_t data)
890+
{
891+
ngx_http_modsecurity_ctx_t *ctx;
892+
893+
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
894+
if (ctx == NULL) {
895+
return NGX_ERROR;
896+
}
897+
return ngx_http_modsecurity_time_variable(r, v, data, ctx->resp_body_phase_time);
898+
}
899+
900+
static ngx_int_t
901+
ngx_http_modsecurity_time_variable(ngx_http_request_t *r,
902+
ngx_http_variable_value_t *v, uintptr_t data, ngx_msec_int_t usec)
903+
{
904+
u_char *p;
905+
906+
p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 7);
907+
if (p == NULL) {
908+
return NGX_ERROR;
909+
}
910+
911+
if(usec == -1) {
912+
v->len = ngx_sprintf(p, "-") - p;
913+
} else {
914+
v->len = ngx_sprintf(p, "%T.%06M", (time_t) usec / 1000000, usec % 1000000) - p;
915+
}
916+
917+
v->valid = 1;
918+
v->no_cacheable = 0;
919+
v->not_found = 0;
920+
v->data = p;
921+
922+
return NGX_OK;
923+
}
924+
925+
926+
ngx_msec_int_t
927+
ngx_http_modsecurity_compute_processing_time(struct timeval tv) {
928+
struct timeval current_tv;
929+
ngx_gettimeofday(&current_tv);
930+
return (ngx_msec_int_t) ((current_tv.tv_sec - tv.tv_sec) * 1000000 + (current_tv.tv_usec - tv.tv_usec));
931+
};
932+
791933
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

src/ngx_http_modsecurity_pre_access.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ ngx_http_modsecurity_pre_access_handler(ngx_http_request_t *r)
140140
int ret = 0;
141141
int already_inspected = 0;
142142

143+
struct timeval start_tv;
144+
ngx_gettimeofday(&start_tv);
145+
143146
dd("request body is ready to be processed");
144147

145148
r->write_event_handler = ngx_http_core_run_phases;
@@ -209,7 +212,11 @@ ngx_http_modsecurity_pre_access_handler(ngx_http_request_t *r)
209212
/* XXX: once more -- is body can be modified ? content-length need to be adjusted ? */
210213

211214
old_pool = ngx_http_modsecurity_pcre_malloc_init(r->pool);
215+
212216
msc_process_request_body(ctx->modsec_transaction);
217+
218+
ctx->req_body_phase_time = ngx_http_modsecurity_compute_processing_time(start_tv);
219+
213220
ngx_http_modsecurity_pcre_malloc_done(old_pool);
214221

215222
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0);

src/ngx_http_modsecurity_rewrite.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r)
5151
if (ctx == NULL)
5252
{
5353
int ret = 0;
54+
struct timeval start_tv;
55+
56+
ngx_gettimeofday(&start_tv);
5457

5558
ngx_connection_t *connection = r->connection;
5659
/**
@@ -206,6 +209,9 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r)
206209
ngx_http_modsecurity_pcre_malloc_done(old_pool);
207210
dd("Processing intervention with the request headers information filled in");
208211
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 1);
212+
213+
ctx->req_headers_phase_time = ngx_http_modsecurity_compute_processing_time(start_tv);
214+
209215
if (r->error_page) {
210216
return NGX_DECLINED;
211217
}
@@ -215,6 +221,5 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r)
215221
}
216222
}
217223

218-
219224
return NGX_DECLINED;
220225
}

0 commit comments

Comments
 (0)