From e6bac998d9acfc9eac1f08ff255e8b72ff5c3364 Mon Sep 17 00:00:00 2001 From: Giuseppe Longo Date: Mon, 26 Sep 2016 16:45:15 +0200 Subject: [PATCH] flow: add timeout for local bypass This adds a new timeout value for local bypassed state. For user simplication it is called only `bypassed`. The patch also adds a emergency value so we can clean bypassed flows a bit faster. --- src/flow-manager.c | 4 +- src/flow-private.h | 5 +++ src/flow.c | 103 ++++++++++++++++++++++++++++++++++++++------- src/flow.h | 1 + suricata.yaml.in | 12 +++++- 5 files changed, 108 insertions(+), 17 deletions(-) diff --git a/src/flow-manager.c b/src/flow-manager.c index 0ccbea80f8..8da17f93e6 100644 --- a/src/flow-manager.c +++ b/src/flow-manager.c @@ -204,7 +204,6 @@ static inline uint32_t FlowGetFlowTimeout(const Flow *f, enum FlowState state) timeout = flow_timeouts[f->protomap].new_timeout; break; case FLOW_STATE_ESTABLISHED: - case FLOW_STATE_LOCAL_BYPASSED: timeout = flow_timeouts[f->protomap].est_timeout; break; case FLOW_STATE_CLOSED: @@ -213,6 +212,9 @@ static inline uint32_t FlowGetFlowTimeout(const Flow *f, enum FlowState state) case FLOW_STATE_CAPTURE_BYPASSED: timeout = FLOW_BYPASSED_TIMEOUT; break; + case FLOW_STATE_LOCAL_BYPASSED: + timeout = flow_timeouts[f->protomap].bypassed_timeout; + break; } return timeout; } diff --git a/src/flow-private.h b/src/flow-private.h index a523f6a07c..19b81b4484 100644 --- a/src/flow-private.h +++ b/src/flow-private.h @@ -40,16 +40,21 @@ #define FLOW_DEFAULT_NEW_TIMEOUT 30 #define FLOW_DEFAULT_EST_TIMEOUT 300 #define FLOW_DEFAULT_CLOSED_TIMEOUT 0 +#define FLOW_DEFAULT_BYPASSED_TIMEOUT 100 #define FLOW_IPPROTO_TCP_NEW_TIMEOUT 30 #define FLOW_IPPROTO_TCP_EST_TIMEOUT 300 +#define FLOW_IPPROTO_TCP_BYPASSED_TIMEOUT 100 #define FLOW_IPPROTO_UDP_NEW_TIMEOUT 30 #define FLOW_IPPROTO_UDP_EST_TIMEOUT 300 +#define FLOW_IPPROTO_UDP_BYPASSED_TIMEOUT 100 #define FLOW_IPPROTO_ICMP_NEW_TIMEOUT 30 #define FLOW_IPPROTO_ICMP_EST_TIMEOUT 300 +#define FLOW_IPPROTO_ICMP_BYPASSED_TIMEOUT 100 #define FLOW_DEFAULT_EMERG_NEW_TIMEOUT 10 #define FLOW_DEFAULT_EMERG_EST_TIMEOUT 100 #define FLOW_DEFAULT_EMERG_CLOSED_TIMEOUT 0 +#define FLOW_DEFAULT_EMERG_BYPASSED_TIMEOUT 50 #define FLOW_IPPROTO_TCP_EMERG_NEW_TIMEOUT 10 #define FLOW_IPPROTO_TCP_EMERG_EST_TIMEOUT 100 #define FLOW_IPPROTO_UDP_EMERG_NEW_TIMEOUT 10 diff --git a/src/flow.c b/src/flow.c index 3718d5c9fb..f33c2bc5ba 100644 --- a/src/flow.c +++ b/src/flow.c @@ -499,34 +499,36 @@ void FlowInitFlowProto(void) { FlowTimeoutsInit(); -#define SET_DEFAULTS(p, n, e, c, ne, ee, ce) \ - flow_timeouts_normal[(p)].new_timeout = (n); \ - flow_timeouts_normal[(p)].est_timeout = (e); \ - flow_timeouts_normal[(p)].closed_timeout = (c); \ - flow_timeouts_emerg[(p)].new_timeout = (ne); \ - flow_timeouts_emerg[(p)].est_timeout = (ee); \ - flow_timeouts_emerg[(p)].closed_timeout = (ce); +#define SET_DEFAULTS(p, n, e, c, b, ne, ee, ce, be) \ + flow_timeouts_normal[(p)].new_timeout = (n); \ + flow_timeouts_normal[(p)].est_timeout = (e); \ + flow_timeouts_normal[(p)].closed_timeout = (c); \ + flow_timeouts_normal[(p)].bypassed_timeout = (b); \ + flow_timeouts_emerg[(p)].new_timeout = (ne); \ + flow_timeouts_emerg[(p)].est_timeout = (ee); \ + flow_timeouts_emerg[(p)].closed_timeout = (ce); \ + flow_timeouts_emerg[(p)].bypassed_timeout = (be); \ SET_DEFAULTS(FLOW_PROTO_DEFAULT, FLOW_DEFAULT_NEW_TIMEOUT, FLOW_DEFAULT_EST_TIMEOUT, - FLOW_DEFAULT_CLOSED_TIMEOUT, + FLOW_DEFAULT_CLOSED_TIMEOUT, FLOW_DEFAULT_BYPASSED_TIMEOUT, FLOW_DEFAULT_EMERG_NEW_TIMEOUT, FLOW_DEFAULT_EMERG_EST_TIMEOUT, - FLOW_DEFAULT_EMERG_CLOSED_TIMEOUT); + FLOW_DEFAULT_EMERG_CLOSED_TIMEOUT, FLOW_DEFAULT_EMERG_BYPASSED_TIMEOUT); SET_DEFAULTS(FLOW_PROTO_TCP, FLOW_IPPROTO_TCP_NEW_TIMEOUT, FLOW_IPPROTO_TCP_EST_TIMEOUT, - FLOW_DEFAULT_CLOSED_TIMEOUT, + FLOW_DEFAULT_CLOSED_TIMEOUT, FLOW_IPPROTO_TCP_BYPASSED_TIMEOUT, FLOW_IPPROTO_TCP_EMERG_NEW_TIMEOUT, FLOW_IPPROTO_TCP_EMERG_EST_TIMEOUT, - FLOW_DEFAULT_EMERG_CLOSED_TIMEOUT); + FLOW_DEFAULT_EMERG_CLOSED_TIMEOUT, FLOW_DEFAULT_EMERG_BYPASSED_TIMEOUT); SET_DEFAULTS(FLOW_PROTO_UDP, FLOW_IPPROTO_UDP_NEW_TIMEOUT, FLOW_IPPROTO_UDP_EST_TIMEOUT, - FLOW_DEFAULT_CLOSED_TIMEOUT, + FLOW_DEFAULT_CLOSED_TIMEOUT, FLOW_IPPROTO_UDP_BYPASSED_TIMEOUT, FLOW_IPPROTO_UDP_EMERG_NEW_TIMEOUT, FLOW_IPPROTO_UDP_EMERG_EST_TIMEOUT, - FLOW_DEFAULT_EMERG_CLOSED_TIMEOUT); + FLOW_DEFAULT_EMERG_CLOSED_TIMEOUT, FLOW_DEFAULT_EMERG_BYPASSED_TIMEOUT); SET_DEFAULTS(FLOW_PROTO_ICMP, FLOW_IPPROTO_ICMP_NEW_TIMEOUT, FLOW_IPPROTO_ICMP_EST_TIMEOUT, - FLOW_DEFAULT_CLOSED_TIMEOUT, + FLOW_DEFAULT_CLOSED_TIMEOUT, FLOW_IPPROTO_ICMP_BYPASSED_TIMEOUT, FLOW_IPPROTO_ICMP_EMERG_NEW_TIMEOUT, FLOW_IPPROTO_ICMP_EMERG_EST_TIMEOUT, - FLOW_DEFAULT_EMERG_CLOSED_TIMEOUT); + FLOW_DEFAULT_EMERG_CLOSED_TIMEOUT, FLOW_DEFAULT_EMERG_BYPASSED_TIMEOUT); flow_freefuncs[FLOW_PROTO_DEFAULT].Freefunc = NULL; flow_freefuncs[FLOW_PROTO_TCP].Freefunc = NULL; @@ -537,9 +539,11 @@ void FlowInitFlowProto(void) const char *new = NULL; const char *established = NULL; const char *closed = NULL; + const char *bypassed = NULL; const char *emergency_new = NULL; const char *emergency_established = NULL; const char *emergency_closed = NULL; + const char *emergency_bypassed = NULL; ConfNode *flow_timeouts = ConfGetNode("flow-timeouts"); if (flow_timeouts != NULL) { @@ -552,11 +556,14 @@ void FlowInitFlowProto(void) new = ConfNodeLookupChildValue(proto, "new"); established = ConfNodeLookupChildValue(proto, "established"); closed = ConfNodeLookupChildValue(proto, "closed"); + bypassed = ConfNodeLookupChildValue(proto, "bypassed"); emergency_new = ConfNodeLookupChildValue(proto, "emergency-new"); emergency_established = ConfNodeLookupChildValue(proto, "emergency-established"); emergency_closed = ConfNodeLookupChildValue(proto, "emergency-closed"); + emergency_bypassed = ConfNodeLookupChildValue(proto, + "emergency-bypassed"); if (new != NULL && ByteExtractStringUint32(&configval, 10, strlen(new), new) > 0) { @@ -575,6 +582,13 @@ void FlowInitFlowProto(void) flow_timeouts_normal[FLOW_PROTO_DEFAULT].closed_timeout = configval; } + if (bypassed != NULL && + ByteExtractStringUint32(&configval, 10, + strlen(bypassed), + bypassed) > 0) { + + flow_timeouts_normal[FLOW_PROTO_DEFAULT].bypassed_timeout = configval; + } if (emergency_new != NULL && ByteExtractStringUint32(&configval, 10, strlen(emergency_new), emergency_new) > 0) { @@ -595,6 +609,13 @@ void FlowInitFlowProto(void) flow_timeouts_emerg[FLOW_PROTO_DEFAULT].closed_timeout = configval; } + if (emergency_bypassed != NULL && + ByteExtractStringUint32(&configval, 10, + strlen(emergency_bypassed), + emergency_bypassed) > 0) { + + flow_timeouts_emerg[FLOW_PROTO_DEFAULT].bypassed_timeout = configval; + } } /* TCP. */ @@ -603,11 +624,14 @@ void FlowInitFlowProto(void) new = ConfNodeLookupChildValue(proto, "new"); established = ConfNodeLookupChildValue(proto, "established"); closed = ConfNodeLookupChildValue(proto, "closed"); + bypassed = ConfNodeLookupChildValue(proto, "bypassed"); emergency_new = ConfNodeLookupChildValue(proto, "emergency-new"); emergency_established = ConfNodeLookupChildValue(proto, "emergency-established"); emergency_closed = ConfNodeLookupChildValue(proto, "emergency-closed"); + emergency_bypassed = ConfNodeLookupChildValue(proto, + "emergency-bypassed"); if (new != NULL && ByteExtractStringUint32(&configval, 10, strlen(new), new) > 0) { @@ -626,6 +650,13 @@ void FlowInitFlowProto(void) flow_timeouts_normal[FLOW_PROTO_TCP].closed_timeout = configval; } + if (bypassed != NULL && + ByteExtractStringUint32(&configval, 10, + strlen(bypassed), + bypassed) > 0) { + + flow_timeouts_normal[FLOW_PROTO_TCP].bypassed_timeout = configval; + } if (emergency_new != NULL && ByteExtractStringUint32(&configval, 10, strlen(emergency_new), emergency_new) > 0) { @@ -646,6 +677,13 @@ void FlowInitFlowProto(void) flow_timeouts_emerg[FLOW_PROTO_TCP].closed_timeout = configval; } + if (emergency_bypassed != NULL && + ByteExtractStringUint32(&configval, 10, + strlen(emergency_bypassed), + emergency_bypassed) > 0) { + + flow_timeouts_emerg[FLOW_PROTO_TCP].bypassed_timeout = configval; + } } /* UDP. */ @@ -653,9 +691,13 @@ void FlowInitFlowProto(void) if (proto != NULL) { new = ConfNodeLookupChildValue(proto, "new"); established = ConfNodeLookupChildValue(proto, "established"); + bypassed = ConfNodeLookupChildValue(proto, "bypassed"); emergency_new = ConfNodeLookupChildValue(proto, "emergency-new"); emergency_established = ConfNodeLookupChildValue(proto, "emergency-established"); + emergency_bypassed = ConfNodeLookupChildValue(proto, + "emergency-bypassed"); + if (new != NULL && ByteExtractStringUint32(&configval, 10, strlen(new), new) > 0) { @@ -667,6 +709,13 @@ void FlowInitFlowProto(void) flow_timeouts_normal[FLOW_PROTO_UDP].est_timeout = configval; } + if (bypassed != NULL && + ByteExtractStringUint32(&configval, 10, + strlen(bypassed), + bypassed) > 0) { + + flow_timeouts_normal[FLOW_PROTO_UDP].bypassed_timeout = configval; + } if (emergency_new != NULL && ByteExtractStringUint32(&configval, 10, strlen(emergency_new), emergency_new) > 0) { @@ -680,6 +729,13 @@ void FlowInitFlowProto(void) flow_timeouts_emerg[FLOW_PROTO_UDP].est_timeout = configval; } + if (emergency_bypassed != NULL && + ByteExtractStringUint32(&configval, 10, + strlen(emergency_bypassed), + emergency_bypassed) > 0) { + + flow_timeouts_emerg[FLOW_PROTO_UDP].bypassed_timeout = configval; + } } /* ICMP. */ @@ -687,9 +743,12 @@ void FlowInitFlowProto(void) if (proto != NULL) { new = ConfNodeLookupChildValue(proto, "new"); established = ConfNodeLookupChildValue(proto, "established"); + bypassed = ConfNodeLookupChildValue(proto, "bypassed"); emergency_new = ConfNodeLookupChildValue(proto, "emergency-new"); emergency_established = ConfNodeLookupChildValue(proto, "emergency-established"); + emergency_bypassed = ConfNodeLookupChildValue(proto, + "emergency-bypassed"); if (new != NULL && ByteExtractStringUint32(&configval, 10, strlen(new), new) > 0) { @@ -702,6 +761,13 @@ void FlowInitFlowProto(void) flow_timeouts_normal[FLOW_PROTO_ICMP].est_timeout = configval; } + if (bypassed != NULL && + ByteExtractStringUint32(&configval, 10, + strlen(bypassed), + bypassed) > 0) { + + flow_timeouts_normal[FLOW_PROTO_ICMP].bypassed_timeout = configval; + } if (emergency_new != NULL && ByteExtractStringUint32(&configval, 10, strlen(emergency_new), emergency_new) > 0) { @@ -715,6 +781,13 @@ void FlowInitFlowProto(void) flow_timeouts_emerg[FLOW_PROTO_ICMP].est_timeout = configval; } + if (emergency_bypassed != NULL && + ByteExtractStringUint32(&configval, 10, + strlen(emergency_bypassed), + emergency_bypassed) > 0) { + + flow_timeouts_emerg[FLOW_PROTO_UDP].bypassed_timeout = configval; + } } } diff --git a/src/flow.h b/src/flow.h index e42e21147b..52dec76df1 100644 --- a/src/flow.h +++ b/src/flow.h @@ -434,6 +434,7 @@ typedef struct FlowProtoTimeout_ { uint32_t new_timeout; uint32_t est_timeout; uint32_t closed_timeout; + uint32_t bypassed_timeout; } FlowProtoTimeout; typedef struct FlowProtoFreeFunc_ { diff --git a/suricata.yaml.in b/suricata.yaml.in index 061f5830c4..69dfbdaec8 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -1055,7 +1055,9 @@ vlan: # of that flow). The value of "established" is the amount of # seconds that the engine will wait to free the flow if it spend that amount # without receiving new packets or closing the connection. "closed" is the -# amount of time to wait after a flow is closed (usually zero). +# amount of time to wait after a flow is closed (usually zero). "bypassed" +# timeout controls locally bypassed flows. For these flows we don't do any other +# tracking. If no packets have been seen after this timeout, the flow is discarded. # # There's an emergency mode that will become active under attack circumstances, # making the engine to check flow status faster. This configuration variables @@ -1069,26 +1071,34 @@ flow-timeouts: new: 30 established: 300 closed: 0 + bypassed: 100 emergency-new: 10 emergency-established: 100 emergency-closed: 0 + emergency-bypassed: 50 tcp: new: 60 established: 600 closed: 60 + bypassed: 100 emergency-new: 5 emergency-established: 100 emergency-closed: 10 + emergency-bypassed: 50 udp: new: 30 established: 300 + bypassed: 100 emergency-new: 10 emergency-established: 100 + emergency-bypassed: 50 icmp: new: 30 established: 300 + bypassed: 100 emergency-new: 10 emergency-established: 100 + emergency-bypassed: 50 # Stream engine settings. Here the TCP stream tracking and reassembly # engine is configured.