int have_xff_ip = 0;
if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) {
- have_xff_ip = HttpXFFGetIP(p, xff_cfg, buffer, XFF_MAXLEN);
+ have_xff_ip = HttpXFFGetIP(p->flow, xff_cfg, buffer, XFF_MAXLEN);
}
if (have_xff_ip) {
if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) {
if (pa->flags & PACKET_ALERT_FLAG_TX) {
- have_xff_ip = HttpXFFGetIPFromTx(p, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN);
+ have_xff_ip = HttpXFFGetIPFromTx(p->flow, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN);
} else {
- have_xff_ip = HttpXFFGetIP(p, xff_cfg, buffer, XFF_MAXLEN);
+ have_xff_ip = HttpXFFGetIP(p->flow, xff_cfg, buffer, XFF_MAXLEN);
}
}
if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) {
if (pa->flags & PACKET_ALERT_FLAG_TX) {
- have_xff_ip = HttpXFFGetIPFromTx(p, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN);
+ have_xff_ip = HttpXFFGetIPFromTx(p->flow, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN);
} else {
- have_xff_ip = HttpXFFGetIP(p, xff_cfg, buffer, XFF_MAXLEN);
+ have_xff_ip = HttpXFFGetIP(p->flow, xff_cfg, buffer, XFF_MAXLEN);
}
}
* \retval 1 if the IP has been found and returned in dstbuf
* \retval 0 if the IP has not being found or error
*/
-int HttpXFFGetIPFromTx(const Packet *p, uint64_t tx_id, HttpXFFCfg *xff_cfg,
+int HttpXFFGetIPFromTx(const Flow *f, uint64_t tx_id, HttpXFFCfg *xff_cfg,
char *dstbuf, int dstbuflen)
{
uint8_t xff_chain[XFF_CHAIN_MAXLEN];
uint64_t total_txs = 0;
uint8_t *p_xff = NULL;
- htp_state = (HtpState *)FlowGetAppState(p->flow);
+ htp_state = (HtpState *)FlowGetAppState(f);
if (htp_state == NULL) {
SCLogDebug("no http state, XFF IP cannot be retrieved");
return 0;
}
- total_txs = AppLayerParserGetTxCnt(p->flow, htp_state);
+ total_txs = AppLayerParserGetTxCnt(f, htp_state);
if (tx_id >= total_txs)
return 0;
- tx = AppLayerParserGetTx(p->flow->proto, ALPROTO_HTTP, htp_state, tx_id);
+ tx = AppLayerParserGetTx(f->proto, ALPROTO_HTTP, htp_state, tx_id);
if (tx == NULL) {
SCLogDebug("tx is NULL, XFF cannot be retrieved");
return 0;
* \retval 1 if the IP has been found and returned in dstbuf
* \retval 0 if the IP has not being found or error
*/
-int HttpXFFGetIP(const Packet *p, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen)
+int HttpXFFGetIP(const Flow *f, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen)
{
HtpState *htp_state = NULL;
uint64_t tx_id = 0;
uint64_t total_txs = 0;
- htp_state = (HtpState *)FlowGetAppState(p->flow);
+ htp_state = (HtpState *)FlowGetAppState(f);
if (htp_state == NULL) {
SCLogDebug("no http state, XFF IP cannot be retrieved");
goto end;
}
- total_txs = AppLayerParserGetTxCnt(p->flow, htp_state);
+ total_txs = AppLayerParserGetTxCnt(f, htp_state);
for (; tx_id < total_txs; tx_id++) {
- if (HttpXFFGetIPFromTx(p, tx_id, xff_cfg, dstbuf, dstbuflen) == 1)
+ if (HttpXFFGetIPFromTx(f, tx_id, xff_cfg, dstbuf, dstbuflen) == 1)
return 1;
}
void HttpXFFGetCfg(ConfNode *conf, HttpXFFCfg *result);
-int HttpXFFGetIPFromTx(const Packet *p, uint64_t tx_id, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen);
+int HttpXFFGetIPFromTx(const Flow *f, uint64_t tx_id, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen);
-int HttpXFFGetIP(const Packet *p, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen);
+int HttpXFFGetIP(const Flow *f, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen);
void HTPXFFParserRegisterTests(void);
#include "app-layer-parser.h"
#include "app-layer-htp.h"
+#include "app-layer-htp-xff.h"
#include "app-layer-smtp.h"
#include "output.h"
char prefix[FILESTORE_PREFIX_MAX];
char tmpdir[FILESTORE_PREFIX_MAX];
bool fileinfo;
+ HttpXFFCfg *xff_cfg;
} OutputFilestoreCtx;
typedef struct OutputFilestoreLogThread_ {
snprintf(js_metadata_filename, sizeof(js_metadata_filename),
"%s.%"PRIuMAX".%u.json", final_filename,
(uintmax_t)p->ts.tv_sec, ff->file_store_id);
- json_t *js_fileinfo = JsonBuildFileInfoRecord(p, ff, true, dir);
+ json_t *js_fileinfo = JsonBuildFileInfoRecord(p, ff, true, dir,
+ ctx->xff_cfg);
if (likely(js_fileinfo != NULL)) {
json_dump_file(js_fileinfo, js_metadata_filename, 0);
json_decref(js_fileinfo);
static void OutputFilestoreLogDeInitCtx(OutputCtx *output_ctx)
{
OutputFilestoreCtx *ctx = (OutputFilestoreCtx *)output_ctx->data;
+ if (ctx->xff_cfg != NULL) {
+ SCFree(ctx->xff_cfg);
+ }
SCFree(ctx);
SCFree(output_ctx);
}
strlcpy(ctx->prefix, log_directory, sizeof(ctx->prefix));
snprintf(ctx->tmpdir, sizeof(ctx->tmpdir) - 1, "%s/tmp", log_directory);
+ ctx->xff_cfg = SCCalloc(1, sizeof(HttpXFFCfg));
+ if (ctx->xff_cfg != NULL) {
+ HttpXFFGetCfg(conf, ctx->xff_cfg);
+ }
+
OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
if (unlikely(output_ctx == NULL)) {
SCFree(ctx);
if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) {
if (pa->flags & PACKET_ALERT_FLAG_TX) {
- have_xff_ip = HttpXFFGetIPFromTx(p, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN);
+ have_xff_ip = HttpXFFGetIPFromTx(p->flow, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN);
} else {
- have_xff_ip = HttpXFFGetIP(p, xff_cfg, buffer, XFF_MAXLEN);
+ have_xff_ip = HttpXFFGetIP(p->flow, xff_cfg, buffer, XFF_MAXLEN);
}
}
#include "output-json-smb.h"
#include "app-layer-htp.h"
+#include "app-layer-htp-xff.h"
#include "util-memcmp.h"
#include "stream-tcp-reassemble.h"
typedef struct OutputFileCtx_ {
LogFileCtx *file_ctx;
uint32_t file_cnt;
+ HttpXFFCfg *xff_cfg;
} OutputFileCtx;
typedef struct JsonFileLogThread_ {
} JsonFileLogThread;
json_t *JsonBuildFileInfoRecord(const Packet *p, const File *ff,
- const bool stored, uint8_t dir)
+ const bool stored, uint8_t dir, HttpXFFCfg *xff_cfg)
{
json_t *hjs = NULL;
enum OutputJsonLogDirection fdir = LOG_DIR_FLOW;
json_object_set_new(fjs, "size", json_integer(FileTrackedSize(ff)));
json_object_set_new(fjs, "tx_id", json_integer(ff->txid));
+ /* xff header */
+ if ((xff_cfg != NULL) && !(xff_cfg->flags & XFF_DISABLED) && p->flow != NULL) {
+ int have_xff_ip = 0;
+ char buffer[XFF_MAXLEN];
+
+ if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) {
+ have_xff_ip = HttpXFFGetIPFromTx(p->flow, ff->txid, xff_cfg, buffer, XFF_MAXLEN);
+ }
+
+ if (have_xff_ip) {
+ if (xff_cfg->flags & XFF_EXTRADATA) {
+ json_object_set_new(js, "xff", json_string(buffer));
+ }
+ else if (xff_cfg->flags & XFF_OVERWRITE) {
+ if (p->flowflags & FLOW_PKT_TOCLIENT) {
+ json_object_set(js, "dest_ip", json_string(buffer));
+ } else {
+ json_object_set(js, "src_ip", json_string(buffer));
+ }
+ }
+ }
+ }
+
/* originally just 'file', but due to bug 1127 naming it fileinfo */
json_object_set_new(js, "fileinfo", fjs);
static void FileWriteJsonRecord(JsonFileLogThread *aft, const Packet *p,
const File *ff, uint32_t dir)
{
+ HttpXFFCfg *xff_cfg = aft->filelog_ctx->xff_cfg;
json_t *js = JsonBuildFileInfoRecord(p, ff,
- ff->flags & FILE_STORED ? true : false, dir);
+ ff->flags & FILE_STORED ? true : false, dir, xff_cfg);
if (unlikely(js == NULL)) {
return;
}
static void OutputFileLogDeinitSub(OutputCtx *output_ctx)
{
OutputFileCtx *ff_ctx = output_ctx->data;
+ if (ff_ctx->xff_cfg != NULL) {
+ SCFree(ff_ctx->xff_cfg);
+ }
SCFree(ff_ctx);
SCFree(output_ctx);
}
FileForceHashParseCfg(conf);
}
+ output_file_ctx->xff_cfg = SCCalloc(1, sizeof(HttpXFFCfg));
+ if (output_file_ctx->xff_cfg != NULL) {
+ HttpXFFGetCfg(conf, output_file_ctx->xff_cfg);
+ }
output_ctx->data = output_file_ctx;
output_ctx->DeInit = OutputFileLogDeinitSub;
void JsonFileLogRegister(void);
#ifdef HAVE_LIBJANSSON
+#include "app-layer-htp-xff.h"
+
json_t *JsonBuildFileInfoRecord(const Packet *p, const File *ff,
- const bool stored, uint8_t dir);
+ const bool stored, uint8_t dir, HttpXFFCfg *xff_cfg);
#endif
#endif /* __OUTPUT_JSON_FILE_H__ */
#include "output.h"
#include "app-layer-htp.h"
+#include "app-layer-htp-xff.h"
#include "app-layer.h"
#include "app-layer-parser.h"
#include "util-privs.h"
uint32_t flags; /** Store mode */
uint64_t fields;/** Store fields */
bool include_metadata;
+ HttpXFFCfg *xff_cfg;
} LogHttpFileCtx;
typedef struct JsonHttpLogThread_ {
MemBufferReset(jhl->buffer);
JsonHttpLogJSON(jhl, js, tx, tx_id);
+ HttpXFFCfg *xff_cfg = jhl->httplog_ctx->xff_cfg;
+
+ /* xff header */
+ if ((xff_cfg != NULL) && !(xff_cfg->flags & XFF_DISABLED) && p->flow != NULL) {
+ int have_xff_ip = 0;
+ char buffer[XFF_MAXLEN];
+
+ have_xff_ip = HttpXFFGetIPFromTx(p->flow, tx_id, xff_cfg, buffer, XFF_MAXLEN);
+
+ if (have_xff_ip) {
+ if (xff_cfg->flags & XFF_EXTRADATA) {
+ json_object_set_new(js, "xff", json_string(buffer));
+ }
+ else if (xff_cfg->flags & XFF_OVERWRITE) {
+ if (p->flowflags & FLOW_PKT_TOCLIENT) {
+ json_object_set(js, "dest_ip", json_string(buffer));
+ } else {
+ json_object_set(js, "src_ip", json_string(buffer));
+ }
+ }
+ }
+ }
OutputJSONBuffer(js, jhl->httplog_ctx->file_ctx, &jhl->buffer);
json_object_del(js, "http");
LogHttpFileCtx *http_ctx = output_ctx->data;
LogFileCtx *logfile_ctx = http_ctx->file_ctx;
LogFileFreeCtx(logfile_ctx);
+ if (http_ctx->xff_cfg) {
+ SCFree(http_ctx->xff_cfg);
+ }
SCFree(http_ctx);
SCFree(output_ctx);
}
}
}
}
+ http_ctx->xff_cfg = SCCalloc(1, sizeof(HttpXFFCfg));
+ if (http_ctx->xff_cfg != NULL) {
+ HttpXFFGetCfg(conf, http_ctx->xff_cfg);
+ }
+
output_ctx->data = http_ctx;
output_ctx->DeInit = OutputHttpLogDeinit;
static void OutputHttpLogDeinitSub(OutputCtx *output_ctx)
{
LogHttpFileCtx *http_ctx = output_ctx->data;
+ if (http_ctx->xff_cfg) {
+ SCFree(http_ctx->xff_cfg);
+ }
SCFree(http_ctx);
SCFree(output_ctx);
}
}
}
}
+ http_ctx->xff_cfg = SCCalloc(1, sizeof(HttpXFFCfg));
+ if (http_ctx->xff_cfg != NULL) {
+ HttpXFFGetCfg(conf, http_ctx->xff_cfg);
+ }
+
output_ctx->data = http_ctx;
output_ctx->DeInit = OutputHttpLogDeinitSub;
# custom allows additional http fields to be included in eve-log
# the example below adds three additional fields when uncommented
#custom: [Accept-Encoding, Accept-Language, Authorization]
+ # 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 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.
+ header: X-Forwarded-For
- dns:
# This configuration uses the new DNS logging format,
# the old configuration is still available:
# force logging of checksums, available hash functions are md5,
# sha1 and sha256
#force-hash: [md5]
+ # 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 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.
+ header: X-Forwarded-For
#- drop:
# alerts: yes # log alerts that caused drops
# flows: all # start or all: 'start' logs only a single drop
# the use of this output module as it uses the SHA256 as the
# file naming scheme.
#force-hash: [sha1, md5]
+ # NOTE: X-Forwarded configuration is ignored if write-fileinfo is disabled
+ # 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 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.
+ header: X-Forwarded-For
# output module to store extracted files to disk (old style, deprecated)
#