From e97cdb48f3e32e8d76aaa2f7325a1a67e245be8e Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Mon, 23 Mar 2020 11:06:55 +0100 Subject: [PATCH] decode/teredo: implement port support Implement support for limiting Teredo detection and decoding to specific UDP ports, with 3544 as the default. If no ports are specified, the old behaviour of detecting/decoding on any port is still in place. This can also be forced by specifying 'any' as the port setting. --- doc/userguide/configuration/suricata-yaml.rst | 6 ++ src/decode-teredo.c | 63 ++++++++++++++++++- src/decode-teredo.h | 3 +- src/decode-udp.c | 5 +- suricata.yaml.in | 5 ++ 5 files changed, 77 insertions(+), 5 deletions(-) diff --git a/doc/userguide/configuration/suricata-yaml.rst b/doc/userguide/configuration/suricata-yaml.rst index 70a6effdfd..e3d82350a2 100644 --- a/doc/userguide/configuration/suricata-yaml.rst +++ b/doc/userguide/configuration/suricata-yaml.rst @@ -2246,7 +2246,13 @@ The Teredo decoder can be disabled. It is enabled by default. # it will sometimes detect non-teredo as teredo. teredo: enabled: true + # ports to look for Teredo. Max 4 ports. If no ports are given, or + # the value is set to 'any', Teredo detection runs on _all_ UDP packets. + ports: $TEREDO_PORTS # syntax: '[3544, 1234]' +Using this default configuration, Teredo detection will run on UDP port +3544. If the `ports` parameter is missing, or set to `any`, all ports will be +inspected for possible presence of Teredo. Advanced Options ---------------- diff --git a/src/decode-teredo.c b/src/decode-teredo.c index 93e9711c51..4b8c648a16 100644 --- a/src/decode-teredo.c +++ b/src/decode-teredo.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Open Information Security Foundation +/* Copyright (C) 2012-2020 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -38,10 +38,63 @@ #include "decode-teredo.h" #include "util-debug.h" #include "conf.h" +#include "detect-engine-port.h" -#define TEREDO_ORIG_INDICATION_LENGTH 8 +#define TEREDO_ORIG_INDICATION_LENGTH 8 static bool g_teredo_enabled = true; +static int g_teredo_ports[4] = { -1, -1, -1, -1 }; +static int g_teredo_ports_cnt = 0; +static bool g_teredo_ports_any = true; + +bool DecodeTeredoEnabledForPort(const uint16_t sp, const uint16_t dp) +{ + SCLogDebug("ports %u->%u ports %d %d %d %d", sp, dp, + g_teredo_ports[0], g_teredo_ports[1], + g_teredo_ports[2], g_teredo_ports[3]); + + if (g_teredo_enabled) { + /* no port config means we are enabled for all ports */ + if (g_teredo_ports_any) { + return true; + } + + for (int i = 0; i < g_teredo_ports_cnt; i++) { + if (g_teredo_ports[i] == -1) + return false; + const int port = g_teredo_ports[i]; + if (port == (const int)sp || + port == (const int)dp) + return true; + } + } + return false; +} + +static void DecodeTeredoConfigPorts(const char *pstr) +{ + SCLogDebug("parsing \'%s\'", pstr); + + if (strcmp(pstr, "any") == 0) { + g_teredo_ports_any = true; + return; + } + + DetectPort *head = NULL; + DetectPortParse(NULL, &head, pstr); + + g_teredo_ports_any = false; + g_teredo_ports_cnt = 0; + for (DetectPort *p = head; p != NULL; p = p->next) { + if (g_teredo_ports_cnt >= 4) { + SCLogWarning(SC_ERR_INVALID_YAML_CONF_ENTRY, + "only 4 Teredo ports can be defined"); + break; + } + g_teredo_ports[g_teredo_ports_cnt++] = (int)p->port; + } + DetectPortCleanupList(NULL, head); +} void DecodeTeredoConfig(void) { @@ -53,6 +106,12 @@ void DecodeTeredoConfig(void) g_teredo_enabled = false; } } + if (g_teredo_enabled) { + ConfNode *node = ConfGetNode("decoder.teredo.ports"); + if (node && node->val) { + DecodeTeredoConfigPorts(node->val); + } + } } /** diff --git a/src/decode-teredo.h b/src/decode-teredo.h index 1c414f19bf..bbd9dc8163 100644 --- a/src/decode-teredo.h +++ b/src/decode-teredo.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Open Information Security Foundation +/* Copyright (C) 2012-2020 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -21,5 +21,6 @@ int DecodeTeredo(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len); void DecodeTeredoConfig(void); +bool DecodeTeredoEnabledForPort(const uint16_t sp, const uint16_t dp); #endif diff --git a/src/decode-udp.c b/src/decode-udp.c index 225a15daa7..436b10a132 100644 --- a/src/decode-udp.c +++ b/src/decode-udp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2010 Open Information Security Foundation +/* Copyright (C) 2007-2020 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -84,7 +84,8 @@ int DecodeUDP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, SCLogDebug("UDP sp: %" PRIu32 " -> dp: %" PRIu32 " - HLEN: %" PRIu32 " LEN: %" PRIu32 "", UDP_GET_SRC_PORT(p), UDP_GET_DST_PORT(p), UDP_HEADER_LEN, p->payload_len); - if (unlikely(DecodeTeredo(tv, dtv, p, p->payload, p->payload_len) == TM_ECODE_OK)) { + if (DecodeTeredoEnabledForPort(p->sp, p->dp) && + likely(DecodeTeredo(tv, dtv, p, p->payload, p->payload_len) == TM_ECODE_OK)) { /* Here we have a Teredo packet and don't need to handle app * layer */ FlowSetupPacket(p); diff --git a/suricata.yaml.in b/suricata.yaml.in index 4890729498..628a3c0d47 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -45,6 +45,7 @@ vars: FILE_DATA_PORTS: "[$HTTP_PORTS,110,143]" FTP_PORTS: 21 VXLAN_PORTS: 4789 + TEREDO_PORTS: 3544 ## ## Step 2: Select outputs to enable @@ -1328,6 +1329,10 @@ decoder: # as it will sometimes detect non-teredo as teredo. teredo: enabled: true + # ports to look for Teredo. Max 4 ports. If no ports are given, or + # the value is set to 'any', Teredo detection runs on _all_ UDP packets. + ports: $TEREDO_PORTS # syntax: '[3544, 1234]' or '3533' or 'any'. + # VXLAN decoder is assigned to up to 4 UDP ports. By default only the # IANA assigned port 4789 is enabled. vxlan: