合并tun、tap配置,减少重复代码
This commit is contained in:
@@ -1,58 +0,0 @@
|
|||||||
use crate::tun_device::{TunReader, TunWriter};
|
|
||||||
|
|
||||||
pub type TapReader = TunReader;
|
|
||||||
pub type TapWriter = TunWriter;
|
|
||||||
|
|
||||||
use std::net::Ipv4Addr;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use tun::Device;
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
pub fn create_tap(
|
|
||||||
address: Ipv4Addr,
|
|
||||||
netmask: Ipv4Addr,
|
|
||||||
gateway: Ipv4Addr,
|
|
||||||
) -> io::Result<(TunWriter, TunReader, [u8; 6])> {
|
|
||||||
println!("========TAP网卡配置========");
|
|
||||||
let mut config = tun::Configuration::default();
|
|
||||||
|
|
||||||
config
|
|
||||||
.destination(gateway)
|
|
||||||
.address(address)
|
|
||||||
.netmask(netmask)
|
|
||||||
.mtu(1420)
|
|
||||||
.layer(tun::Layer::L2)
|
|
||||||
// .queues(2) 用多个队列有兼容性问题
|
|
||||||
.up();
|
|
||||||
|
|
||||||
let dev = tun::create(&config).unwrap();
|
|
||||||
let name = dev.name();
|
|
||||||
println!("name:{:?}", name);
|
|
||||||
let packet_information = dev.has_packet_information();
|
|
||||||
let queue = dev.queue(0).unwrap();
|
|
||||||
let reader = queue.reader();
|
|
||||||
let writer = queue.writer();
|
|
||||||
let get_mac_cmd = format!("cat /sys/class/net/{}/address", name);
|
|
||||||
let mac_out = std::process::Command::new("sh")
|
|
||||||
.arg("-c")
|
|
||||||
.arg(get_mac_cmd)
|
|
||||||
.output()
|
|
||||||
.expect("sh exec error!");
|
|
||||||
if !mac_out.status.success() {
|
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, format!("获取mac地址错误: {:?}", mac_out)));
|
|
||||||
}
|
|
||||||
let mac_str = String::from_utf8(mac_out.stdout).unwrap();
|
|
||||||
let mut mac = [0; 6];
|
|
||||||
let mut split = mac_str.split(":");
|
|
||||||
for i in 0..6 {
|
|
||||||
mac[i] = u8::from_str_radix(&split.next().unwrap()[..2], 16).unwrap();
|
|
||||||
}
|
|
||||||
println!("mac:{:?}", mac);
|
|
||||||
println!("========TAP网卡配置========");
|
|
||||||
Ok((
|
|
||||||
TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
|
|
||||||
TunReader(reader, packet_information),
|
|
||||||
mac
|
|
||||||
))
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
use crate::tun_device::{TunReader, TunWriter};
|
|
||||||
|
|
||||||
pub type TapReader = TunReader;
|
|
||||||
pub type TapWriter = TunWriter;
|
|
||||||
use std::net::Ipv4Addr;
|
|
||||||
|
|
||||||
pub fn create_tap(
|
|
||||||
address: Ipv4Addr,
|
|
||||||
netmask: Ipv4Addr,
|
|
||||||
gateway: Ipv4Addr,
|
|
||||||
) -> crate::error::Result<(TapWriter, TapReader, [u8; 6])> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#[cfg(target_os = "windows")]
|
|
||||||
mod windows;
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
|
||||||
mod linux;
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
mod mac;
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
pub use mac::{TapWriter, TapReader};
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
pub use mac::create_tap;
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
|
||||||
pub use linux::{TapWriter, TapReader};
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
|
||||||
pub use linux::create_tap;
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub use windows::create_tap;
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub use windows::delete_tap;
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub use windows::{TapReader, TapWriter};
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
use std::io;
|
|
||||||
use std::net::Ipv4Addr;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
|
|
||||||
use win_tun_tap::{IFace, TapDevice};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct TapWriter(Arc<TapDevice>, Arc<Mutex<()>>);
|
|
||||||
|
|
||||||
impl TapWriter {
|
|
||||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
self.0.write(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn change_ip(
|
|
||||||
&self,
|
|
||||||
address: Ipv4Addr,
|
|
||||||
netmask: Ipv4Addr,
|
|
||||||
gateway: Ipv4Addr,
|
|
||||||
old_netmask: Ipv4Addr,
|
|
||||||
old_gateway: Ipv4Addr,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
if let Err(e) =
|
|
||||||
self.0.delete_route(dest(old_gateway, old_gateway), old_netmask, old_gateway)
|
|
||||||
{
|
|
||||||
log::warn!("{:?}", e);
|
|
||||||
}
|
|
||||||
self.0.set_ip(address, netmask)?;
|
|
||||||
self.0.add_route(dest(gateway, netmask), netmask, gateway)
|
|
||||||
}
|
|
||||||
pub fn close(&self) -> io::Result<()> {
|
|
||||||
self.0.shutdown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dest(ip: Ipv4Addr, mask: Ipv4Addr) -> Ipv4Addr {
|
|
||||||
let ip = ip.octets();
|
|
||||||
let mask = mask.octets();
|
|
||||||
Ipv4Addr::from([
|
|
||||||
ip[0] & mask[0],
|
|
||||||
ip[1] & mask[1],
|
|
||||||
ip[2] & mask[2],
|
|
||||||
ip[3] & mask[3],
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct TapReader(Arc<TapDevice>);
|
|
||||||
|
|
||||||
impl TapReader {
|
|
||||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
|
||||||
self.0.read(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const TAP_INTERFACE_NAME: &str = "Switch-Tap-V1";
|
|
||||||
|
|
||||||
pub fn create_tap(
|
|
||||||
address: Ipv4Addr,
|
|
||||||
netmask: Ipv4Addr,
|
|
||||||
gateway: Ipv4Addr,
|
|
||||||
) -> io::Result<(TapWriter, TapReader, [u8; 6])> {
|
|
||||||
println!("========TAP网卡配置========");
|
|
||||||
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
|
|
||||||
Ok(tap_device) => tap_device,
|
|
||||||
Err(e) => {
|
|
||||||
log::warn!("{:?}", e);
|
|
||||||
let tap_device = TapDevice::create()?;
|
|
||||||
tap_device.set_name(TAP_INTERFACE_NAME)?;
|
|
||||||
tap_device
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mac = tap_device.get_mac()?;
|
|
||||||
println!("name:{:?}", tap_device.get_name()?);
|
|
||||||
println!("version:{:x?}", tap_device.get_version()?);
|
|
||||||
println!("mac:{:x?}", mac);
|
|
||||||
tap_device.set_ip(address, netmask)?;
|
|
||||||
tap_device.set_metric(1)?;
|
|
||||||
tap_device.set_mtu(1420)?;
|
|
||||||
tap_device.set_status(true)?;
|
|
||||||
tap_device.add_route(address, netmask, gateway)?;
|
|
||||||
let tap = Arc::new(tap_device);
|
|
||||||
println!("========TAP网卡配置========");
|
|
||||||
Ok((
|
|
||||||
TapWriter(tap.clone(), Arc::default()),
|
|
||||||
TapReader(tap),
|
|
||||||
mac
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete_tap() {
|
|
||||||
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
|
|
||||||
Ok(tap_device) => tap_device,
|
|
||||||
Err(_) => {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let _ = tap_device.delete();
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
use std::io;
|
|
||||||
use crate::tun_device::{TunReader, TunWriter};
|
|
||||||
use std::net::Ipv4Addr;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use tun::Device;
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
pub fn create_tun(
|
|
||||||
address: Ipv4Addr,
|
|
||||||
netmask: Ipv4Addr,
|
|
||||||
gateway: Ipv4Addr,
|
|
||||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
|
||||||
) -> crate::error::Result<(TunWriter, TunReader)> {
|
|
||||||
println!("========TUN网卡配置========");
|
|
||||||
let mut config = tun::Configuration::default();
|
|
||||||
|
|
||||||
config
|
|
||||||
.destination(gateway)
|
|
||||||
.address(address)
|
|
||||||
.netmask(netmask)
|
|
||||||
.mtu(1420)
|
|
||||||
// .queues(2) 用多个队列有兼容性问题
|
|
||||||
.up();
|
|
||||||
|
|
||||||
let dev = tun::create(&config).unwrap();
|
|
||||||
let packet_information = dev.has_packet_information();
|
|
||||||
let queue = dev.queue(0).unwrap();
|
|
||||||
let reader = queue.reader();
|
|
||||||
let writer = queue.writer();
|
|
||||||
let name = dev.name();
|
|
||||||
println!("name:{:?}", name);
|
|
||||||
for (address, netmask) in in_ips {
|
|
||||||
add_route(name, address, netmask)?;
|
|
||||||
}
|
|
||||||
println!("========TUN网卡配置========");
|
|
||||||
Ok((
|
|
||||||
TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
|
|
||||||
TunReader(reader, packet_information),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
|
|
||||||
let route_add_str: String = format!(
|
|
||||||
"ip route add {:?}/{:?} dev {}",
|
|
||||||
address, netmask, name
|
|
||||||
);
|
|
||||||
let route_add_out = Command::new("sh")
|
|
||||||
.arg("-c")
|
|
||||||
.arg(route_add_str)
|
|
||||||
.output()
|
|
||||||
.expect("sh exec error!");
|
|
||||||
if !route_add_out.status.success() {
|
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", route_add_out)));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
use std::net::Ipv4Addr;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::io;
|
|
||||||
use tun::Device;
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::tun_device::{TunReader, TunWriter};
|
|
||||||
|
|
||||||
pub fn create_tun(
|
|
||||||
address: Ipv4Addr,
|
|
||||||
netmask: Ipv4Addr,
|
|
||||||
gateway: Ipv4Addr,
|
|
||||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
|
||||||
) -> crate::error::Result<(TunWriter, TunReader)> {
|
|
||||||
println!("========TUN网卡配置========");
|
|
||||||
let mut config = tun::Configuration::default();
|
|
||||||
|
|
||||||
config
|
|
||||||
.destination(gateway)
|
|
||||||
.address(address)
|
|
||||||
.netmask(netmask)
|
|
||||||
.mtu(1420)
|
|
||||||
.up();
|
|
||||||
|
|
||||||
let dev = tun::create(&config).unwrap();
|
|
||||||
let name = dev.name();
|
|
||||||
config_ip(name, address, netmask, gateway)?;
|
|
||||||
add_route(name, address, netmask)?;
|
|
||||||
for (address, netmask) in in_ips {
|
|
||||||
add_route(name, address, netmask)?;
|
|
||||||
}
|
|
||||||
let packet_information = dev.has_packet_information();
|
|
||||||
let queue = dev.queue(0).unwrap();
|
|
||||||
let reader = queue.reader();
|
|
||||||
let writer = queue.writer();
|
|
||||||
println!("name:{:?}", name);
|
|
||||||
println!("========TUN网卡配置========");
|
|
||||||
Ok((
|
|
||||||
TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
|
|
||||||
TunReader(reader, packet_information),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
|
|
||||||
let route_add_str: String = format!(
|
|
||||||
"sudo route -n add -net {:?}/{:?} -interface {}",
|
|
||||||
address, netmask, name
|
|
||||||
);
|
|
||||||
let route_add_out = Command::new("sh")
|
|
||||||
.arg("-c")
|
|
||||||
.arg(route_add_str)
|
|
||||||
.output()
|
|
||||||
.expect("sh exec error!");
|
|
||||||
if !route_add_out.status.success() {
|
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", route_add_out)));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn config_ip(name: &str, address: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
|
|
||||||
let up_eth_str: String = format!("ifconfig {} {:?} {:?} up ", name, address, gateway);
|
|
||||||
let up_eth_out = Command::new("sh")
|
|
||||||
.arg("-c")
|
|
||||||
.arg(up_eth_str)
|
|
||||||
.output()
|
|
||||||
.expect("sh exec error!");
|
|
||||||
if !up_eth_out.status.success() {
|
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: {:?}", up_eth_out)));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
|
||||||
pub use linux::create_tun;
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
pub use mac::create_tun;
|
|
||||||
#[cfg(any(unix))]
|
|
||||||
pub use unix::{TunReader, TunWriter};
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub use windows::create_tun;
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub use windows::delete_tun;
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub use windows::{TunReader, TunWriter};
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
|
||||||
pub mod linux;
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
pub mod mac;
|
|
||||||
#[cfg(any(unix))]
|
|
||||||
pub mod unix;
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub mod windows;
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
use std::io;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use bytes::BufMut;
|
|
||||||
use tun::platform::posix::{Reader, Writer};
|
|
||||||
use std::net::Ipv4Addr;
|
|
||||||
use std::os::unix::io::AsRawFd;
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
|
||||||
use tun::platform::linux::Device;
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
|
||||||
use tun::platform::macos::Device;
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct TunReader(pub(crate) Reader, pub(crate) bool);
|
|
||||||
|
|
||||||
impl TunReader {
|
|
||||||
pub fn read(&self, buf: & mut [u8]) -> io::Result<usize> {
|
|
||||||
self.0.read(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct TunWriter(pub(crate) Writer, pub(crate) bool, pub(crate) Arc<Mutex<Device>>);
|
|
||||||
|
|
||||||
impl TunWriter {
|
|
||||||
pub fn write(&self, packet: &[u8]) -> io::Result<()> {
|
|
||||||
if self.1 {
|
|
||||||
let mut buf = Vec::<u8>::with_capacity(4 + packet.len());
|
|
||||||
buf.put_u16(0);
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
|
||||||
buf.put_u16(libc::PF_INET as u16);
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
|
||||||
buf.put_u16(libc::ETH_P_IP as u16);
|
|
||||||
buf.extend_from_slice(packet);
|
|
||||||
self.0.write_all(&buf)
|
|
||||||
} else {
|
|
||||||
self.0.write_all(packet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn close(&self) -> io::Result<()>{
|
|
||||||
unsafe {
|
|
||||||
let raw = self.0.as_raw_fd();
|
|
||||||
if raw >= 0 {
|
|
||||||
libc::close(raw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
|
|
||||||
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
|
|
||||||
let mut config = tun::Configuration::default();
|
|
||||||
use tun::Device;
|
|
||||||
config
|
|
||||||
.destination(gateway)
|
|
||||||
.address(address)
|
|
||||||
.netmask(netmask)
|
|
||||||
.mtu(1420)
|
|
||||||
// .queues(2)
|
|
||||||
.up();
|
|
||||||
let mut dev = self.2.lock();
|
|
||||||
if let Err(e) = dev.configure(&config) {
|
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
|
|
||||||
}
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
if let Err(e) = crate::tun_device::mac::config_ip(dev.name(), address, netmask, gateway){
|
|
||||||
log::error!("{}",e);
|
|
||||||
}
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
use std::{io, thread};
|
|
||||||
use std::net::Ipv4Addr;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use libloading::Library;
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
|
|
||||||
use win_tun_tap::{IFace, TunDevice};
|
|
||||||
use win_tun_tap::packet::TunPacket;
|
|
||||||
|
|
||||||
pub const TUN_INTERFACE_NAME: &str = "Switch-V1";
|
|
||||||
pub const TUN_POOL_NAME: &str = "Switch-V1";
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct TunWriter(Arc<TunDevice>, Arc<Mutex<()>>);
|
|
||||||
|
|
||||||
impl TunWriter {
|
|
||||||
pub fn write(&self, buf: &[u8]) -> io::Result<()> {
|
|
||||||
let mut packet = self.0.allocate_send_packet(buf.len() as u16)?;
|
|
||||||
packet.bytes_mut().copy_from_slice(buf);
|
|
||||||
self.0.send_packet(packet);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
pub fn change_ip(
|
|
||||||
&self,
|
|
||||||
address: Ipv4Addr,
|
|
||||||
netmask: Ipv4Addr,
|
|
||||||
gateway: Ipv4Addr,
|
|
||||||
old_netmask: Ipv4Addr,
|
|
||||||
old_gateway: Ipv4Addr,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
if let Err(e) =
|
|
||||||
self.0.delete_route(dest(old_gateway, old_gateway), old_netmask, old_gateway)
|
|
||||||
{
|
|
||||||
log::warn!("{:?}", e);
|
|
||||||
}
|
|
||||||
self.0.set_ip(address, netmask)?;
|
|
||||||
self.0.add_route(dest(gateway, netmask), netmask, gateway)
|
|
||||||
}
|
|
||||||
pub fn close(&self) -> io::Result<()> {
|
|
||||||
self.0.shutdown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dest(ip: Ipv4Addr, mask: Ipv4Addr) -> Ipv4Addr {
|
|
||||||
let ip = ip.octets();
|
|
||||||
let mask = mask.octets();
|
|
||||||
Ipv4Addr::from([
|
|
||||||
ip[0] & mask[0],
|
|
||||||
ip[1] & mask[1],
|
|
||||||
ip[2] & mask[2],
|
|
||||||
ip[3] & mask[3],
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct TunReader(Arc<TunDevice>);
|
|
||||||
|
|
||||||
|
|
||||||
impl TunReader {
|
|
||||||
pub fn next(&self) -> io::Result<TunPacket> {
|
|
||||||
self.0.receive_blocking()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_tun(
|
|
||||||
address: Ipv4Addr,
|
|
||||||
netmask: Ipv4Addr,
|
|
||||||
gateway: Ipv4Addr,
|
|
||||||
in_ips:Vec<(Ipv4Addr,Ipv4Addr)>
|
|
||||||
) -> io::Result<(TunWriter, TunReader)> {
|
|
||||||
unsafe {
|
|
||||||
println!("========TUN网卡配置========");
|
|
||||||
match Library::new("wintun.dll") {
|
|
||||||
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
|
|
||||||
Ok(_) => {
|
|
||||||
thread::sleep(Duration::from_millis(5));
|
|
||||||
}
|
|
||||||
Err(_) => {}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("wintun.dll not found");
|
|
||||||
return Err(io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("wintun.dll not found {:?}", e),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let tun_device = match TunDevice::create(
|
|
||||||
Library::new("wintun.dll").unwrap(),
|
|
||||||
TUN_POOL_NAME,
|
|
||||||
TUN_INTERFACE_NAME,
|
|
||||||
) {
|
|
||||||
Ok(tun_device) => tun_device,
|
|
||||||
Err(_) => {
|
|
||||||
thread::sleep(Duration::from_millis(200));
|
|
||||||
match TunDevice::create(
|
|
||||||
Library::new("wintun.dll").unwrap(),
|
|
||||||
TUN_POOL_NAME,
|
|
||||||
TUN_INTERFACE_NAME,
|
|
||||||
) {
|
|
||||||
Ok(tun_device) => tun_device,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("{:?}", e),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
println!("name:{:?}", tun_device.get_name()?);
|
|
||||||
println!("version:{:?}", tun_device.version()?);
|
|
||||||
tun_device.set_ip(address, netmask)?;
|
|
||||||
tun_device.set_metric(1)?;
|
|
||||||
tun_device.set_mtu(1420)?;
|
|
||||||
for (address, netmask) in in_ips {
|
|
||||||
tun_device.add_route(address, netmask, gateway)?;
|
|
||||||
}
|
|
||||||
tun_device.add_route(address, netmask, gateway)?;
|
|
||||||
let device = Arc::new(tun_device);
|
|
||||||
println!("========TUN网卡配置========");
|
|
||||||
Ok((
|
|
||||||
TunWriter(device.clone(), Arc::default()),
|
|
||||||
TunReader(device),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete_tun() {
|
|
||||||
unsafe {
|
|
||||||
match Library::new("wintun.dll") {
|
|
||||||
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
|
|
||||||
Ok(_) => {
|
|
||||||
}
|
|
||||||
Err(_) => {}
|
|
||||||
},
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
use crate::tun_tap_device::{DeviceReader, DeviceType, DeviceWriter};
|
||||||
|
use tun::Device;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use crate::tun_tap_device::unix::DeviceW;
|
||||||
|
|
||||||
|
impl DeviceWriter {
|
||||||
|
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
|
||||||
|
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
|
||||||
|
let mut config = tun::Configuration::default();
|
||||||
|
config
|
||||||
|
.destination(gateway)
|
||||||
|
.address(address)
|
||||||
|
.netmask(netmask)
|
||||||
|
.mtu(1420)
|
||||||
|
// .queues(2)
|
||||||
|
.up();
|
||||||
|
let mut dev = self.lock.lock();
|
||||||
|
if let Err(e) = dev.configure(&config) {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
let name = dev.name();
|
||||||
|
for (address, netmask) in &self.in_ips {
|
||||||
|
add_route(name, *address, *netmask)?;
|
||||||
|
}
|
||||||
|
// 当前网段路由
|
||||||
|
// add_route(name, address, netmask)?;
|
||||||
|
// 广播和组播路由
|
||||||
|
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||||
|
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
|
||||||
|
let route_add_str: String = format!(
|
||||||
|
"ip route add {:?}/{:?} dev {}",
|
||||||
|
address, netmask, name
|
||||||
|
);
|
||||||
|
let route_add_out = Command::new("sh")
|
||||||
|
.arg("-c")
|
||||||
|
.arg(&route_add_str)
|
||||||
|
.output()
|
||||||
|
.expect("sh exec error!");
|
||||||
|
if !route_add_out.status.success() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: cmd:{},out:{:?}", route_add_str, route_add_out)));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_device(device_type: DeviceType,
|
||||||
|
address: Ipv4Addr,
|
||||||
|
netmask: Ipv4Addr,
|
||||||
|
gateway: Ipv4Addr,
|
||||||
|
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||||
|
) -> io::Result<(DeviceWriter, DeviceReader)> {
|
||||||
|
println!("========网卡配置========");
|
||||||
|
let mut config = tun::Configuration::default();
|
||||||
|
|
||||||
|
config
|
||||||
|
.destination(gateway)
|
||||||
|
.address(address)
|
||||||
|
.netmask(netmask)
|
||||||
|
.mtu(1420)
|
||||||
|
// .queues(2) 用多个队列有兼容性问题
|
||||||
|
.up();
|
||||||
|
match device_type {
|
||||||
|
DeviceType::Tun => {}
|
||||||
|
DeviceType::Tap => {
|
||||||
|
config.layer(tun::Layer::L2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let dev = tun::create(&config).unwrap();
|
||||||
|
let packet_information = dev.has_packet_information();
|
||||||
|
let queue = dev.queue(0).unwrap();
|
||||||
|
let reader = queue.reader();
|
||||||
|
let writer = queue.writer();
|
||||||
|
let name = dev.name();
|
||||||
|
println!("name:{:?}", name);
|
||||||
|
for (address, netmask) in &in_ips {
|
||||||
|
add_route(name, *address, *netmask)?;
|
||||||
|
}
|
||||||
|
// 当前网段路由
|
||||||
|
// add_route(name, address, netmask)?;
|
||||||
|
// 广播和组播路由
|
||||||
|
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||||
|
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||||
|
let device_w = match device_type {
|
||||||
|
DeviceType::Tun => {
|
||||||
|
DeviceW::Tun(writer)
|
||||||
|
}
|
||||||
|
DeviceType::Tap => {
|
||||||
|
let get_mac_cmd = format!("cat /sys/class/net/{}/address", name);
|
||||||
|
let mac_out = Command::new("sh")
|
||||||
|
.arg("-c")
|
||||||
|
.arg(get_mac_cmd)
|
||||||
|
.output()
|
||||||
|
.expect("sh exec error!");
|
||||||
|
if !mac_out.status.success() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, format!("获取mac地址错误: {:?}", mac_out)));
|
||||||
|
}
|
||||||
|
let mac_str = String::from_utf8(mac_out.stdout).unwrap();
|
||||||
|
let mut mac = [0; 6];
|
||||||
|
let mut split = mac_str.split(":");
|
||||||
|
for i in 0..6 {
|
||||||
|
mac[i] = u8::from_str_radix(&split.next().unwrap()[..2], 16).unwrap();
|
||||||
|
}
|
||||||
|
DeviceW::Tap((writer, mac))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
println!("========TUN网卡配置========");
|
||||||
|
Ok((
|
||||||
|
DeviceWriter::new(device_w, Arc::new(Mutex::new(dev)), in_ips, address, packet_information),
|
||||||
|
DeviceReader::new(reader),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_device(_device_type: DeviceType) {}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
use crate::tun_tap_device::{DeviceReader, DeviceType, DeviceWriter};
|
||||||
|
use tun::Device;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use crate::tun_tap_device::unix::DeviceW;
|
||||||
|
|
||||||
|
impl DeviceWriter {
|
||||||
|
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
|
||||||
|
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
|
||||||
|
let mut config = tun::Configuration::default();
|
||||||
|
config
|
||||||
|
.destination(gateway)
|
||||||
|
.address(address)
|
||||||
|
.netmask(netmask)
|
||||||
|
.mtu(1420)
|
||||||
|
.up();
|
||||||
|
let mut dev = self.lock.lock();
|
||||||
|
if let Err(e) = dev.configure(&config) {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
if let Err(e) = config_ip(dev.name(), address, netmask, gateway) {
|
||||||
|
log::error!("{}",e);
|
||||||
|
}
|
||||||
|
let name = dev.name();
|
||||||
|
for (address, netmask) in &self.in_ips {
|
||||||
|
add_route(name, *address, *netmask)?;
|
||||||
|
}
|
||||||
|
// 当前网段路由
|
||||||
|
add_route(name, address, netmask)?;
|
||||||
|
// 广播和组播路由
|
||||||
|
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||||
|
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_device(device_type: DeviceType,
|
||||||
|
address: Ipv4Addr,
|
||||||
|
netmask: Ipv4Addr,
|
||||||
|
gateway: Ipv4Addr,
|
||||||
|
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||||
|
) -> io::Result<(DeviceWriter, DeviceReader)> {
|
||||||
|
match device_type {
|
||||||
|
DeviceType::Tun => {}
|
||||||
|
DeviceType::Tap => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("========TUN网卡配置========");
|
||||||
|
let mut config = tun::Configuration::default();
|
||||||
|
|
||||||
|
config
|
||||||
|
.destination(gateway)
|
||||||
|
.address(address)
|
||||||
|
.netmask(netmask)
|
||||||
|
.mtu(1420)
|
||||||
|
.up();
|
||||||
|
|
||||||
|
let dev = tun::create(&config).unwrap();
|
||||||
|
let name = dev.name();
|
||||||
|
config_ip(name, address, netmask, gateway)?;
|
||||||
|
for (address, netmask) in &in_ips {
|
||||||
|
add_route(name, *address, *netmask)?;
|
||||||
|
}
|
||||||
|
// 当前网段路由
|
||||||
|
add_route(name, address, netmask)?;
|
||||||
|
// 广播和组播路由
|
||||||
|
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||||
|
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||||
|
let packet_information = dev.has_packet_information();
|
||||||
|
let queue = dev.queue(0).unwrap();
|
||||||
|
let reader = queue.reader();
|
||||||
|
let writer = queue.writer();
|
||||||
|
println!("name:{:?}", name);
|
||||||
|
println!("========TUN网卡配置========");
|
||||||
|
Ok((
|
||||||
|
DeviceWriter::new(DeviceW::Tun(writer), Arc::new(Mutex::new(dev)), in_ips, address, packet_information),
|
||||||
|
DeviceReader::new(reader),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
|
||||||
|
let route_add_str: String = format!(
|
||||||
|
"sudo route -n add -net {:?}/{:?} -interface {}",
|
||||||
|
address, netmask, name
|
||||||
|
);
|
||||||
|
let route_add_out = Command::new("sh")
|
||||||
|
.arg("-c")
|
||||||
|
.arg(&route_add_str)
|
||||||
|
.output()
|
||||||
|
.expect("sh exec error!");
|
||||||
|
if !route_add_out.status.success() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: cmd:{},out:{:?}", route_add_str, route_add_out)));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn config_ip(name: &str, address: Ipv4Addr, _netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
|
||||||
|
let up_eth_str: String = format!("ifconfig {} {:?} {:?} up ", name, address, gateway);
|
||||||
|
let up_eth_out = Command::new("sh")
|
||||||
|
.arg("-c")
|
||||||
|
.arg(&up_eth_str)
|
||||||
|
.output()
|
||||||
|
.expect("sh exec error!");
|
||||||
|
if !up_eth_out.status.success() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: cmd:{},out:{:?}", up_eth_str, up_eth_out)));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_device(_device_type: DeviceType) {}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub mod windows;
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
pub mod linux;
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
pub mod mac;
|
||||||
|
#[cfg(any(unix))]
|
||||||
|
pub mod unix;
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
pub use linux::create_device;
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
pub use linux::delete_device;
|
||||||
|
#[cfg(any(unix))]
|
||||||
|
pub use unix::{DeviceWriter, DeviceReader};
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
pub use mac::create_device;
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
pub use mac::delete_device;
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub use windows::create_device;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub use windows::delete_device;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub use windows::{DeviceWriter, DeviceReader};
|
||||||
|
|
||||||
|
pub enum DeviceType {
|
||||||
|
Tun,
|
||||||
|
Tap,
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use bytes::BufMut;
|
||||||
|
use tun::platform::posix::{Reader, Writer};
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use crossbeam::atomic::AtomicCell;
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
use tun::platform::linux::Device;
|
||||||
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
|
use tun::platform::macos::Device;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use packet::ethernet;
|
||||||
|
|
||||||
|
use packet::ethernet::packet::EthernetPacket;
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum DeviceW {
|
||||||
|
Tun(Writer),
|
||||||
|
Tap((Writer, [u8; 6])),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceW {
|
||||||
|
pub fn is_tun(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
DeviceW::Tun(_) => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
DeviceW::Tap(_) => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DeviceWriter {
|
||||||
|
writer: DeviceW,
|
||||||
|
pub lock: Arc<Mutex<Device>>,
|
||||||
|
pub in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||||
|
ip: Arc<AtomicCell<Ipv4Addr>>,
|
||||||
|
packet_information: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceWriter {
|
||||||
|
pub fn new(writer: DeviceW,lock: Arc<Mutex<Device>>, in_ips: Vec<(Ipv4Addr, Ipv4Addr)>, ip: Ipv4Addr, packet_information: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
writer,
|
||||||
|
lock,
|
||||||
|
in_ips,
|
||||||
|
ip: Arc::new(AtomicCell::new(ip)),
|
||||||
|
packet_information,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceWriter {
|
||||||
|
pub fn write(packet_information: bool, writer: &Writer, packet: &[u8]) -> io::Result<()> {
|
||||||
|
if packet_information {
|
||||||
|
let mut buf = Vec::<u8>::with_capacity(4 + packet.len());
|
||||||
|
buf.put_u16(0);
|
||||||
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
|
buf.put_u16(libc::PF_INET as u16);
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
buf.put_u16(libc::ETH_P_IP as u16);
|
||||||
|
buf.extend_from_slice(packet);
|
||||||
|
writer.write_all(&buf)
|
||||||
|
} else {
|
||||||
|
writer.write_all(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///tun网卡写入ipv4数据
|
||||||
|
pub fn write_ipv4_tun(&self, buf: &[u8]) -> io::Result<()> {
|
||||||
|
match &self.writer {
|
||||||
|
DeviceW::Tun(writer) => {
|
||||||
|
Self::write(self.packet_information, writer, buf)
|
||||||
|
}
|
||||||
|
DeviceW::Tap(_) => {
|
||||||
|
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// tap网卡写入以太网帧
|
||||||
|
pub fn write_ethernet_tap(&self, buf: &[u8]) -> io::Result<()> {
|
||||||
|
match &self.writer {
|
||||||
|
DeviceW::Tun(_) => {
|
||||||
|
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||||
|
}
|
||||||
|
DeviceW::Tap((writer, _)) => {
|
||||||
|
Self::write(self.packet_information, writer, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///写入ipv4数据,头部必须留14字节,给tap写入以太网帧头
|
||||||
|
pub fn write_ipv4(&self, buf: &mut [u8]) -> io::Result<()> {
|
||||||
|
match &self.writer {
|
||||||
|
DeviceW::Tun(writer) => {
|
||||||
|
Self::write(self.packet_information, writer, &buf[14..])
|
||||||
|
}
|
||||||
|
DeviceW::Tap((writer, mac)) => {
|
||||||
|
let source_mac = [buf[14 + 12], buf[14 + 13], buf[14 + 14], buf[14 + 15], 123, 234];
|
||||||
|
let mut ethernet_packet = EthernetPacket::unchecked(buf);
|
||||||
|
ethernet_packet.set_source(&source_mac);
|
||||||
|
ethernet_packet.set_destination(mac);
|
||||||
|
ethernet_packet.set_protocol(ethernet::protocol::Protocol::Ipv4);
|
||||||
|
Self::write(self.packet_information, writer, ðernet_packet.buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn ip(&self) -> Ipv4Addr {
|
||||||
|
self.ip.load()
|
||||||
|
}
|
||||||
|
pub fn close(&self) -> io::Result<()> {
|
||||||
|
unsafe {
|
||||||
|
match &self.writer {
|
||||||
|
DeviceW::Tun(writer) => {
|
||||||
|
libc::close(writer.as_raw_fd());
|
||||||
|
}
|
||||||
|
DeviceW::Tap((writer, _)) => {
|
||||||
|
libc::close(writer.as_raw_fd());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn is_tun(&self) -> bool {
|
||||||
|
self.writer.is_tun()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DeviceReader(Reader);
|
||||||
|
|
||||||
|
impl DeviceReader {
|
||||||
|
pub fn new(device: Reader) -> Self {
|
||||||
|
DeviceReader(device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceReader {
|
||||||
|
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
self.0.read(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,349 @@
|
|||||||
|
use std::{io, thread};
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
use crossbeam::atomic::AtomicCell;
|
||||||
|
use libloading::Library;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use packet::ethernet;
|
||||||
|
use packet::ethernet::packet::EthernetPacket;
|
||||||
|
use win_tun_tap::{IFace, TapDevice, TunDevice};
|
||||||
|
use crate::tun_tap_device::DeviceType;
|
||||||
|
|
||||||
|
pub const TUN_INTERFACE_NAME: &str = "Switch-Tun-V1";
|
||||||
|
pub const TUN_POOL_NAME: &str = "Switch-Tun-V1";
|
||||||
|
pub const TAP_INTERFACE_NAME: &str = "Switch-Tap-V1";
|
||||||
|
|
||||||
|
pub enum Device {
|
||||||
|
Tun(TunDevice),
|
||||||
|
Tap((TapDevice, [u8; 6])),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Device {
|
||||||
|
pub fn is_tun(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Device::Tun(_) => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Device::Tap(_) => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DeviceWriter {
|
||||||
|
device: Arc<Device>,
|
||||||
|
lock: Arc<Mutex<()>>,
|
||||||
|
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||||
|
ip: Arc<AtomicCell<Ipv4Addr>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceWriter {
|
||||||
|
pub fn new(device: Arc<Device>, in_ips: Vec<(Ipv4Addr, Ipv4Addr)>, ip: Ipv4Addr) -> Self {
|
||||||
|
Self {
|
||||||
|
device,
|
||||||
|
lock: Arc::new(Default::default()),
|
||||||
|
in_ips,
|
||||||
|
ip: Arc::new(AtomicCell::new(ip)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceWriter {
|
||||||
|
///tun网卡写入ipv4数据
|
||||||
|
pub fn write_ipv4_tun(&self, buf: &[u8]) -> io::Result<()> {
|
||||||
|
match self.device.as_ref() {
|
||||||
|
Device::Tun(dev) => {
|
||||||
|
let mut packet = dev.allocate_send_packet(buf.len() as u16)?;
|
||||||
|
packet.bytes_mut().copy_from_slice(buf);
|
||||||
|
dev.send_packet(packet);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Device::Tap(_) => {
|
||||||
|
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// tap网卡写入以太网帧
|
||||||
|
pub fn write_ethernet_tap(&self, buf: &[u8]) -> io::Result<()> {
|
||||||
|
match self.device.as_ref() {
|
||||||
|
Device::Tun(_) => {
|
||||||
|
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||||
|
}
|
||||||
|
Device::Tap((dev, _)) => {
|
||||||
|
dev.write(buf)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///写入ipv4数据,头部必须留14字节,给tap写入以太网帧头
|
||||||
|
pub fn write_ipv4(&self, buf: &mut [u8]) -> io::Result<()> {
|
||||||
|
match self.device.as_ref() {
|
||||||
|
Device::Tun(dev) => {
|
||||||
|
let mut packet = dev.allocate_send_packet((buf.len() - 14) as u16)?;
|
||||||
|
packet.bytes_mut().copy_from_slice(&buf[14..]);
|
||||||
|
dev.send_packet(packet);
|
||||||
|
}
|
||||||
|
Device::Tap((dev, mac)) => {
|
||||||
|
let source_mac = [buf[14 + 12], buf[14 + 13], buf[14 + 14], buf[14 + 15], 123, 234];
|
||||||
|
let mut ethernet_packet = EthernetPacket::unchecked(buf);
|
||||||
|
ethernet_packet.set_source(&source_mac);
|
||||||
|
ethernet_packet.set_destination(mac);
|
||||||
|
ethernet_packet.set_protocol(ethernet::protocol::Protocol::Ipv4);
|
||||||
|
dev.write(ðernet_packet.buffer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn change_ip(
|
||||||
|
&self,
|
||||||
|
address: Ipv4Addr,
|
||||||
|
netmask: Ipv4Addr,
|
||||||
|
gateway: Ipv4Addr,
|
||||||
|
old_netmask: Ipv4Addr,
|
||||||
|
old_gateway: Ipv4Addr,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
let _guard = self.lock.lock();
|
||||||
|
let dev: &dyn IFace = match self.device.as_ref() {
|
||||||
|
Device::Tun(dev) => {
|
||||||
|
dev as &dyn IFace
|
||||||
|
}
|
||||||
|
Device::Tap((dev, _)) => {
|
||||||
|
dev as &dyn IFace
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Err(e) =
|
||||||
|
dev.delete_route(dest(old_gateway, old_gateway), old_netmask, old_gateway)
|
||||||
|
{
|
||||||
|
log::warn!("{:?}", e);
|
||||||
|
}
|
||||||
|
dev.set_ip(address, netmask)?;
|
||||||
|
self.ip.store(address);
|
||||||
|
for (address, netmask) in &self.in_ips {
|
||||||
|
dev.add_route(*address, *netmask, gateway, 1)?;
|
||||||
|
}
|
||||||
|
// 当前网段路由
|
||||||
|
dev.add_route(address, netmask, gateway, 1)?;
|
||||||
|
// 广播和组播路由
|
||||||
|
dev.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||||
|
dev.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)
|
||||||
|
}
|
||||||
|
pub fn ip(&self) -> Ipv4Addr {
|
||||||
|
self.ip.load()
|
||||||
|
}
|
||||||
|
pub fn close(&self) -> io::Result<()> {
|
||||||
|
match self.device.as_ref() {
|
||||||
|
Device::Tun(dev) => {
|
||||||
|
dev.shutdown()
|
||||||
|
}
|
||||||
|
Device::Tap((dev, _)) => {
|
||||||
|
dev.shutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn is_tun(&self) -> bool {
|
||||||
|
self.device.is_tun()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dest(ip: Ipv4Addr, mask: Ipv4Addr) -> Ipv4Addr {
|
||||||
|
let ip = ip.octets();
|
||||||
|
let mask = mask.octets();
|
||||||
|
Ipv4Addr::from([
|
||||||
|
ip[0] & mask[0],
|
||||||
|
ip[1] & mask[1],
|
||||||
|
ip[2] & mask[2],
|
||||||
|
ip[3] & mask[3],
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DeviceReader {
|
||||||
|
device: Arc<Device>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceReader {
|
||||||
|
pub fn new(device: Arc<Device>) -> Self {
|
||||||
|
Self {
|
||||||
|
device,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceReader {
|
||||||
|
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
match self.device.as_ref() {
|
||||||
|
Device::Tun(dev) => {
|
||||||
|
let packet = dev.receive_blocking()?;
|
||||||
|
let packet = packet.bytes();
|
||||||
|
let len = packet.len();
|
||||||
|
if len > buf.len() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::InvalidData, "data too long"));
|
||||||
|
}
|
||||||
|
buf[..len].copy_from_slice(packet);
|
||||||
|
Ok(len)
|
||||||
|
}
|
||||||
|
Device::Tap((dev, _)) => {
|
||||||
|
dev.read(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_tun(
|
||||||
|
address: Ipv4Addr,
|
||||||
|
netmask: Ipv4Addr,
|
||||||
|
gateway: Ipv4Addr,
|
||||||
|
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||||
|
) -> io::Result<(DeviceWriter, DeviceReader)> {
|
||||||
|
unsafe {
|
||||||
|
println!("========TUN网卡配置========");
|
||||||
|
match Library::new("wintun.dll") {
|
||||||
|
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
|
||||||
|
Ok(_) => {
|
||||||
|
thread::sleep(Duration::from_millis(5));
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("wintun.dll not found");
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("wintun.dll not found {:?}", e),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let tun_device = match TunDevice::create(
|
||||||
|
Library::new("wintun.dll").unwrap(),
|
||||||
|
TUN_POOL_NAME,
|
||||||
|
TUN_INTERFACE_NAME,
|
||||||
|
) {
|
||||||
|
Ok(tun_device) => tun_device,
|
||||||
|
Err(_) => {
|
||||||
|
thread::sleep(Duration::from_millis(200));
|
||||||
|
match TunDevice::create(
|
||||||
|
Library::new("wintun.dll").unwrap(),
|
||||||
|
TUN_POOL_NAME,
|
||||||
|
TUN_INTERFACE_NAME,
|
||||||
|
) {
|
||||||
|
Ok(tun_device) => tun_device,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("{:?}", e),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
println!("name:{:?}", tun_device.get_name()?);
|
||||||
|
println!("version:{:?}", tun_device.version()?);
|
||||||
|
tun_device.set_ip(address, netmask)?;
|
||||||
|
tun_device.set_metric(1)?;
|
||||||
|
tun_device.set_mtu(1420)?;
|
||||||
|
// ip代理路由
|
||||||
|
for (address, netmask) in &in_ips {
|
||||||
|
tun_device.add_route(*address, *netmask, gateway, 1)?;
|
||||||
|
}
|
||||||
|
// 当前网段路由
|
||||||
|
tun_device.add_route(address, netmask, gateway, 1)?;
|
||||||
|
// 广播和组播路由
|
||||||
|
tun_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||||
|
tun_device.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)?;
|
||||||
|
let device = Arc::new(Device::Tun(tun_device));
|
||||||
|
println!("========TUN网卡配置========");
|
||||||
|
Ok((
|
||||||
|
DeviceWriter::new(device.clone(), in_ips, address),
|
||||||
|
DeviceReader::new(device),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_tun() {
|
||||||
|
unsafe {
|
||||||
|
match Library::new("wintun.dll") {
|
||||||
|
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(_) => {}
|
||||||
|
},
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_tap(
|
||||||
|
address: Ipv4Addr,
|
||||||
|
netmask: Ipv4Addr,
|
||||||
|
gateway: Ipv4Addr,
|
||||||
|
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||||
|
) -> io::Result<(DeviceWriter, DeviceReader)> {
|
||||||
|
println!("========TAP网卡配置========");
|
||||||
|
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
|
||||||
|
Ok(tap_device) => tap_device,
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("{:?}", e);
|
||||||
|
let tap_device = TapDevice::create()?;
|
||||||
|
tap_device.set_name(TAP_INTERFACE_NAME)?;
|
||||||
|
tap_device
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mac = tap_device.get_mac()?;
|
||||||
|
println!("name:{:?}", tap_device.get_name()?);
|
||||||
|
println!("version:{:x?}", tap_device.get_version()?);
|
||||||
|
println!("mac:{:x?}", mac);
|
||||||
|
tap_device.set_ip(address, netmask)?;
|
||||||
|
tap_device.set_metric(1)?;
|
||||||
|
tap_device.set_mtu(1420)?;
|
||||||
|
tap_device.set_status(true)?;
|
||||||
|
tap_device.add_route(address, netmask, gateway, 1)?;
|
||||||
|
for (address, netmask) in &in_ips {
|
||||||
|
tap_device.add_route(*address, *netmask, gateway, 1)?;
|
||||||
|
}
|
||||||
|
// 广播和组播路由
|
||||||
|
tap_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||||
|
tap_device.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)?;
|
||||||
|
let tap = Arc::new(Device::Tap((tap_device, mac)));
|
||||||
|
println!("========TAP网卡配置========");
|
||||||
|
Ok((
|
||||||
|
DeviceWriter::new(tap.clone(), in_ips, address),
|
||||||
|
DeviceReader::new(tap)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_tap() {
|
||||||
|
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
|
||||||
|
Ok(tap_device) => tap_device,
|
||||||
|
Err(_) => {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _ = tap_device.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_device(device_type: DeviceType, address: Ipv4Addr,
|
||||||
|
netmask: Ipv4Addr,
|
||||||
|
gateway: Ipv4Addr,
|
||||||
|
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>, ) -> io::Result<(DeviceWriter, DeviceReader)> {
|
||||||
|
match device_type {
|
||||||
|
DeviceType::Tun => {
|
||||||
|
create_tun(address, netmask, gateway, in_ips)
|
||||||
|
}
|
||||||
|
DeviceType::Tap => {
|
||||||
|
create_tap(address, netmask, gateway, in_ips)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_device(device_type: DeviceType) {
|
||||||
|
match device_type {
|
||||||
|
DeviceType::Tun => {
|
||||||
|
delete_tun()
|
||||||
|
}
|
||||||
|
DeviceType::Tap => {
|
||||||
|
delete_tap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user