From: Fupeng Zhao Date: Tue, 24 Jun 2025 06:27:26 +0000 (+0800) Subject: decoder/vxlan: fix VXLAN port detection per RFC 7348 X-Git-Tag: suricata-8.0.2~48 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F14001%2Fhead;p=thirdparty%2Fsuricata.git decoder/vxlan: fix VXLAN port detection per RFC 7348 Simplify DecodeVXLANEnabledForPort() to only check destination port to avoids false positives when identifying VXLAN traffic. Per RFC 7348 ยง5, VXLAN identification is based solely on the outer UDP destination port (4789), regardless of inner packet direction. The outer UDP source port is used for load balancing via inner packet hash and should not be considered for VXLAN detection. This ensures correct VXLAN identification for all encapsulated traffic patterns. Checking both source and destination ports could incorrectly classify non-VXLAN UDP traffic as VXLAN when the source port happens to be 4789, leading to false positives in VXLAN detection and potential decode errors. (cherry picked from commit 7a04a032b9387c85321a24a4105700c288aee5e6) --- diff --git a/src/decode-udp.c b/src/decode-udp.c index 6d34250d22..9f96def3cd 100644 --- a/src/decode-udp.c +++ b/src/decode-udp.c @@ -103,7 +103,7 @@ int DecodeUDP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, } /* Handle VXLAN if configured */ - if (DecodeVXLANEnabledForPort(p->sp, p->dp) && + if (DecodeVXLANEnabledForPort(p->dp) && unlikely(DecodeVXLAN(tv, dtv, p, p->payload, p->payload_len) == TM_ECODE_OK)) { /* Here we have a VXLAN packet and don't need to handle app * layer */ diff --git a/src/decode-vxlan.c b/src/decode-vxlan.c index 92433a0fcd..4b6984821d 100644 --- a/src/decode-vxlan.c +++ b/src/decode-vxlan.c @@ -59,17 +59,17 @@ typedef struct VXLANHeader_ { uint8_t res; } VXLANHeader; -bool DecodeVXLANEnabledForPort(const uint16_t sp, const uint16_t dp) +bool DecodeVXLANEnabledForPort(const uint16_t dp) { - SCLogDebug("ports %u->%u ports %d %d %d %d", sp, dp, g_vxlan_ports[0], g_vxlan_ports[1], - g_vxlan_ports[2], g_vxlan_ports[3]); + SCLogDebug("checking dest port %u against ports %d %d %d %d", dp, g_vxlan_ports[0], + g_vxlan_ports[1], g_vxlan_ports[2], g_vxlan_ports[3]); if (g_vxlan_enabled) { for (int i = 0; i < g_vxlan_ports_idx; i++) { if (g_vxlan_ports[i] == VXLAN_UNSET_PORT) return false; - const int port = g_vxlan_ports[i]; - if (port == (const int)sp || port == (const int)dp) + /* RFC 7348: VXLAN identification is based on destination port only */ + if (g_vxlan_ports[i] == (const int)dp) return true; } } diff --git a/src/decode-vxlan.h b/src/decode-vxlan.h index f80ebd001a..65328be852 100644 --- a/src/decode-vxlan.h +++ b/src/decode-vxlan.h @@ -28,6 +28,6 @@ void DecodeVXLANRegisterTests(void); void DecodeVXLANConfig(void); -bool DecodeVXLANEnabledForPort(const uint16_t sp, const uint16_t dp); +bool DecodeVXLANEnabledForPort(const uint16_t dp); #endif /* !SURICATA_DECODE_VXLAN_H */