]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
decoder/vxlan: fix VXLAN port detection per RFC 7348 14001/head
authorFupeng Zhao <fupeng.zhao@foxmail.com>
Tue, 24 Jun 2025 06:27:26 +0000 (14:27 +0800)
committerVictor Julien <victor@inliniac.net>
Fri, 10 Oct 2025 11:46:41 +0000 (13:46 +0200)
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)

src/decode-udp.c
src/decode-vxlan.c
src/decode-vxlan.h

index 6d34250d22bd0b623f1ee20dfae058d1492d68c1..9f96def3cdb4694a285f35700dc27362d05f6922 100644 (file)
@@ -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 */
index 92433a0fcdedf98583870ffbbf3c4e4a83a129b0..4b6984821de70194811f8beb1f714d3eed4dc349 100644 (file)
@@ -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;
         }
     }
index f80ebd001a7c0974260872ecf949cbbe5b62a0bd..65328be85273abacdd49372c823883ee6829d62e 100644 (file)
@@ -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 */