40 #define XFF_CHAIN_MINLEN 7
42 #define XFF_CHAIN_MAXLEN 256
44 #define XFF_DEFAULT "X-Forwarded-For"
53 static int ParseXFFString(
char *input,
char *output,
int output_size)
55 size_t len = strlen(input);
59 if (input[0] ==
'[') {
60 char *end = strchr(input,
']');
64 if (end != input+(
len - 1)) {
86 if (d == 3 && c == 1) {
88 char *x = strchr(input,
':');
101 if (inet_pton(AF_INET, input, ip) == 1 ||
102 inet_pton(AF_INET6, input, ip) == 1)
104 strlcpy(output, input, output_size);
110 static int HttpXFFGetIPFromTxAux(
111 const Flow *f, htp_tx_t *tx,
HttpXFFCfg *xff_cfg,
char *dstbuf,
int dstbuflen)
114 uint8_t *p_xff = NULL;
116 const htp_header_t *h_xff = htp_tx_request_header(tx, xff_cfg->
header);
121 memcpy(xff_chain, htp_header_value_ptr(h_xff), htp_header_value_len(h_xff));
122 xff_chain[htp_header_value_len(h_xff)] = 0;
126 p_xff =
memrchr(xff_chain,
' ', htp_header_value_len(h_xff));
135 p_xff = memchr(xff_chain,
',', htp_header_value_len(h_xff));
141 return ParseXFFString((
char *)p_xff, dstbuf, dstbuflen);
153 const Flow *f, uint64_t tx_id,
HttpXFFCfg *xff_cfg,
char *dstbuf,
int dstbuflen)
156 uint64_t total_txs = 0;
159 htp_state = (
HtpState *)FlowGetAppState(f);
161 if (htp_state == NULL) {
162 SCLogDebug(
"no http state, XFF IP cannot be retrieved");
167 if (tx_id >= total_txs)
172 SCLogDebug(
"tx is NULL, XFF cannot be retrieved");
175 return HttpXFFGetIPFromTxAux(f, tx, xff_cfg, dstbuf, dstbuflen);
186 if (htp_state == NULL) {
187 SCLogDebug(
"no http state, XFF IP cannot be retrieved");
195 memset(&state, 0,
sizeof(state));
203 if (HttpXFFGetIPFromTxAux(f, ires.
tx_ptr, xff_cfg, dstbuf, dstbuflen) == 1)
206 tx_id = ires.
tx_id + 1;
228 if (xff_mode != NULL && strcasecmp(xff_mode,
"overwrite") == 0) {
231 if (xff_mode == NULL) {
232 SCLogWarning(
"The XFF mode hasn't been defined, falling back to extra-data mode");
234 else if (strcasecmp(xff_mode,
"extra-data") != 0) {
236 "The XFF mode %s is invalid, falling back to extra-data mode", xff_mode);
243 if (xff_deployment != NULL && strcasecmp(xff_deployment,
"forward") == 0) {
246 if (xff_deployment == NULL) {
247 SCLogWarning(
"The XFF deployment hasn't been defined, falling back to reverse "
250 else if (strcasecmp(xff_deployment,
"reverse") != 0) {
251 SCLogWarning(
"The XFF mode %s is invalid, falling back to reverse proxy deployment",
259 if (xff_header != NULL) {
260 result->
header = (
char *) xff_header;
272 static int XFFTest01(
void) {
273 char input[] =
"1.2.3.4:5678";
275 int r = ParseXFFString(input, output,
sizeof(output));
276 FAIL_IF_NOT(r == 1 && strcmp(output,
"1.2.3.4") == 0);
280 static int XFFTest02(
void) {
281 char input[] =
"[12::34]:1234";
283 int r = ParseXFFString(input, output,
sizeof(output));
284 FAIL_IF_NOT(r == 1 && strcmp(output,
"12::34") == 0);
288 static int XFFTest03(
void) {
289 char input[] =
"[2a03:2880:1010:3f02:face:b00c:0:2]:80";
291 int r = ParseXFFString(input, output,
sizeof(output));
292 FAIL_IF_NOT(r == 1 && strcmp(output,
"2a03:2880:1010:3f02:face:b00c:0:2") == 0);
296 static int XFFTest04(
void) {
297 char input[] =
"[2a03:2880:1010:3f02:face:b00c:0:2]";
299 int r = ParseXFFString(input, output,
sizeof(output));
300 FAIL_IF_NOT(r == 1 && strcmp(output,
"2a03:2880:1010:3f02:face:b00c:0:2") == 0);
304 static int XFFTest05(
void) {
305 char input[] =
"[::ffff:1.2.3.4]:1234";
307 int r = ParseXFFString(input, output,
sizeof(output));
308 FAIL_IF_NOT(r == 1 && strcmp(output,
"::ffff:1.2.3.4") == 0);
312 static int XFFTest06(
void) {
313 char input[] =
"12::34";
315 int r = ParseXFFString(input, output,
sizeof(output));
316 FAIL_IF_NOT(r == 1 && strcmp(output,
"12::34") == 0);
320 static int XFFTest07(
void) {
321 char input[] =
"1.2.3.4";
323 int r = ParseXFFString(input, output,
sizeof(output));
324 FAIL_IF_NOT(r == 1 && strcmp(output,
"1.2.3.4") == 0);
328 static int XFFTest08(
void) {
329 char input[] =
"[1.2.3.4:1234";
331 int r = ParseXFFString(input, output,
sizeof(output));
336 static int XFFTest09(
void) {
337 char input[] =
"999.999.999.999:1234";
339 int r = ParseXFFString(input, output,
sizeof(output));