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 fn create_tun(
_interface_name: &str,
_src_addr: Option<SocketAddr>,
local_addr: SocketAddr,
interface_name: &str,
src_addr: Option<SocketAddr>,
dst_addr: SocketAddr,
) -> 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)),
Err(e) => {
tracing::warn!(
?e,
?local_addr,
?dst_addr,
"WinDivertTun init failed, falling back to PnetTun"
);
Ok(Arc::new(pnet::PnetTun::new(
local_addr.to_string().as_str(),
pnet::create_packet_filter(None, local_addr),
interface_name,
pnet::create_packet_filter(src_addr, dst_addr),
)?))
}
}
@@ -80,15 +80,11 @@ impl Drop for 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 ip_filter = match local_addr {
SocketAddr::V4(addr) => format!("ip.DstAddr == {}", addr.ip()),
SocketAddr::V6(addr) => format!("ipv6.DstAddr == {}", addr.ip()),
};
// Filter: DstIP == LocalIP AND TCP.
let filter = format!("{} and tcp", ip_filter);
let filter = build_filter(src_addr, dst_addr)?;
tracing::debug!(%filter, "WinDivertTun created with filter");
// Sniff mode: 1 (WINDIVERT_FLAG_SNIFF)
// 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]
impl stack::Tun for WinDivertTun {
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()
}
#[tracing::instrument(ret)]
pub fn parse_ip_packet(
buf: &Bytes,
) -> 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());
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);
continue;
} else {
trace!("Unknown TCP packet from {}, ignoring", remote_addr);
continue;
}
}
None => {