mirror of
https://github.com/tun2proxy/tun2proxy.git
synced 2025-04-23 15:29:10 +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"
|
serial_test = "2.0"
|
||||||
test-log = "0.2"
|
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 tuntapinterfacedesc;
|
||||||
mod virtdevice;
|
mod virtdevice;
|
||||||
mod virtdns;
|
mod virtdns;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
mod wintuninterface;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Proxy {
|
pub struct Proxy {
|
||||||
|
|
|
@ -6,16 +6,17 @@ use crate::{dns, error::Error, error::Result, virtdevice::VirtualTunDevice, Netw
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
use mio::unix::SourceFd;
|
use mio::unix::SourceFd;
|
||||||
use mio::{event::Event, net::TcpStream, net::UdpSocket, Events, Interest, Poll, Token};
|
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"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
use smoltcp::phy::RawSocket;
|
use smoltcp::phy::RawSocket;
|
||||||
// #[cfg(any(target_os = "linux", target_os = "android"))]
|
// #[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
// use smoltcp::phy::TunTapInterface;
|
// use smoltcp::phy::TunTapInterface;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use crate::wintuninterface::WinTunInterface;
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
use smoltcp::phy::{Device, Medium, RxToken, TxToken};
|
use smoltcp::phy::{RxToken, TxToken};
|
||||||
use smoltcp::{
|
use smoltcp::{
|
||||||
iface::{Config, Interface, SocketHandle, SocketSet},
|
iface::{Config, Interface, SocketHandle, SocketSet},
|
||||||
|
phy::{Device, Medium},
|
||||||
socket::{tcp, tcp::State, udp, udp::UdpMetadata},
|
socket::{tcp, tcp::State, udp, udp::UdpMetadata},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
wire::{IpCidr, IpProtocol, Ipv4Packet, Ipv6Packet, TcpPacket, UdpPacket, UDP_HEADER_LEN},
|
wire::{IpCidr, IpProtocol, Ipv4Packet, Ipv6Packet, TcpPacket, UdpPacket, UDP_HEADER_LEN},
|
||||||
|
@ -217,6 +218,8 @@ pub struct TunToProxy<'a> {
|
||||||
tun: TunTapInterface,
|
tun: TunTapInterface,
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
tun: RawSocket,
|
tun: RawSocket,
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
tun: WinTunInterface,
|
||||||
poll: Poll,
|
poll: Poll,
|
||||||
iface: Interface,
|
iface: Interface,
|
||||||
connection_map: HashMap<ConnectionInfo, ConnectionState>,
|
connection_map: HashMap<ConnectionInfo, ConnectionState>,
|
||||||
|
@ -246,6 +249,11 @@ impl<'a> TunToProxy<'a> {
|
||||||
NetworkInterface::Fd(_fd) => panic!("Not supported"),
|
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()?;
|
let poll = Poll::new()?;
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
|
@ -258,19 +266,13 @@ impl<'a> TunToProxy<'a> {
|
||||||
poll.registry()
|
poll.registry()
|
||||||
.register(&mut exit_receiver, EXIT_TOKEN, Interest::READABLE)?;
|
.register(&mut exit_receiver, EXIT_TOKEN, Interest::READABLE)?;
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
let config = match tun.capabilities().medium {
|
let config = match tun.capabilities().medium {
|
||||||
Medium::Ethernet => Config::new(smoltcp::wire::EthernetAddress([0x02, 0, 0, 0, 0, 0x01]).into()),
|
Medium::Ethernet => Config::new(smoltcp::wire::EthernetAddress([0x02, 0, 0, 0, 0, 0x01]).into()),
|
||||||
Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip),
|
Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip),
|
||||||
Medium::Ieee802154 => todo!(),
|
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());
|
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 gateway4: Ipv4Addr = Ipv4Addr::from_str("0.0.0.1")?;
|
||||||
let gateway6: Ipv6Addr = Ipv6Addr::from_str("::1")?;
|
let gateway6: Ipv6Addr = Ipv6Addr::from_str("::1")?;
|
||||||
|
@ -284,7 +286,6 @@ impl<'a> TunToProxy<'a> {
|
||||||
iface.set_any_ip(true);
|
iface.set_any_ip(true);
|
||||||
|
|
||||||
let tun = Self {
|
let tun = Self {
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
tun,
|
tun,
|
||||||
poll,
|
poll,
|
||||||
iface,
|
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