From 39a8da10c97064adec381777d1d9c771a94ca0b9 Mon Sep 17 00:00:00 2001 From: spacemeowx2 Date: Sun, 6 Feb 2022 06:55:44 +0800 Subject: [PATCH 1/7] feat: add wintun --- protocol/raw/Cargo.toml | 2 + protocol/raw/src/config.rs | 13 +++- protocol/raw/src/device.rs | 47 ++++++++------ protocol/raw/src/device/interface_info.rs | 11 ++-- protocol/raw/src/device/windows.rs | 74 +++++++++++++++++++++++ 5 files changed, 123 insertions(+), 24 deletions(-) create mode 100644 protocol/raw/src/device/windows.rs diff --git a/protocol/raw/Cargo.toml b/protocol/raw/Cargo.toml index 714fcafb..32e6feff 100644 --- a/protocol/raw/Cargo.toml +++ b/protocol/raw/Cargo.toml @@ -26,6 +26,8 @@ features = ["async"] [target.'cfg(windows)'.dependencies] libc = "0.2" +wintun = "0.2" +once_cell = "1.7.2" [target.'cfg(unix)'.dependencies] nix = "0.23.1" diff --git a/protocol/raw/src/config.rs b/protocol/raw/src/config.rs index 5dc04792..b7d251f6 100644 --- a/protocol/raw/src/config.rs +++ b/protocol/raw/src/config.rs @@ -1,8 +1,10 @@ +use std::net::Ipv4Addr; + use rd_interface::{ config::{Config, NetRef}, prelude::*, }; -use tokio_smoltcp::smoltcp::phy::Medium; +use tokio_smoltcp::smoltcp::{phy::Medium, wire::IpCidr}; #[rd_config] #[serde(rename_all = "lowercase")] @@ -46,6 +48,7 @@ impl Default for Layer { } } +#[cfg(unix)] impl From for tun_crate::Layer { fn from(l: Layer) -> Self { match l { @@ -98,3 +101,11 @@ pub struct RawNetConfig { #[serde(default)] pub forward: bool, } + +pub struct TunTapSetup { + pub name: Option, + pub addr: Ipv4Addr, + pub destination_addr: IpCidr, + pub mtu: usize, + pub layer: Layer, +} diff --git a/protocol/raw/src/device.rs b/protocol/raw/src/device.rs index 4e200e35..62c91858 100644 --- a/protocol/raw/src/device.rs +++ b/protocol/raw/src/device.rs @@ -1,6 +1,6 @@ use std::{net::Ipv4Addr, str::FromStr}; -use crate::config::{DeviceConfig, RawNetConfig, TunTap}; +use crate::config::{DeviceConfig, RawNetConfig, TunTap, TunTapSetup}; use boxed::BoxedAsyncDevice; pub use interface_info::get_interface_info; use pcap::{Capture, Device}; @@ -14,10 +14,15 @@ mod boxed; mod interface_info; #[cfg(unix)] mod unix; +#[cfg(unix)] +use crate::device::unix::get_tun; + +#[cfg(windows)] +mod windows; +#[cfg(windows)] +use crate::device::windows::get_tun; pub fn get_device(config: &RawNetConfig) -> Result<(EthernetAddress, BoxedAsyncDevice)> { - #[cfg(unix)] - use crate::device::unix::{get_tun, TunTapSetup}; let (ethernet_address, device) = match &config.device { DeviceConfig::String(dev) => { let ethernet_address = crate::device::get_interface_info(&dev) @@ -44,11 +49,7 @@ pub fn get_device(config: &RawNetConfig) -> Result<(EthernetAddress, BoxedAsyncD let device = Box::new(get_tun(setup)?); let ethernet_addr = match cfg.tuntap { TunTap::Tun => EthernetAddress::BROADCAST, - TunTap::Tap => { - crate::device::get_interface_info(&device.name()) - .context("Failed to get interface info")? - .ethernet_address - } + TunTap::Tap => unreachable!(), }; (ethernet_addr, BoxedAsyncDevice(device)) @@ -80,11 +81,7 @@ fn pcap_device_by_name(name: &str) -> Result { #[cfg(unix)] pub fn get_by_device(device: Device) -> Result { - use std::io; - use tokio_smoltcp::{ - device::{AsyncCapture, DeviceCapabilities}, - smoltcp::phy::Checksum, - }; + use tokio_smoltcp::device::AsyncCapture; let cap = Capture::from_device(device.clone()) .context("Failed to capture device")? @@ -127,9 +124,14 @@ pub fn get_by_device(device: Device) -> Result { } #[cfg(windows)] -pub fn get_by_device(device: Device) -> Result { +pub fn get_by_device(device: Device) -> Result { + use std::io; + use tokio::sync::mpsc::{Receiver, Sender}; - use tokio_smoltcp::util::ChannelCapture; + use tokio_smoltcp::{ + device::{ChannelCapture, DeviceCapabilities}, + smoltcp::phy::Checksum, + }; let mut cap = Capture::from_device(device.clone()) .context("Failed to capture device")? @@ -146,7 +148,7 @@ pub fn get_by_device(device: Device) -> Result { .open() .context("Failed to open device")?; - let recv = move |tx: Sender>| loop { + let recv = move |tx: Sender>>| loop { let p = match cap.next().map(|p| p.to_vec()) { Ok(p) => p, Err(pcap::Error::TimeoutExpired) => continue, @@ -155,13 +157,22 @@ pub fn get_by_device(device: Device) -> Result { break; } }; - tx.blocking_send(p).unwrap(); + + tx.blocking_send(Ok(p)).unwrap(); }; let send = move |mut rx: Receiver>| { while let Some(pkt) = rx.blocking_recv() { send.sendpacket(pkt).unwrap(); } }; - let capture = ChannelCapture::new(recv, send); + let mut caps = DeviceCapabilities::default(); + caps.max_transmission_unit = 1500; + caps.checksum.ipv4 = Checksum::Tx; + caps.checksum.tcp = Checksum::Tx; + caps.checksum.udp = Checksum::Tx; + caps.checksum.icmpv4 = Checksum::Tx; + caps.checksum.icmpv6 = Checksum::Tx; + + let capture = ChannelCapture::new(recv, send, caps); Ok(capture) } diff --git a/protocol/raw/src/device/interface_info.rs b/protocol/raw/src/device/interface_info.rs index 1d9700ce..71ed5ba7 100644 --- a/protocol/raw/src/device/interface_info.rs +++ b/protocol/raw/src/device/interface_info.rs @@ -51,9 +51,10 @@ mod unix { #[cfg(windows)] mod windows { - use super::{Error, InterfaceInfo}; + use super::InterfaceInfo; use smoltcp::wire::EthernetAddress; - use std::{mem, ptr}; + use std::{io, mem, ptr}; + use tokio_smoltcp::smoltcp; const NO_ERROR: u32 = 0; const ERROR_INSUFFICIENT_BUFFER: u32 = 122; @@ -77,7 +78,7 @@ mod windows { return None; } - pub fn get_interface_info(name: &str) -> Result { + pub fn get_interface_info(name: &str) -> io::Result { if let Some(intf_guid) = get_guid(name) { let mut size = 0u32; let table: *mut MibIftable; @@ -96,7 +97,7 @@ mod windows { { table = mem::transmute(libc::malloc(size as libc::size_t)); } else { - return Err(Error::NotFound); + return Err(io::ErrorKind::NotFound.into()); } if GetIfTable(table, &mut size as *mut libc::c_ulong, false) == NO_ERROR { @@ -130,7 +131,7 @@ mod windows { libc::free(mem::transmute(table)); } } - Err(Error::NotFound) + Err(io::ErrorKind::NotFound.into()) } pub const MAX_INTERFACE_NAME_LEN: usize = 256; diff --git a/protocol/raw/src/device/windows.rs b/protocol/raw/src/device/windows.rs new file mode 100644 index 00000000..967b7d3b --- /dev/null +++ b/protocol/raw/src/device/windows.rs @@ -0,0 +1,74 @@ +use std::{io, sync::Arc}; + +use crate::config::{Layer, TunTapSetup}; +use once_cell::sync::OnceCell; +use rd_interface::{Error, Result}; +use tokio::sync::mpsc::{Receiver, Sender}; +use tokio_smoltcp::{ + device::{ChannelCapture, DeviceCapabilities}, + smoltcp::phy::Checksum, +}; +use wintun::{Adapter, Wintun}; + +static WINTUN: OnceCell = OnceCell::new(); +const POOL_NAME: &'static str = "rabbit-digger-pro"; +const DEVICE_NAME: &'static str = "rabbit digger pro"; + +fn get_wintun() -> &'static Wintun { + WINTUN.get_or_init(|| unsafe { wintun::load() }.expect("Failed to load wintun.dll")) +} + +pub fn get_tun(cfg: TunTapSetup) -> Result { + if let Layer::L2 = cfg.layer { + return Err(Error::Other("On windows only support tun".into())); + } + + let adapter = match Adapter::open(get_wintun(), DEVICE_NAME) { + Ok(a) => a, + Err(_) => Adapter::create(&get_wintun(), POOL_NAME, DEVICE_NAME, None) + .map_err(|_| rd_interface::Error::other("Failed to create wintun"))?, + }; + let s1 = Arc::new( + adapter + .start_session(wintun::MAX_RING_CAPACITY) + .map_err(|_| rd_interface::Error::other("Failed to create wintun session"))?, + ); + let s2 = s1.clone(); + + let recv = move |tx: Sender>>| loop { + let p = match s1.receive_blocking().map(|p| p.bytes().to_vec()) { + Ok(p) => p, + Err(e) => { + eprintln!("Wintun recv error: {:?}", e); + break; + } + }; + tx.blocking_send(Ok(p)).unwrap(); + }; + let send = move |mut rx: Receiver>| { + while let Some(pkt) = rx.blocking_recv() { + let mut p = match s2.allocate_send_packet(pkt.len() as u16) { + Ok(p) => p, + Err(_) => { + eprintln!("Wintun send error"); + break; + } + }; + p.bytes_mut().copy_from_slice(&pkt); + s2.send_packet(p); + } + }; + + let mut caps = DeviceCapabilities::default(); + caps.medium = cfg.layer.into(); + caps.max_transmission_unit = 1500; + caps.checksum.ipv4 = Checksum::Tx; + caps.checksum.tcp = Checksum::Tx; + caps.checksum.udp = Checksum::Tx; + caps.checksum.icmpv4 = Checksum::Tx; + caps.checksum.icmpv6 = Checksum::Tx; + + let dev = ChannelCapture::new(recv, send, caps); + + Ok(dev) +} From 19766cb9c091ea3d1c32db58aa37f4bf617c6463 Mon Sep 17 00:00:00 2001 From: spacemeowx2 Date: Sun, 6 Feb 2022 06:59:55 +0800 Subject: [PATCH 2/7] fix(raw): unix compile error --- protocol/raw/src/device.rs | 23 ++++++++++++++--------- protocol/raw/src/device/unix.rs | 15 ++------------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/protocol/raw/src/device.rs b/protocol/raw/src/device.rs index 62c91858..f3f5e2f6 100644 --- a/protocol/raw/src/device.rs +++ b/protocol/raw/src/device.rs @@ -1,4 +1,4 @@ -use std::{net::Ipv4Addr, str::FromStr}; +use std::{io, net::Ipv4Addr, str::FromStr}; use crate::config::{DeviceConfig, RawNetConfig, TunTap, TunTapSetup}; use boxed::BoxedAsyncDevice; @@ -6,8 +6,11 @@ pub use interface_info::get_interface_info; use pcap::{Capture, Device}; use rd_interface::{Error, ErrorContext, Result}; use tokio_smoltcp::{ - device::AsyncDevice, - smoltcp::wire::{EthernetAddress, IpCidr}, + device::{AsyncDevice, DeviceCapabilities}, + smoltcp::{ + phy::Checksum, + wire::{EthernetAddress, IpCidr}, + }, }; mod boxed; @@ -49,6 +52,13 @@ pub fn get_device(config: &RawNetConfig) -> Result<(EthernetAddress, BoxedAsyncD let device = Box::new(get_tun(setup)?); let ethernet_addr = match cfg.tuntap { TunTap::Tun => EthernetAddress::BROADCAST, + #[cfg(unix)] + TunTap::Tap => { + crate::device::get_interface_info(&device.name()) + .context("Failed to get interface info")? + .ethernet_address + } + #[cfg(windows)] TunTap::Tap => unreachable!(), }; @@ -125,13 +135,8 @@ pub fn get_by_device(device: Device) -> Result { #[cfg(windows)] pub fn get_by_device(device: Device) -> Result { - use std::io; - use tokio::sync::mpsc::{Receiver, Sender}; - use tokio_smoltcp::{ - device::{ChannelCapture, DeviceCapabilities}, - smoltcp::phy::Checksum, - }; + use tokio_smoltcp::device::ChannelCapture; let mut cap = Capture::from_device(device.clone()) .context("Failed to capture device")? diff --git a/protocol/raw/src/device/unix.rs b/protocol/raw/src/device/unix.rs index dc16a2a2..7b65c187 100644 --- a/protocol/raw/src/device/unix.rs +++ b/protocol/raw/src/device/unix.rs @@ -5,15 +5,12 @@ use std::{ task::{Context, Poll}, }; -use crate::config::Layer; +use crate::config::TunTapSetup; use futures::{ready, Sink, SinkExt, Stream, StreamExt}; use rd_interface::{error::map_other, Result}; use tokio_smoltcp::{ device::{AsyncDevice, DeviceCapabilities, Packet}, - smoltcp::{ - phy::Checksum, - wire::{IpAddress, IpCidr}, - }, + smoltcp::{phy::Checksum, wire::IpAddress}, }; use tokio_util::codec::Framed; use tun_crate::{create_as_async, Configuration, Device, TunPacket, TunPacketCodec}; @@ -24,14 +21,6 @@ pub struct TunAsyncDevice { caps: DeviceCapabilities, } -pub struct TunTapSetup { - pub name: Option, - pub addr: Ipv4Addr, - pub destination_addr: IpCidr, - pub mtu: usize, - pub layer: Layer, -} - pub fn get_tun(cfg: TunTapSetup) -> Result { let mut config = Configuration::default(); let netmask = !0u32 >> (32 - cfg.destination_addr.prefix_len()); From 9199d505720ee0513e5652206d483a2c11b8e32c Mon Sep 17 00:00:00 2001 From: spacemeowx2 Date: Mon, 7 Feb 2022 03:16:06 +0800 Subject: [PATCH 3/7] feat(raw): set address to wintun device --- protocol/raw/src/device/windows.rs | 47 ++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/protocol/raw/src/device/windows.rs b/protocol/raw/src/device/windows.rs index 967b7d3b..68ef2da1 100644 --- a/protocol/raw/src/device/windows.rs +++ b/protocol/raw/src/device/windows.rs @@ -1,8 +1,12 @@ -use std::{io, sync::Arc}; +use std::{ + io::{self, Write}, + process::{Command, Stdio}, + sync::Arc, +}; use crate::config::{Layer, TunTapSetup}; use once_cell::sync::OnceCell; -use rd_interface::{Error, Result}; +use rd_interface::{error::map_other, Error, Result}; use tokio::sync::mpsc::{Receiver, Sender}; use tokio_smoltcp::{ device::{ChannelCapture, DeviceCapabilities}, @@ -35,6 +39,23 @@ pub fn get_tun(cfg: TunTapSetup) -> Result { ); let s2 = s1.clone(); + let wintun_adapter_index = adapter + .get_adapter_index() + .map_err(|_| rd_interface::Error::other("Failed to get adapter index"))?; + + let mut cmds = Vec::::new(); + cmds.push(format!("set interface {} metric=1", wintun_adapter_index)); + cmds.push(format!( + "set address {} static {}/{} gateway={} store=active", + wintun_adapter_index, + cfg.addr, + cfg.destination_addr.prefix_len(), + cfg.destination_addr.address(), + )); + for cmd in cmds.iter() { + run_netsh(cmd)?; + } + let recv = move |tx: Sender>>| loop { let p = match s1.receive_blocking().map(|p| p.bytes().to_vec()) { Ok(p) => p, @@ -72,3 +93,25 @@ pub fn get_tun(cfg: TunTapSetup) -> Result { Ok(dev) } + +fn run_netsh(cmd_str: &str) -> Result<()> { + let mut cmd = Command::new("netsh"); + cmd.arg("interface").arg("ip").args(cmd_str.split(" ")); + let output = cmd.stdout(Stdio::inherit()).output().map_err(map_other)?; + let status = output.status; + let stdout = output.stdout; + let stderr = output.stderr; + + if !status.success() || (!stdout.is_empty() && stdout != b"Ok.") { + tracing::error!( + "Running process: {:?} failed! Status: {:?}", + cmd_str, + status, + ); + io::stderr().write_all(&stdout)?; + io::stderr().write_all(&stderr)?; + return Err(Error::Other("Failed to run netsh".into())); + } + + Ok(()) +} From ac9553dd390b4f36c7dddfb39882df73c25f2d88 Mon Sep 17 00:00:00 2001 From: spacemeowx2 Date: Mon, 7 Feb 2022 03:24:55 +0800 Subject: [PATCH 4/7] build: update toolchain --- .github/workflows/codecov.yml | 2 +- .github/workflows/rust.yml | 12 ++++++------ .github/workflows/update_schema.yml | 6 +++--- rabbit-digger | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 87e63e45..38fa97ad 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -16,7 +16,7 @@ jobs: - name: Setup toolchain uses: actions-rs/toolchain@v1 with: - toolchain: nightly-2021-05-21 + toolchain: nightly-2022-01-01 override: true - name: Run cargo-tarpaulin uses: actions-rs/tarpaulin@v0.1 diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8916d248..930aec3d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -27,13 +27,13 @@ jobs: uses: actions/cache@v1 with: path: ~/.cargo - key: ${{ matrix.os }}-nightly-2021-05-21-cargo-v1 + key: ${{ matrix.os }}-nightly-2022-01-01-cargo-v1 restore-keys: | - ${{ matrix.os }}-nightly-2021-05-21-cargo-v1 + ${{ matrix.os }}-nightly-2022-01-01-cargo-v1 - name: Setup toolchain uses: actions-rs/toolchain@v1 with: - toolchain: nightly-2021-05-21 + toolchain: nightly-2022-01-01 target: ${{ matrix.target }} override: true - name: Run tests @@ -74,13 +74,13 @@ jobs: uses: actions/cache@v1 with: path: ~/.cargo - key: ${{ matrix.target }}-nightly-2021-05-21-cargo-v1 + key: ${{ matrix.target }}-nightly-2022-01-01-cargo-v1 restore-keys: | - ${{ matrix.target }}-nightly-2021-05-21-cargo-v1 + ${{ matrix.target }}-nightly-2022-01-01-cargo-v1 - name: Setup toolchain uses: actions-rs/toolchain@v1 with: - toolchain: nightly-2021-05-21 + toolchain: nightly-2022-01-01 target: ${{ matrix.target }} override: true - name: Build release diff --git a/.github/workflows/update_schema.yml b/.github/workflows/update_schema.yml index 46f7b7dd..14692aa6 100644 --- a/.github/workflows/update_schema.yml +++ b/.github/workflows/update_schema.yml @@ -20,13 +20,13 @@ jobs: uses: actions/cache@v1 with: path: ~/.cargo - key: ${{ matrix.os }}-nightly-2021-05-21-cargo-v1 + key: ${{ matrix.os }}-nightly-2022-01-01-cargo-v1 restore-keys: | - ${{ matrix.os }}-nightly-2021-05-21-cargo-v1 + ${{ matrix.os }}-nightly-2022-01-01-cargo-v1 - name: Setup toolchain uses: actions-rs/toolchain@v1 with: - toolchain: nightly-2021-05-21 + toolchain: nightly-2022-01-01 target: ${{ matrix.target }} override: true - name: Generate schema diff --git a/rabbit-digger b/rabbit-digger index 2cfb00c7..a13506bd 160000 --- a/rabbit-digger +++ b/rabbit-digger @@ -1 +1 @@ -Subproject commit 2cfb00c7397416dd008484f52e622e41cec17b81 +Subproject commit a13506bdc1c21039862beeabf3264fbd7974bd8a From 6baef49b2bd993c6fb2b6282a68d833f7db87095 Mon Sep 17 00:00:00 2001 From: spacemeowx2 Date: Tue, 8 Feb 2022 01:49:29 +0800 Subject: [PATCH 5/7] fix(raw): ignore broadcast packets --- protocol/raw/src/device/windows.rs | 12 ++++-------- protocol/raw/src/forward.rs | 14 ++++++++++---- protocol/raw/src/forward/source.rs | 29 +++++++++++++++++++++++++---- protocol/raw/src/net.rs | 7 ++++++- 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/protocol/raw/src/device/windows.rs b/protocol/raw/src/device/windows.rs index 68ef2da1..ec7ba117 100644 --- a/protocol/raw/src/device/windows.rs +++ b/protocol/raw/src/device/windows.rs @@ -43,18 +43,14 @@ pub fn get_tun(cfg: TunTapSetup) -> Result { .get_adapter_index() .map_err(|_| rd_interface::Error::other("Failed to get adapter index"))?; - let mut cmds = Vec::::new(); - cmds.push(format!("set interface {} metric=1", wintun_adapter_index)); - cmds.push(format!( + run_netsh(format!("set interface {} metric=250", wintun_adapter_index))?; + run_netsh(format!( "set address {} static {}/{} gateway={} store=active", wintun_adapter_index, cfg.addr, cfg.destination_addr.prefix_len(), cfg.destination_addr.address(), - )); - for cmd in cmds.iter() { - run_netsh(cmd)?; - } + ))?; let recv = move |tx: Sender>>| loop { let p = match s1.receive_blocking().map(|p| p.bytes().to_vec()) { @@ -94,7 +90,7 @@ pub fn get_tun(cfg: TunTapSetup) -> Result { Ok(dev) } -fn run_netsh(cmd_str: &str) -> Result<()> { +fn run_netsh(cmd_str: String) -> Result<()> { let mut cmd = Command::new("netsh"); cmd.arg("interface").arg("ip").args(cmd_str.split(" ")); let output = cmd.stdout(Stdio::inherit()).output().map_err(map_other)?; diff --git a/protocol/raw/src/forward.rs b/protocol/raw/src/forward.rs index 6eb95d00..f60fee37 100644 --- a/protocol/raw/src/forward.rs +++ b/protocol/raw/src/forward.rs @@ -7,7 +7,7 @@ use rd_interface::{Arc, Context, IntoAddress, Net, Result}; use rd_std::util::{connect_tcp, forward_udp}; use tokio::{select, spawn}; use tokio_smoltcp::{ - smoltcp::wire::{IpProtocol, IpVersion}, + smoltcp::wire::{IpCidr, IpProtocol, IpVersion}, Net as SmoltcpNet, RawSocket, TcpListener, }; @@ -18,9 +18,15 @@ mod source; struct Forward { net: Net, map: MapTable, + ip_cidr: IpCidr, } -pub async fn forward_net(net: Net, smoltcp_net: Arc, map: MapTable) -> io::Result<()> { +pub async fn forward_net( + net: Net, + smoltcp_net: Arc, + map: MapTable, + ip_cidr: IpCidr, +) -> io::Result<()> { let tcp_listener = smoltcp_net .tcp_bind(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 1).into()) .await?; @@ -28,7 +34,7 @@ pub async fn forward_net(net: Net, smoltcp_net: Arc, map: MapTable) .raw_socket(IpVersion::Ipv4, IpProtocol::Udp) .await?; - let forward = Forward { net, map }; + let forward = Forward { net, map, ip_cidr }; let tcp_task = forward.serve_tcp(tcp_listener); let udp_task = forward.serve_udp(raw_socket); @@ -63,7 +69,7 @@ impl Forward { } } async fn serve_udp(&self, raw: RawSocket) -> Result<()> { - let source = source::Source::new(raw); + let source = source::Source::new(raw, self.ip_cidr); forward_udp::forward_udp(source, self.net.clone()).await?; diff --git a/protocol/raw/src/forward/source.rs b/protocol/raw/src/forward/source.rs index 68f1c7bb..e5c7a69e 100644 --- a/protocol/raw/src/forward/source.rs +++ b/protocol/raw/src/forward/source.rs @@ -12,7 +12,7 @@ use tokio_smoltcp::{ smoltcp::{ self, phy::ChecksumCapabilities, - wire::{IpProtocol, Ipv4Address, Ipv4Packet, Ipv4Repr, UdpPacket, UdpRepr}, + wire::{IpCidr, IpProtocol, Ipv4Address, Ipv4Packet, Ipv4Repr, UdpPacket, UdpRepr}, }, RawSocket, }; @@ -21,14 +21,16 @@ pub struct Source { raw: RawSocket, recv_buf: Box<[u8]>, send_buf: Option>, + ip_cidr: IpCidr, } impl Source { - pub fn new(raw: RawSocket) -> Source { + pub fn new(raw: RawSocket, ip_cidr: IpCidr) -> Source { Source { raw, recv_buf: Box::new([0u8; 65536]), send_buf: None, + ip_cidr, } } } @@ -40,13 +42,32 @@ impl Stream for Source { mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, ) -> task::Poll> { - let Source { raw, recv_buf, .. } = &mut *self; + let Source { + raw, + recv_buf, + ip_cidr, + .. + } = &mut *self; let (from, to, data) = loop { let size = ready!(raw.poll_recv(cx, recv_buf))?; match parse_udp(&recv_buf[..size]) { - Ok(v) => break v, + Ok(v) => { + let broadcast = match ip_cidr { + IpCidr::Ipv4(v4) => { + v4.broadcast().map(Into::into).map(std::net::IpAddr::V4) + } + _ => None, + }; + + let to = v.1; + if broadcast == Some(to.ip()) || to.ip().is_multicast() { + continue; + } + + break v; + } _ => {} }; }; diff --git a/protocol/raw/src/net.rs b/protocol/raw/src/net.rs index ffdc8ef3..781387a9 100644 --- a/protocol/raw/src/net.rs +++ b/protocol/raw/src/net.rs @@ -68,7 +68,12 @@ impl RawNet { let map = device.get_map(); let smoltcp_net = Arc::new(SmoltcpNet::new(device, net_config)); - forward_handle = Some(tokio::spawn(forward_net(net, smoltcp_net.clone(), map))); + forward_handle = Some(tokio::spawn(forward_net( + net, + smoltcp_net.clone(), + map, + ip_cidr, + ))); smoltcp_net } else { Arc::new(SmoltcpNet::new(device, net_config)) From 4f6c546ba5dc0fb8040f93d9594d86c2aeb96bd3 Mon Sep 17 00:00:00 2001 From: spacemeowx2 Date: Tue, 8 Feb 2022 02:25:00 +0800 Subject: [PATCH 6/7] fix: wrong impl write_vectored in AsyncWrite --- protocol/obfs/src/http_simple.rs | 12 ------------ protocol/trojan/src/client/tcp.rs | 12 ------------ protocol/trojan/src/tls/rustls.rs | 12 ------------ rabbit-digger | 2 +- 4 files changed, 1 insertion(+), 37 deletions(-) diff --git a/protocol/obfs/src/http_simple.rs b/protocol/obfs/src/http_simple.rs index 78f87aca..d0792c44 100644 --- a/protocol/obfs/src/http_simple.rs +++ b/protocol/obfs/src/http_simple.rs @@ -173,18 +173,6 @@ impl AsyncWrite for Connect { ) -> Poll> { Pin::new(&mut self.inner).poll_shutdown(cx) } - - fn poll_write_vectored( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - bufs: &[io::IoSlice<'_>], - ) -> Poll> { - Pin::new(&mut self.inner).poll_write_vectored(cx, bufs) - } - - fn is_write_vectored(&self) -> bool { - self.inner.is_write_vectored() - } } #[async_trait] diff --git a/protocol/trojan/src/client/tcp.rs b/protocol/trojan/src/client/tcp.rs index 5e4e2dc6..bb6832c6 100644 --- a/protocol/trojan/src/client/tcp.rs +++ b/protocol/trojan/src/client/tcp.rs @@ -71,18 +71,6 @@ impl AsyncWrite for TrojanTcp { ) -> task::Poll> { Pin::new(&mut self.stream).poll_shutdown(cx) } - - fn poll_write_vectored( - mut self: Pin<&mut Self>, - cx: &mut task::Context<'_>, - bufs: &[io::IoSlice<'_>], - ) -> task::Poll> { - Pin::new(&mut self.stream).poll_write_vectored(cx, bufs) - } - - fn is_write_vectored(&self) -> bool { - self.stream.is_write_vectored() - } } #[async_trait] diff --git a/protocol/trojan/src/tls/rustls.rs b/protocol/trojan/src/tls/rustls.rs index 4a021b93..c7a9c7ff 100644 --- a/protocol/trojan/src/tls/rustls.rs +++ b/protocol/trojan/src/tls/rustls.rs @@ -117,18 +117,6 @@ where fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut self.inner).poll_shutdown(cx) } - - fn poll_write_vectored( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - bufs: &[io::IoSlice<'_>], - ) -> Poll> { - Pin::new(&mut self.inner).poll_write_vectored(cx, bufs) - } - - fn is_write_vectored(&self) -> bool { - self.inner.is_write_vectored() - } } impl PushingStream { diff --git a/rabbit-digger b/rabbit-digger index a13506bd..3dd430f6 160000 --- a/rabbit-digger +++ b/rabbit-digger @@ -1 +1 @@ -Subproject commit a13506bdc1c21039862beeabf3264fbd7974bd8a +Subproject commit 3dd430f62ba047acb585d991ead8368b0a51dd79 From 56096f0926f62123318173761354a7de9a497be7 Mon Sep 17 00:00:00 2001 From: spacemeowx2 Date: Tue, 8 Feb 2022 02:34:25 +0800 Subject: [PATCH 7/7] fix(raw): skip udp to self --- protocol/raw/src/forward/source.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/protocol/raw/src/forward/source.rs b/protocol/raw/src/forward/source.rs index e5c7a69e..081c6d12 100644 --- a/protocol/raw/src/forward/source.rs +++ b/protocol/raw/src/forward/source.rs @@ -1,6 +1,6 @@ use std::{ io, - net::{SocketAddr, SocketAddrV4}, + net::{IpAddr, SocketAddr, SocketAddrV4}, pin::Pin, task, }; @@ -55,14 +55,15 @@ impl Stream for Source { match parse_udp(&recv_buf[..size]) { Ok(v) => { let broadcast = match ip_cidr { - IpCidr::Ipv4(v4) => { - v4.broadcast().map(Into::into).map(std::net::IpAddr::V4) - } + IpCidr::Ipv4(v4) => v4.broadcast().map(Into::into).map(IpAddr::V4), _ => None, }; let to = v.1; - if broadcast == Some(to.ip()) || to.ip().is_multicast() { + if broadcast == Some(to.ip()) + || to.ip().is_multicast() + || to.ip() == IpAddr::from(ip_cidr.address()) + { continue; }