diff --git a/src/alert-unified2-alert.c b/src/alert-unified2-alert.c index 330cf55bd9..14432d46a8 100644 --- a/src/alert-unified2-alert.c +++ b/src/alert-unified2-alert.c @@ -336,7 +336,7 @@ int Unified2Logger(ThreadVars *t, void *data, const Packet *p) /* overwrite mode can only work per u2 block, not per individual * alert. So we'll look for an XFF record once */ - if ((xff_cfg->mode & XFF_OVERWRITE) && p->flow != NULL) { + if ((xff_cfg->flags & XFF_OVERWRITE) && p->flow != NULL) { char buffer[XFF_MAXLEN]; int have_xff_ip = 0; @@ -896,7 +896,7 @@ static int Unified2IPv6TypeAlert(ThreadVars *t, const Packet *p, void *data) HttpXFFCfg *xff_cfg = aun->unified2alert_ctx->xff_cfg; - if ((xff_cfg->mode & XFF_EXTRADATA) && p->flow != NULL) { + if ((xff_cfg->flags & XFF_EXTRADATA) && p->flow != NULL) { char buffer[XFF_MAXLEN]; int have_xff_ip = 0; @@ -1073,7 +1073,7 @@ static int Unified2IPv4TypeAlert (ThreadVars *tv, const Packet *p, void *data) HttpXFFCfg *xff_cfg = aun->unified2alert_ctx->xff_cfg; - if ((xff_cfg->mode & XFF_EXTRADATA) && p->flow != NULL) { + if ((xff_cfg->flags & XFF_EXTRADATA) && p->flow != NULL) { char buffer[XFF_MAXLEN]; int have_xff_ip = 0; diff --git a/src/app-layer-htp-xff.c b/src/app-layer-htp-xff.c index 2abf972675..2d931daeb3 100644 --- a/src/app-layer-htp-xff.c +++ b/src/app-layer-htp-xff.c @@ -140,7 +140,7 @@ void HttpXFFGetCfg(ConfNode *conf, HttpXFFCfg *result) const char *xff_mode = ConfNodeLookupChildValue(xff_node, "mode"); if (xff_mode != NULL && strcasecmp(xff_mode, "overwrite") == 0) { - result->mode |= XFF_OVERWRITE; + result->flags |= XFF_OVERWRITE; } else { if (xff_mode == NULL) { SCLogWarning(SC_WARN_XFF_INVALID_MODE, "The XFF mode hasn't been defined, falling back to extra-data mode"); @@ -149,7 +149,22 @@ void HttpXFFGetCfg(ConfNode *conf, HttpXFFCfg *result) SCLogWarning(SC_WARN_XFF_INVALID_MODE, "The XFF mode %s is invalid, falling back to extra-data mode", xff_mode); } - result->mode |= XFF_EXTRADATA; + result->flags |= XFF_EXTRADATA; + } + + const char *xff_deployment = ConfNodeLookupChildValue(xff_node, "deployment"); + + if (xff_deployment != NULL && strcasecmp(xff_deployment, "forward") == 0) { + result->flags |= XFF_FORWARD; + } else { + if (xff_deployment == NULL) { + SCLogWarning(SC_WARN_XFF_INVALID_DEPLOYMENT, "The XFF deployment hasn't been defined, falling back to reverse proxy deployment"); + } + else if (strcasecmp(xff_deployment, "reverse") != 0) { + SCLogWarning(SC_WARN_XFF_INVALID_DEPLOYMENT, "The XFF mode %s is invalid, falling back to reverse proxy deployment", + xff_deployment); + } + result->flags |= XFF_REVERSE; } const char *xff_header = ConfNodeLookupChildValue(xff_node, "header"); @@ -163,6 +178,6 @@ void HttpXFFGetCfg(ConfNode *conf, HttpXFFCfg *result) } } else { - result->mode = XFF_DISABLED; + result->flags = XFF_DISABLED; } } diff --git a/src/app-layer-htp-xff.h b/src/app-layer-htp-xff.h index 45c74b7534..5ef20125d5 100644 --- a/src/app-layer-htp-xff.h +++ b/src/app-layer-htp-xff.h @@ -31,11 +31,15 @@ #define XFF_EXTRADATA 2 /** XFF overwrite mode */ #define XFF_OVERWRITE 4 +/** XFF is to be used in a reverse proxy deployment */ +#define XFF_REVERSE 8 +/** XFF is to be used in a forward proxy deployment */ +#define XFF_FORWARD 16 /** Single XFF IP maximum length (default value based on IPv6 address length) */ #define XFF_MAXLEN 46 typedef struct HttpXFFCfg_ { - uint8_t mode; /**< XFF operation mode */ + uint8_t flags; /**< XFF operation mode and deployment */ char *header; /**< XFF header name */ } HttpXFFCfg; diff --git a/src/output-json-alert.c b/src/output-json-alert.c index 266e96c7b0..4a07f60eae 100644 --- a/src/output-json-alert.c +++ b/src/output-json-alert.c @@ -256,7 +256,7 @@ static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p) HttpXFFCfg *xff_cfg = json_output_ctx->xff_cfg; /* xff header */ - if (!(xff_cfg->mode & XFF_DISABLED) && p->flow != NULL) { + if (!(xff_cfg->flags & XFF_DISABLED) && p->flow != NULL) { int have_xff_ip = 0; char buffer[XFF_MAXLEN]; @@ -271,10 +271,10 @@ static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p) FLOWLOCK_UNLOCK(p->flow); if (have_xff_ip) { - if (xff_cfg->mode & XFF_EXTRADATA) { + if (xff_cfg->flags & XFF_EXTRADATA) { json_object_set_new(js, "xff", json_string(buffer)); } - else if (xff_cfg->mode & XFF_OVERWRITE) { + else if (xff_cfg->flags & XFF_OVERWRITE) { if (p->flowflags & FLOW_PKT_TOCLIENT) { json_object_set(js, "dest_ip", json_string(buffer)); } else { diff --git a/src/util-error.c b/src/util-error.c index 454f8f3ff2..e8dd993902 100644 --- a/src/util-error.c +++ b/src/util-error.c @@ -291,6 +291,7 @@ const char * SCErrorToString(SCError err) CASE_CODE (SC_ERR_THREAD_QUEUE); CASE_CODE (SC_WARN_XFF_INVALID_MODE); CASE_CODE (SC_WARN_XFF_INVALID_HEADER); + CASE_CODE (SC_WARN_XFF_INVALID_DEPLOYMENT); CASE_CODE (SC_ERR_THRESHOLD_SETUP); CASE_CODE (SC_ERR_DNS_CONFIG); CASE_CODE (SC_ERR_MODBUS_CONFIG); diff --git a/src/util-error.h b/src/util-error.h index 21fc611160..8d5577d8ef 100644 --- a/src/util-error.h +++ b/src/util-error.h @@ -267,6 +267,7 @@ typedef enum { SC_ERR_THREAD_QUEUE, SC_WARN_XFF_INVALID_MODE, SC_WARN_XFF_INVALID_HEADER, + SC_WARN_XFF_INVALID_DEPLOYMENT, SC_ERR_THRESHOLD_SETUP, SC_ERR_DNS_CONFIG, SC_ERR_MODBUS_CONFIG, diff --git a/suricata.yaml.in b/suricata.yaml.in index dc4b9babd8..89c4326959 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -109,12 +109,16 @@ outputs: # HTTP X-Forwarded-For support by adding an extra field or overwriting # the source or destination IP address (depending on flow direction) # with the one reported in the X-Forwarded-For HTTP header. This is - # helpful when reviewing alerts for traffic that is being reversed - # proxied. + # helpful when reviewing alerts for traffic that is being reverse + # or forward proxied. xff: enabled: no # Two operation modes are available, "extra-data" and "overwrite". mode: extra-data + # Two proxy deployments are supported, "reverse" and "forward". In + # a "reverse" deployment the IP address used is the last one, in a + # "forward" deployment the first IP address is used. + deployment: reverse # Header name where the actual IP address will be reported, if more # than one IP address is present, the last IP address will be the # one taken into consideration. @@ -153,8 +157,8 @@ outputs: # HTTP X-Forwarded-For support by adding the unified2 extra header or # overwriting the source or destination IP address (depending on flow # direction) with the one reported in the X-Forwarded-For HTTP header. - # This is helpful when reviewing alerts for traffic that is being reversed - # proxied. + # This is helpful when reviewing alerts for traffic that is being reverse + # or forward proxied. xff: enabled: no # Two operation modes are available, "extra-data" and "overwrite". Note @@ -162,6 +166,10 @@ outputs: # X-Forwarded-For header is of a different version of the packet # received, it will fall-back to "extra-data" mode. mode: extra-data + # Two proxy deployments are supported, "reverse" and "forward". In + # a "reverse" deployment the IP address used is the last one, in a + # "forward" deployment the first IP address is used. + deployment: reverse # Header name where the actual IP address will be reported, if more # than one IP address is present, the last IP address will be the # one taken into consideration.