diff --git a/netstack/src/filter/conntrack.rs b/netstack/src/filter/conntrack.rs index 438b93d955..f18720b8d0 100644 --- a/netstack/src/filter/conntrack.rs +++ b/netstack/src/filter/conntrack.rs @@ -150,6 +150,7 @@ struct ConnEntry { reply_key: ConnKey, state: ConnState, tcp_state: TcpTracking, + fin_from_orig: bool, timeout: Instant, orig_packets: u64, orig_bytes: u64, @@ -194,10 +195,12 @@ fn advance_entry_state(entry: &mut ConnEntry, is_orig: bool, ctx: &PacketContext } TcpTracking::Established if res_fin => { entry.tcp_state = TcpTracking::FinWait; + entry.fin_from_orig = true; entry.timeout = now + Duration::from_secs(120); return true; } - TcpTracking::FinWait if res_fin => { + TcpTracking::FinWait if res_fin && !entry.fin_from_orig => { + // Second FIN from reply direction (orig FIN was first) entry.tcp_state = TcpTracking::TimeWait; entry.timeout = now + Duration::from_secs(120); return true; @@ -219,10 +222,12 @@ fn advance_entry_state(entry: &mut ConnEntry, is_orig: bool, ctx: &PacketContext } TcpTracking::Established if res_fin => { entry.tcp_state = TcpTracking::FinWait; + entry.fin_from_orig = false; entry.timeout = now + Duration::from_secs(120); return true; } - TcpTracking::FinWait if res_fin => { + TcpTracking::FinWait if res_fin && entry.fin_from_orig => { + // Second FIN from orig direction (reply FIN was first) entry.tcp_state = TcpTracking::TimeWait; entry.timeout = now + Duration::from_secs(120); return true; @@ -327,6 +332,7 @@ impl ConntrackTable { reply_key, state, tcp_state, + fin_from_orig: false, timeout: now + timeout, orig_packets: 1, orig_bytes: ctx.packet.len() as u64, @@ -390,6 +396,7 @@ impl ConntrackTable { }, state: ConnState::New, tcp_state: TcpTracking::None, + fin_from_orig: false, timeout: now + Duration::from_secs(30), orig_packets: 1, orig_bytes: ctx.packet.len() as u64, @@ -518,9 +525,15 @@ impl ConntrackTable { pub fn format(&self) -> alloc::string::String { let mut out = alloc::format!("conntrack entries: {}, over_limit: {}\n", self.entries.len(), self.over_limit_count); for entry in self.entries.values() { + let tcp_info = if entry.key.l4proto == 6 { + alloc::format!(" tcp={:?}", entry.tcp_state) + } else { + alloc::string::String::new() + }; out.push_str(&alloc::format!( - " {:?} src={} dst={} sport={} dport={} orig_pkts={} orig_bytes={} reply_pkts={} reply_bytes={}\n", + " {:?}{} src={} dst={} sport={} dport={} orig_pkts={} orig_bytes={} reply_pkts={} reply_bytes={}\n", entry.state, + tcp_info, entry.key.src_addr, entry.key.dst_addr, entry.key.src_port,