Add negation prefix ! to log actions

Now filtering rules can disable log actions too. This is possible thanks
to the newly added precedence field of rules. Log actions of filtering
rules at higher precedence can modify logging now. In other words, more
specific rules can change the log actions of more general rules.
HTTP filtering rules can only disable logging.
pull/48/head
Soner Tari 3 years ago
parent cc7bd4a332
commit 11884271fd

@ -15,7 +15,7 @@
uri (uri[*]|*)|
ip (serveraddr|*)|
*)]
[log ([connect] [master] [cert] [content] [pcap] [mirror]|*)]
[log ([[!]connect] [[!]master] [[!]cert] [[!]content] [[!]pcap] [[!]mirror]|*)]
|*)
- Add -Q test config option.

@ -305,7 +305,7 @@ The syntax of filtering rules is as follows:
uri (uri[*]|*)|
ip (serveraddr|*)|
*)]
[log ([connect] [master] [cert] [content] [pcap] [mirror]|*)]
[log ([[!]connect] [[!]master] [[!]cert] [[!]content] [[!]pcap] [[!]mirror]|*)]
|*)
The definition of which connections the rule action will be applied to is
@ -331,6 +331,8 @@ filtering rules:
- `pcap` enables writing packets to pcap files
- `mirror` enables mirroring packets to mirror interfaces or targets
You can add a negation prefix `!` to a log action to disable that logging.
For example, if the following rules are defined in a structured HTTPS proxyspec,
Split from user soner desc notebook to sni example.com log content
@ -382,8 +384,8 @@ In terms of possible filter actions,
- Dst Host filtering rules can take all of the filter and log actions.
- SSL filtering rules can take all of the filter and log actions.
- HTTP filtering rules take the match and block filter actions, but not the
divert, split, or pass actions. Also, HTTP filtering rules do not take log
actions.
divert, split, or pass actions. Also, HTTP filtering rules can only disable
logging.
Log actions do not configure any loggers. Global loggers for respective log
actions should have been configured for those log actions to have any effect.

@ -979,12 +979,7 @@ errout:
}
int
log_content_close(log_content_ctx_t *ctx, int by_requestor, int log_content, int log_pcap
#ifndef WITHOUT_MIRROR
, int log_mirror
#endif /* !WITHOUT_MIRROR */
)
log_content_close(log_content_ctx_t *ctx, int by_requestor)
{
unsigned long prepflags = PREPFLAG_EOF;
unsigned long ctl;
@ -1001,7 +996,7 @@ log_content_close(log_content_ctx_t *ctx, int by_requestor, int log_content, int
* closing the file. The logger_close() call will actually close the
* log. Some logs prefer to use the close callback for logging the
* close event to the log. */
if (log_content && content_file_log && ctx->file) {
if (content_file_log && ctx->file) {
if (logger_submit(content_file_log, ctx->file,
prepflags, NULL) == -1) {
return -1;
@ -1011,7 +1006,7 @@ log_content_close(log_content_ctx_t *ctx, int by_requestor, int log_content, int
}
ctx->file = NULL;
}
if (log_pcap && content_pcap_log && ctx->pcap) {
if (content_pcap_log && ctx->pcap) {
if (logger_submit(content_pcap_log, ctx->pcap,
prepflags, NULL) == -1) {
return -1;
@ -1022,7 +1017,7 @@ log_content_close(log_content_ctx_t *ctx, int by_requestor, int log_content, int
ctx->pcap = NULL;
}
#ifndef WITHOUT_MIRROR
if (log_mirror && content_mirror_log && ctx->mirror) {
if (content_mirror_log && ctx->mirror) {
if (logger_submit(content_mirror_log, ctx->mirror,
prepflags, NULL) == -1) {
return -1;

@ -160,11 +160,7 @@ int log_content_submit(log_content_ctx_t *, logbuf_t *, int, int, int
, int
#endif /* !WITHOUT_MIRROR */
) NONNULL(1,2) WUNRES;
int log_content_close(log_content_ctx_t *, int, int, int
#ifndef WITHOUT_MIRROR
, int
#endif /* !WITHOUT_MIRROR */
) NONNULL(1) WUNRES;
int log_content_close(log_content_ctx_t *, int) NONNULL(1) WUNRES;
int log_content_split_pathspec(const char *, char **,
char **) NONNULL(1,2,3) WUNRES;

@ -2527,7 +2527,7 @@ filter_rule_parse(opts_t *opts, const char *name, char *value, int line_num)
// uri (uri[*]|*)|
// ip (serveraddr|*)|
// *)]
// [log ([connect] [master] [cert] [content] [pcap] [mirror]|*)]
// [log ([[!]connect] [[!]master] [[!]cert] [[!]content] [[!]pcap] [[!]mirror]|*)]
// |*)
char *argv[sizeof(char *) * MAX_FILTER_RULE_TOKENS];
@ -2688,9 +2688,10 @@ filter_rule_parse(opts_t *opts, const char *name, char *value, int line_num)
rule->precedence++;
i = opts_inc_arg_index(i, argc, argv[i], line_num);
if (equal(argv[i], "connect") || equal(argv[i], "master") || equal(argv[i], "cert") || equal(argv[i], "content") || equal(argv[i], "pcap")
if (equal(argv[i], "connect") || equal(argv[i], "master") || equal(argv[i], "cert") || equal(argv[i], "content") || equal(argv[i], "pcap") ||
equal(argv[i], "!connect") || equal(argv[i], "!master") || equal(argv[i], "!cert") || equal(argv[i], "!content") || equal(argv[i], "!pcap")
#ifndef WITHOUT_MIRROR
|| equal(argv[i], "mirror")
|| equal(argv[i], "mirror") || equal(argv[i], "!mirror")
#endif /* !WITHOUT_MIRROR */
) {
do {
@ -2704,16 +2705,29 @@ filter_rule_parse(opts_t *opts, const char *name, char *value, int line_num)
rule->log_content = 1;
else if (equal(argv[i], "pcap"))
rule->log_pcap = 1;
else if (equal(argv[i], "!connect"))
rule->log_connect = 0;
else if (equal(argv[i], "!master"))
rule->log_master = 0;
else if (equal(argv[i], "!cert"))
rule->log_cert = 0;
else if (equal(argv[i], "!content"))
rule->log_content = 0;
else if (equal(argv[i], "!pcap"))
rule->log_pcap = 0;
#ifndef WITHOUT_MIRROR
else if (equal(argv[i], "mirror"))
rule->log_mirror = 1;
else if (equal(argv[i], "!mirror"))
rule->log_mirror = 0;
#endif /* !WITHOUT_MIRROR */
if (++i == argc)
break;
} while (equal(argv[i], "connect") || equal(argv[i], "master") || equal(argv[i], "cert") || equal(argv[i], "content") || equal(argv[i], "pcap")
} while (equal(argv[i], "connect") || equal(argv[i], "master") || equal(argv[i], "cert") || equal(argv[i], "content") || equal(argv[i], "pcap") ||
equal(argv[i], "!connect") || equal(argv[i], "!master") || equal(argv[i], "!cert") || equal(argv[i], "!content") || equal(argv[i], "!pcap")
#ifndef WITHOUT_MIRROR
|| equal(argv[i], "mirror")
|| equal(argv[i], "mirror") || equal(argv[i], "!mirror")
#endif /* !WITHOUT_MIRROR */
);
@ -2731,6 +2745,10 @@ filter_rule_parse(opts_t *opts, const char *name, char *value, int line_num)
i++;
done_log = 1;
}
else if (equal(argv[i], "!*")) {
i++;
done_log = 1;
}
else {
fprintf(stderr, "Unknown argument in filter rule at '%s' on line %d\n", argv[i], line_num);
exit(EXIT_FAILURE);
@ -2833,29 +2851,32 @@ opts_add_site(filter_site_t *site, filter_rule_t *rule)
prepend = 0;
}
s->all_sites = rule->all_sites;
s->exact = rule->exact;
// Multiple rules can set an action for the same site, hence the bit-wise OR
s->divert |= rule->divert;
s->split |= rule->split;
s->pass |= rule->pass;
s->block |= rule->block;
s->match |= rule->match;
// Multiple log actions can be set for the same site, hence the bit-wise OR
s->log_connect |= rule->log_connect;
s->log_master |= rule->log_master;
s->log_cert |= rule->log_cert;
s->log_content |= rule->log_content;
s->log_pcap |= rule->log_pcap;
// Do not override the specs of site rules at higher precedence
// precedence can only go up not down
if (rule->precedence >= s->precedence) {
s->all_sites = rule->all_sites;
s->exact = rule->exact;
// Multiple rules can set an action for the same site, hence the bit-wise OR
s->divert |= rule->divert;
s->split |= rule->split;
s->pass |= rule->pass;
s->block |= rule->block;
s->match |= rule->match;
// Multiple log actions can be set for the same site
// Multiple rules can enable/disable a log action for the same site, hence the direct assignment
s->log_connect = rule->log_connect;
s->log_master = rule->log_master;
s->log_cert = rule->log_cert;
s->log_content = rule->log_content;
s->log_pcap = rule->log_pcap;
#ifndef WITHOUT_MIRROR
s->log_mirror |= rule->log_mirror;
s->log_mirror = rule->log_mirror;
#endif /* !WITHOUT_MIRROR */
// precedence can only go up not down
if (rule->precedence > s->precedence)
s->precedence = rule->precedence;
}
return prepend ? s : site;
}

@ -522,17 +522,40 @@ protohttp_apply_filter(pxy_conn_ctx_t *ctx)
}
else if (action & (FILTER_ACTION_DIVERT | FILTER_ACTION_SPLIT | FILTER_ACTION_PASS)) {
log_err_level_printf(LOG_WARNING, "HTTP filter cannot take divert, split, or pass actions, any log actions are ignored too\n");
goto out;
}
//else { /* FILTER_ACTION_MATCH */ }
if (action & (FILTER_LOG_CONNECT | FILTER_LOG_MASTER | FILTER_LOG_CERT | FILTER_LOG_CONTENT | FILTER_LOG_PCAP
if (action & (FILTER_LOG_CONTENT | FILTER_LOG_PCAP
#ifndef WITHOUT_MIRROR
| FILTER_LOG_MIRROR
#endif /* !WITHOUT_MIRROR */
)) {
log_err_level_printf(LOG_WARNING, "HTTP filter cannot take log actions\n");
#ifndef WITHOUT_MIRROR
log_err_level_printf(LOG_WARNING, "HTTP filter cannot enable content, pcap, and mirror logging\n");
#else /* !WITHOUT_MIRROR */
log_err_level_printf(LOG_WARNING, "HTTP filter cannot enable content and pcap logging\n");
#endif /* WITHOUT_MIRROR */
}
// Note that connect, master, and cert logs have already been written by now
// so disabling those logs here will not have any effect
ctx->log_connect = !!(action & FILTER_LOG_CONNECT);
ctx->log_master = !!(action & FILTER_LOG_MASTER);
ctx->log_cert = !!(action & FILTER_LOG_CERT);
// content, pcap, and mirror logging can be disabled only
// loggers will stop writing further contents
if (!(action & FILTER_LOG_CONTENT))
ctx->log_content = 0;
if (!(action & FILTER_LOG_PCAP))
ctx->log_pcap = 0;
#ifndef WITHOUT_MIRROR
if (!(action & FILTER_LOG_MIRROR))
ctx->log_mirror = 0;
#endif /* !WITHOUT_MIRROR */
}
out:
return rv;
}

@ -775,13 +775,13 @@ protossl_apply_filter(pxy_conn_ctx_t *ctx)
}
//else { /* FILTER_ACTION_MATCH */ }
ctx->log_connect |= !!(action & FILTER_LOG_CONNECT);
ctx->log_master |= !!(action & FILTER_LOG_MASTER);
ctx->log_cert |= !!(action & FILTER_LOG_CERT);
ctx->log_content |= !!(action & FILTER_LOG_CONTENT);
ctx->log_pcap |= !!(action & FILTER_LOG_PCAP);
ctx->log_connect = !!(action & FILTER_LOG_CONNECT);
ctx->log_master = !!(action & FILTER_LOG_MASTER);
ctx->log_cert = !!(action & FILTER_LOG_CERT);
ctx->log_content = !!(action & FILTER_LOG_CONTENT);
ctx->log_pcap = !!(action & FILTER_LOG_PCAP);
#ifndef WITHOUT_MIRROR
ctx->log_mirror |= !!(action & FILTER_LOG_MIRROR);
ctx->log_mirror = !!(action & FILTER_LOG_MIRROR);
#endif /* !WITHOUT_MIRROR */
}
return rv;

@ -575,17 +575,18 @@ prototcp_apply_filter(pxy_conn_ctx_t *ctx)
}
//else { /* FILTER_ACTION_MATCH */ }
// Filtering rules at higher precedence can enable/disable logging
// The presence of a log action enables that logging
// The absence does nothing
// hence the bit-wise OR
// The absence disables it
// hence the direct assignment
// And note the signum function '!!'
ctx->log_connect |= !!(action & FILTER_LOG_CONNECT);
ctx->log_master |= !!(action & FILTER_LOG_MASTER);
ctx->log_cert |= !!(action & FILTER_LOG_CERT);
ctx->log_content |= !!(action & FILTER_LOG_CONTENT);
ctx->log_pcap |= !!(action & FILTER_LOG_PCAP);
ctx->log_connect = !!(action & FILTER_LOG_CONNECT);
ctx->log_master = !!(action & FILTER_LOG_MASTER);
ctx->log_cert = !!(action & FILTER_LOG_CERT);
ctx->log_content = !!(action & FILTER_LOG_CONTENT);
ctx->log_pcap = !!(action & FILTER_LOG_PCAP);
#ifndef WITHOUT_MIRROR
ctx->log_mirror |= !!(action & FILTER_LOG_MIRROR);
ctx->log_mirror = !!(action & FILTER_LOG_MIRROR);
#endif /* !WITHOUT_MIRROR */
}
return rv;

@ -319,11 +319,10 @@ pxy_conn_ctx_free(pxy_conn_ctx_t *ctx, int by_requestor)
log_finest("ENTER");
if (WANT_CONTENT_LOG(ctx)) {
if (log_content_close(&ctx->logctx, by_requestor, ctx->log_content, ctx->log_pcap
#ifndef WITHOUT_MIRROR
, ctx->log_mirror
#endif /* !WITHOUT_MIRROR */
) == -1) {
// Always try to close log files, even if content, pcap, or mirror logging is disabled by filter rules
// The log files may have been initialized and opened
// so, do not pass down the log_content, log_pcap, and log_mirror fields of ctx
if (log_content_close(&ctx->logctx, by_requestor) == -1) {
log_err_level_printf(LOG_WARNING, "Content log close failed\n");
}
}
@ -2025,29 +2024,29 @@ pxyconn_set_filter_action(pxy_conn_ctx_t *ctx, filter_site_t *site)
}
// Multiple log actions can be defined, hence no 'else'
log_err_level_printf(LOG_INFO, "Site filter %s connect log for %s, precedence %d\n", site->log_connect ? "enable" : "disable", site->site, site->precedence);
if (site->log_connect) {
log_err_level_printf(LOG_INFO, "Site filter connect log for %s, precedence %d\n", site->site, site->precedence);
action |= FILTER_LOG_CONNECT;
}
log_err_level_printf(LOG_INFO, "Site filter %s master log for %s, precedence %d\n", site->log_master ? "enable" : "disable", site->site, site->precedence);
if (site->log_master) {
log_err_level_printf(LOG_INFO, "Site filter master log for %s, precedence %d\n", site->site, site->precedence);
action |= FILTER_LOG_MASTER;
}
log_err_level_printf(LOG_INFO, "Site filter %s cert log for %s, precedence %d\n", site->log_cert ? "enable" : "disable", site->site, site->precedence);
if (site->log_cert) {
log_err_level_printf(LOG_INFO, "Site filter cert log for %s, precedence %d\n", site->site, site->precedence);
action |= FILTER_LOG_CERT;
}
log_err_level_printf(LOG_INFO, "Site filter %s content log for %s, precedence %d\n", site->log_content ? "enable" : "disable", site->site, site->precedence);
if (site->log_content) {
log_err_level_printf(LOG_INFO, "Site filter content log for %s, precedence %d\n", site->site, site->precedence);
action |= FILTER_LOG_CONTENT;
}
log_err_level_printf(LOG_INFO, "Site filter %s pcap log for %s, precedence %d\n", site->log_pcap ? "enable" : "disable", site->site, site->precedence);
if (site->log_pcap) {
log_err_level_printf(LOG_INFO, "Site filter pcap log for %s, precedence %d\n", site->site, site->precedence);
action |= FILTER_LOG_PCAP;
}
#ifndef WITHOUT_MIRROR
log_err_level_printf(LOG_INFO, "Site filter %s mirror log for %s, precedence %d\n", site->log_mirror ? "enable" : "disable", site->site, site->precedence);
if (site->log_mirror) {
log_err_level_printf(LOG_INFO, "Site filter mirror log for %s, precedence %d\n", site->site, site->precedence);
action |= FILTER_LOG_MIRROR;
}
#endif /* !WITHOUT_MIRROR */

@ -318,7 +318,7 @@ The syntax of filtering rules is as follows:
uri (uri[*]|*)|
ip (serveraddr|*)|
*)]
[log ([connect] [master] [cert] [content] [pcap] [mirror]|*)]
[log ([[!]connect] [[!]master] [[!]cert] [[!]content] [[!]pcap] [[!]mirror]|*)]
|*)
.LP
The definition of which connections the rule action will be applied to is
@ -344,6 +344,8 @@ filtering rules:
- pcap enables writing packets to pcap files
- mirror enables mirroring packets to mirror interfaces or targets
.LP
You can add a negation prefix ! to a log action to disable that logging.
.LP
For example, if the following rules are defined in a structured HTTPS proxyspec,
.LP
Split from user soner desc notebook to sni example.com log content
@ -395,8 +397,8 @@ In terms of possible filter actions,
- Dst Host filtering rules can take all of the filter and log actions.
- SSL filtering rules can take all of the filter and log actions.
- HTTP filtering rules take the match and block filter actions, but not the
divert, split, or pass actions. Also, HTTP filtering rules do not take log
actions.
divert, split, or pass actions. Also, HTTP filtering rules can only disable
logging.
.LP
Log actions do not configure any loggers. Global loggers for respective log
actions should have been configured for those log actions to have any effect.

@ -286,7 +286,7 @@ PassUsers admin
# uri (uri[*]|*)|
# ip (serveraddr|*)|
# *)]
# [log ([connect] [master] [cert] [content] [pcap] [mirror]|*)]
# [log ([[!]connect] [[!]master] [[!]cert] [[!]content] [[!]pcap] [[!]mirror]|*)]
# |*)
#
# PassSite example.com is equivalent to the following two Pass rules:

@ -344,7 +344,7 @@ The syntax of filtering rules is as follows:
uri (uri[*]|*)|
ip (serveraddr|*)|
*)]
[log ([connect] [master] [cert] [content] [pcap] [mirror]|*)]
[log ([[!]connect] [[!]master] [[!]cert] [[!]content] [[!]pcap] [[!]mirror]|*)]
|*)
.br

Loading…
Cancel
Save