From e7901e88302e8db99a6d02eff19daff785207691 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Fri, 24 May 2024 16:46:00 +0100 Subject: [PATCH] ipsec: fix missing udp port check Type: fix This patch fixes the missing UDP port check in IPsec NAT-T case. As of RFC3948 UDP encapped ESP traffic should have destination port ID of 4500, which was missing. The related tests are updated with this port ID, too. Change-Id: I73ecc6a93de8d0f4b642313b0f4d9c2f214a7790 Signed-off-by: Fan Zhang --- src/vnet/ipsec/ipsec_input.c | 15 +++++++-------- test/template_ipsec.py | 12 ++++++------ test/test_ipsec_spd_flow_cache_input.py | 8 ++++---- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/vnet/ipsec/ipsec_input.c b/src/vnet/ipsec/ipsec_input.c index 6ccc0be2622..9cec7dd15d1 100644 --- a/src/vnet/ipsec/ipsec_input.c +++ b/src/vnet/ipsec/ipsec_input.c @@ -299,10 +299,11 @@ ipsec_esp_packet_process (vlib_main_t *vm, ipsec_main_t *im, ip4_header_t *ip0, search_flow_cache = im->input_flow_cache_flag; udp_or_esp: - /* SPI ID field in the ESP header MUST NOT be a zero value */ if (esp0->spi == 0) { - /* Drop the packet if SPI ID is zero */ + /* RFC 4303, section 2.1: The SPI value of zero (0 is reserved for + * local, implementation-specific use and MUST NOT be sent on the wire. + */ *ipsec_unprocessed += 1; next[0] = IPSEC_INPUT_NEXT_DROP; return; @@ -552,12 +553,10 @@ VLIB_NODE_FN (ipsec4_input_node) (vlib_main_t * vm, udp_header_t *udp0 = NULL; udp0 = (udp_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0)); - /* As per rfc3948 in UDP Encapsulated Header, UDP checksum must be - * Zero, and receivers must not depen upon UPD checksum. - * inside ESP header , SPI ID value MUST NOT be a zero value - * */ - - if (udp0->checksum == 0) + /* RFC5996 Section 2.23 "Port 4500 is reserved for + * UDP-encapsulated ESP and IKE." + */ + if (clib_host_to_net_u16 (4500) == udp0->dst_port) { esp0 = (esp_header_t *) ((u8 *) udp0 + sizeof (udp_header_t)); diff --git a/test/template_ipsec.py b/test/template_ipsec.py index b5cd922f127..7953f603287 100644 --- a/test/template_ipsec.py +++ b/test/template_ipsec.py @@ -3022,7 +3022,7 @@ class SpdFlowCacheTemplate(IPSecIPv4Fwd): return False def create_stream( - cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=5678, proto="UDP-ESP" + cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=4500, proto="UDP-ESP" ): packets = [] packets = super(SpdFlowCacheTemplate, cls).create_stream( @@ -3031,7 +3031,7 @@ class SpdFlowCacheTemplate(IPSecIPv4Fwd): return packets def verify_capture( - self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=5678 + self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=4500 ): super(SpdFlowCacheTemplate, self).verify_l3_l4_capture( src_if, dst_if, capture, tcp_port_in, udp_port_in @@ -3056,7 +3056,7 @@ class SpdFastPathTemplate(IPSecIPv4Fwd): super(SpdFastPathTemplate, self).tearDown() def create_stream( - cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=5678, proto="UDP-ESP" + cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=4500, proto="UDP-ESP" ): packets = [] packets = super(SpdFastPathTemplate, cls).create_stream( @@ -3065,7 +3065,7 @@ class SpdFastPathTemplate(IPSecIPv4Fwd): return packets def verify_capture( - self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=5678 + self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=4500 ): super(SpdFastPathTemplate, self).verify_l3_l4_capture( src_if, dst_if, capture, tcp_port_in, udp_port_in @@ -3084,7 +3084,7 @@ class IpsecDefaultTemplate(IPSecIPv4Fwd): super(IpsecDefaultTemplate, self).tearDown() def create_stream( - cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=5678, proto="UDP-ESP" + cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=4500, proto="UDP-ESP" ): packets = [] packets = super(IpsecDefaultTemplate, cls).create_stream( @@ -3093,7 +3093,7 @@ class IpsecDefaultTemplate(IPSecIPv4Fwd): return packets def verify_capture( - self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=5678 + self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=4500 ): super(IpsecDefaultTemplate, self).verify_l3_l4_capture( src_if, dst_if, capture, tcp_port_in, udp_port_in diff --git a/test/test_ipsec_spd_flow_cache_input.py b/test/test_ipsec_spd_flow_cache_input.py index 283f345be18..b913a980599 100644 --- a/test/test_ipsec_spd_flow_cache_input.py +++ b/test/test_ipsec_spd_flow_cache_input.py @@ -785,9 +785,9 @@ class IPSec4SpdTestCaseCollisionInbound(SpdFlowCacheInbound): # create the packet streams # packet hashes to: # ad727628 - packets1 = self.create_stream(self.pg2, self.pg1, pkt_count, 1, 1) + packets1 = self.create_stream(self.pg2, self.pg1, pkt_count, 1, 4500) # b5512898 - packets2 = self.create_stream(self.pg0, self.pg3, pkt_count, 1, 1) + packets2 = self.create_stream(self.pg0, self.pg3, pkt_count, 1, 4500) # add the streams to the source interfaces self.pg2.add_stream(packets1) self.pg0.add_stream(packets2) @@ -821,9 +821,9 @@ class IPSec4SpdTestCaseCollisionInbound(SpdFlowCacheInbound): # create the packet streams # 2f8f90f557eef12c - packets1 = self.create_stream(self.pg2, self.pg1, pkt_count, 1, 1) + packets1 = self.create_stream(self.pg2, self.pg1, pkt_count, 1, 4500) # 6b7f9987719ffc1c - packets2 = self.create_stream(self.pg3, self.pg2, pkt_count, 1, 1) + packets2 = self.create_stream(self.pg3, self.pg2, pkt_count, 1, 4500) # add the streams to the source interfaces self.pg2.add_stream(packets1) self.pg3.add_stream(packets2)