fix faketcp filter on windows (#2190)

This commit is contained in:
KKRainbow
2026-04-30 23:55:56 +08:00
committed by GitHub
parent aae30894dd
commit 41b6d65604
4 changed files with 54 additions and 16 deletions
@@ -57,21 +57,21 @@ cfg_select! {
pub mod windivert; pub mod windivert;
pub fn create_tun( pub fn create_tun(
_interface_name: &str, interface_name: &str,
_src_addr: Option<SocketAddr>, src_addr: Option<SocketAddr>,
local_addr: SocketAddr, dst_addr: SocketAddr,
) -> io::Result<Arc<dyn super::stack::Tun>> { ) -> io::Result<Arc<dyn super::stack::Tun>> {
match windivert::WinDivertTun::new(local_addr) { match windivert::WinDivertTun::new(src_addr, dst_addr) {
Ok(tun) => Ok(Arc::new(tun)), Ok(tun) => Ok(Arc::new(tun)),
Err(e) => { Err(e) => {
tracing::warn!( tracing::warn!(
?e, ?e,
?local_addr, ?dst_addr,
"WinDivertTun init failed, falling back to PnetTun" "WinDivertTun init failed, falling back to PnetTun"
); );
Ok(Arc::new(pnet::PnetTun::new( Ok(Arc::new(pnet::PnetTun::new(
local_addr.to_string().as_str(), interface_name,
pnet::create_packet_filter(None, local_addr), pnet::create_packet_filter(src_addr, dst_addr),
)?)) )?))
} }
} }
@@ -80,15 +80,11 @@ impl Drop for WinDivertTun {
} }
impl WinDivertTun { impl WinDivertTun {
pub fn new(local_addr: SocketAddr) -> io::Result<Self> { pub fn new(src_addr: Option<SocketAddr>, dst_addr: SocketAddr) -> io::Result<Self> {
let (tx, rx) = tokio::sync::mpsc::channel(1024); let (tx, rx) = tokio::sync::mpsc::channel(1024);
let ip_filter = match local_addr { let filter = build_filter(src_addr, dst_addr)?;
SocketAddr::V4(addr) => format!("ip.DstAddr == {}", addr.ip()), tracing::debug!(%filter, "WinDivertTun created with filter");
SocketAddr::V6(addr) => format!("ipv6.DstAddr == {}", addr.ip()),
};
// Filter: DstIP == LocalIP AND TCP.
let filter = format!("{} and tcp", ip_filter);
// Sniff mode: 1 (WINDIVERT_FLAG_SNIFF) // Sniff mode: 1 (WINDIVERT_FLAG_SNIFF)
// Layer: Network (0) // Layer: Network (0)
@@ -143,6 +139,46 @@ impl WinDivertTun {
} }
} }
fn build_filter(src_addr: Option<SocketAddr>, dst_addr: SocketAddr) -> io::Result<String> {
if let Some(src_addr) = src_addr
&& src_addr.is_ipv4() != dst_addr.is_ipv4()
{
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"src/dst addr family mismatch",
));
}
let mut filters = Vec::with_capacity(5);
filters.push("tcp".to_owned());
match dst_addr {
SocketAddr::V4(addr) => {
filters.push(format!("ip.DstAddr == {}", addr.ip()));
filters.push(format!("tcp.DstPort == {}", addr.port()));
}
SocketAddr::V6(addr) => {
filters.push(format!("ipv6.DstAddr == {}", addr.ip()));
filters.push(format!("tcp.DstPort == {}", addr.port()));
}
}
if let Some(src_addr) = src_addr {
match src_addr {
SocketAddr::V4(addr) => {
filters.push(format!("ip.SrcAddr == {}", addr.ip()));
filters.push(format!("tcp.SrcPort == {}", addr.port()));
}
SocketAddr::V6(addr) => {
filters.push(format!("ipv6.SrcAddr == {}", addr.ip()));
filters.push(format!("tcp.SrcPort == {}", addr.port()));
}
}
}
Ok(filters.join(" and "))
}
#[async_trait::async_trait] #[async_trait::async_trait]
impl stack::Tun for WinDivertTun { impl stack::Tun for WinDivertTun {
async fn recv(&self, packet: &mut BytesMut) -> Result<usize, std::io::Error> { async fn recv(&self, packet: &mut BytesMut) -> Result<usize, std::io::Error> {
-1
View File
@@ -128,7 +128,6 @@ pub fn build_tcp_packet(
eth_buf.freeze() eth_buf.freeze()
} }
#[tracing::instrument(ret)]
pub fn parse_ip_packet( pub fn parse_ip_packet(
buf: &Bytes, buf: &Bytes,
) -> Option<(MacAddr, MacAddr, IPPacket<'_>, tcp::TcpPacket<'_>)> { ) -> Option<(MacAddr, MacAddr, IPPacket<'_>, tcp::TcpPacket<'_>)> {
+4 -1
View File
@@ -517,9 +517,12 @@ impl Stack {
{ {
trace!(?tcp_packet, "Received SYN packet for port {}, ignoring", tcp_packet.get_destination()); trace!(?tcp_packet, "Received SYN packet for port {}, ignoring", tcp_packet.get_destination());
continue; continue;
} else if (tcp_packet.get_flags() & tcp::TcpFlags::RST) == 0 { } else if (tcp_packet.get_flags() & tcp::TcpFlags::RST) != 0 {
info!("Unknown RST TCP packet from {}, ignoring", remote_addr); info!("Unknown RST TCP packet from {}, ignoring", remote_addr);
continue; continue;
} else {
trace!("Unknown TCP packet from {}, ignoring", remote_addr);
continue;
} }
} }
None => { None => {