From 05af535c44d29b7fdb619d790f35994f0eeaefc0 Mon Sep 17 00:00:00 2001 From: Oleksandr Deundiak Date: Fri, 24 Jul 2026 12:05:19 -0400 Subject: [PATCH] fix(s2n-quic-core): Relax port scope check during connection migration Previously, any port scope change would result in rejected connection migration, which could cause unexpected reachability issues. To avoid that we now allow port scope change, unless it's system -> non-system scope change or vice versa. --- quic/s2n-quic-core/src/path/migration.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/quic/s2n-quic-core/src/path/migration.rs b/quic/s2n-quic-core/src/path/migration.rs index ab28d16e2a..55514d7445 100644 --- a/quic/s2n-quic-core/src/path/migration.rs +++ b/quic/s2n-quic-core/src/path/migration.rs @@ -138,10 +138,11 @@ pub mod default { //# datagrams that match these patterns prior to validating the //# destination address. - // NOTE: this may cause reachability issues if a peer or NAT use different - // port scopes for the same connection. Additional research may - // be required to determine if this countermeasure needs to be relaxed. - if PortScope::new(active_addr.port()) != PortScope::new(packet_addr.port()) { + let active_port_scope = PortScope::new(active_addr.port()); + let packet_port_scope = PortScope::new(packet_addr.port()); + if active_port_scope.is_system() != packet_port_scope.is_system() { + // Changing port scope from the system to a non-system (user or dynamic) scope + // and vice versa is rejected. Any other combination is allowed. return Outcome::Deny(DenyReason::PortScopeChanged); } @@ -192,6 +193,11 @@ pub mod default { 49152..=65535 => Self::Dynamic, } } + + #[inline] + pub fn is_system(&self) -> bool { + self == &PortScope::System + } } fn to_addr(addr: &SocketAddress) -> crate::inet::SocketAddress {