mirror of
https://github.com/tun2proxy/tun2proxy.git
synced 2025-04-19 21:39:09 +00:00
wintun added
This commit is contained in:
parent
513702e35f
commit
8aeaf238f2
4 changed files with 177 additions and 10 deletions
10
Cargo.toml
10
Cargo.toml
|
@ -50,3 +50,13 @@ reqwest = { version = "0.11", default-features = false, features = [
|
|||
] }
|
||||
serial_test = "2.0"
|
||||
test-log = "0.2"
|
||||
|
||||
[target.'cfg(target_os="windows")'.dependencies]
|
||||
windows = { version = "0.51", features = [
|
||||
"Win32_NetworkManagement_IpHelper",
|
||||
"Win32_NetworkManagement_Ndis",
|
||||
"Win32_Networking_WinSock",
|
||||
"Win32_Foundation",
|
||||
] }
|
||||
wintun = "0.3"
|
||||
mio = { version = "0.8", features = ["net", "os-ext", "os-poll"] }
|
||||
|
|
|
@ -23,6 +23,8 @@ mod tuntapinterface;
|
|||
mod tuntapinterfacedesc;
|
||||
mod virtdevice;
|
||||
mod virtdns;
|
||||
#[cfg(target_os = "windows")]
|
||||
mod wintuninterface;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Proxy {
|
||||
|
|
|
@ -6,16 +6,17 @@ use crate::{dns, error::Error, error::Result, virtdevice::VirtualTunDevice, Netw
|
|||
#[cfg(target_family = "unix")]
|
||||
use mio::unix::SourceFd;
|
||||
use mio::{event::Event, net::TcpStream, net::UdpSocket, Events, Interest, Poll, Token};
|
||||
#[cfg(not(target_family = "unix"))]
|
||||
use smoltcp::phy::DeviceCapabilities;
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
use smoltcp::phy::RawSocket;
|
||||
// #[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
// use smoltcp::phy::TunTapInterface;
|
||||
#[cfg(target_os = "windows")]
|
||||
use crate::wintuninterface::WinTunInterface;
|
||||
#[cfg(target_family = "unix")]
|
||||
use smoltcp::phy::{Device, Medium, RxToken, TxToken};
|
||||
use smoltcp::phy::{RxToken, TxToken};
|
||||
use smoltcp::{
|
||||
iface::{Config, Interface, SocketHandle, SocketSet},
|
||||
phy::{Device, Medium},
|
||||
socket::{tcp, tcp::State, udp, udp::UdpMetadata},
|
||||
time::Instant,
|
||||
wire::{IpCidr, IpProtocol, Ipv4Packet, Ipv6Packet, TcpPacket, UdpPacket, UDP_HEADER_LEN},
|
||||
|
@ -217,6 +218,8 @@ pub struct TunToProxy<'a> {
|
|||
tun: TunTapInterface,
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
tun: RawSocket,
|
||||
#[cfg(target_os = "windows")]
|
||||
tun: WinTunInterface,
|
||||
poll: Poll,
|
||||
iface: Interface,
|
||||
connection_map: HashMap<ConnectionInfo, ConnectionState>,
|
||||
|
@ -246,6 +249,11 @@ impl<'a> TunToProxy<'a> {
|
|||
NetworkInterface::Fd(_fd) => panic!("Not supported"),
|
||||
};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let tun = match _interface {
|
||||
NetworkInterface::Named(name) => WinTunInterface::new(name.as_str(), Medium::Ip)?,
|
||||
};
|
||||
|
||||
let poll = Poll::new()?;
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
|
@ -258,19 +266,13 @@ impl<'a> TunToProxy<'a> {
|
|||
poll.registry()
|
||||
.register(&mut exit_receiver, EXIT_TOKEN, Interest::READABLE)?;
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
let config = match tun.capabilities().medium {
|
||||
Medium::Ethernet => Config::new(smoltcp::wire::EthernetAddress([0x02, 0, 0, 0, 0, 0x01]).into()),
|
||||
Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip),
|
||||
Medium::Ieee802154 => todo!(),
|
||||
};
|
||||
#[cfg(not(target_family = "unix"))]
|
||||
let config = Config::new(smoltcp::wire::HardwareAddress::Ip);
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
let mut device = VirtualTunDevice::new(tun.capabilities());
|
||||
#[cfg(not(target_family = "unix"))]
|
||||
let mut device = VirtualTunDevice::new(DeviceCapabilities::default());
|
||||
|
||||
let gateway4: Ipv4Addr = Ipv4Addr::from_str("0.0.0.1")?;
|
||||
let gateway6: Ipv6Addr = Ipv6Addr::from_str("::1")?;
|
||||
|
@ -284,7 +286,6 @@ impl<'a> TunToProxy<'a> {
|
|||
iface.set_any_ip(true);
|
||||
|
||||
let tun = Self {
|
||||
#[cfg(target_family = "unix")]
|
||||
tun,
|
||||
poll,
|
||||
iface,
|
||||
|
|
154
src/wintuninterface.rs
Normal file
154
src/wintuninterface.rs
Normal file
|
@ -0,0 +1,154 @@
|
|||
use smoltcp::{
|
||||
phy::{self, Device, DeviceCapabilities, Medium},
|
||||
time::Instant,
|
||||
};
|
||||
use std::{
|
||||
io,
|
||||
net::{IpAddr, Ipv4Addr},
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
/// A virtual TUN (IP) interface.
|
||||
pub struct WinTunInterface {
|
||||
inner: Arc<wintun::Session>,
|
||||
mtu: usize,
|
||||
medium: Medium,
|
||||
}
|
||||
|
||||
// impl AsRawFd for WinTunInterface {
|
||||
// fn as_raw_fd(&self) -> RawFd {
|
||||
// self.inner.borrow().as_raw_fd()
|
||||
// }
|
||||
// }
|
||||
|
||||
impl WinTunInterface {
|
||||
pub fn new(name: &str, medium: Medium) -> io::Result<WinTunInterface> {
|
||||
let wintun = unsafe { wintun::load() }.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||
let tun_name = name;
|
||||
let adapter = match wintun::Adapter::open(&wintun, tun_name) {
|
||||
Ok(a) => a,
|
||||
Err(_) => wintun::Adapter::create(&wintun, tun_name, tun_name, None)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
|
||||
};
|
||||
|
||||
let address = Ipv4Addr::new(10, 1, 0, 33);
|
||||
let mask = Ipv4Addr::new(255, 255, 255, 0);
|
||||
let gateway = Some(IpAddr::V4(Ipv4Addr::new(10, 1, 0, 1)));
|
||||
adapter
|
||||
.set_network_addresses_tuple(IpAddr::V4(address), IpAddr::V4(mask), gateway)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||
|
||||
let session = adapter
|
||||
.start_session(wintun::MAX_RING_CAPACITY)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||
let inner = Arc::new(session);
|
||||
|
||||
// let inner = WinTunInterfaceDesc::new(name, medium)?;
|
||||
// let mtu = inner.interface_mtu()?;
|
||||
let mtu = 1500;
|
||||
Ok(WinTunInterface { inner, mtu, medium })
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WinTunInterface {
|
||||
fn drop(&mut self) {
|
||||
if let Err(e) = self.inner.shutdown() {
|
||||
log::error!("phy: failed to shutdown interface: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for WinTunInterface {
|
||||
type RxToken<'a> = RxToken;
|
||||
type TxToken<'a> = TxToken;
|
||||
|
||||
fn capabilities(&self) -> DeviceCapabilities {
|
||||
let mut v = DeviceCapabilities::default();
|
||||
v.max_transmission_unit = self.mtu;
|
||||
v.medium = self.medium;
|
||||
v
|
||||
}
|
||||
|
||||
fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
||||
let inner = self.inner.clone();
|
||||
match inner.receive_blocking() {
|
||||
Ok(read_pack) => Some((
|
||||
RxToken {
|
||||
buffer: read_pack.bytes().to_vec(),
|
||||
},
|
||||
TxToken { inner },
|
||||
)),
|
||||
Err(err) => {
|
||||
log::error!("phy: failed to receive packet: {}", err);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// match inner.recv(&mut buffer[..]) {
|
||||
// Ok(size) => {
|
||||
// buffer.resize(size, 0);
|
||||
// let rx = RxToken { buffer };
|
||||
// let tx = TxToken {
|
||||
// inner: self.inner.clone(),
|
||||
// };
|
||||
// Some((rx, tx))
|
||||
// }
|
||||
// Err(err) if err.kind() == io::ErrorKind::WouldBlock => None,
|
||||
// Err(err) => panic!("{}", err),
|
||||
// }
|
||||
}
|
||||
|
||||
fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
|
||||
Some(TxToken {
|
||||
inner: self.inner.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct RxToken {
|
||||
buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
impl phy::RxToken for RxToken {
|
||||
fn consume<R, F>(mut self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> R,
|
||||
{
|
||||
f(&mut self.buffer[..])
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct TxToken {
|
||||
inner: Arc<wintun::Session>,
|
||||
}
|
||||
|
||||
impl phy::TxToken for TxToken {
|
||||
fn consume<R, F>(self, len: usize, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> R,
|
||||
{
|
||||
let inner = self.inner.clone();
|
||||
let mut buffer = vec![0; len];
|
||||
let result = f(&mut buffer);
|
||||
|
||||
let write_pack = inner.allocate_send_packet(len as u16);
|
||||
if let Ok(mut write_pack) = write_pack {
|
||||
write_pack.bytes_mut().copy_from_slice(&buffer[..]);
|
||||
inner.send_packet(write_pack);
|
||||
} else if let Err(err) = write_pack {
|
||||
log::error!("phy: failed to allocate send packet: {}", err);
|
||||
}
|
||||
|
||||
// match lower.send(&buffer[..]) {
|
||||
// Ok(_) => {}
|
||||
// Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
|
||||
// log::error!("phy: tx failed due to WouldBlock")
|
||||
// }
|
||||
// Err(err) => panic!("{}", err),
|
||||
// }
|
||||
result
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue