5 个版本 (3 个稳定)

1.1.1 2024年8月7日
1.0.0 2024年8月7日
0.7.1 2024年7月14日
0.6.1 2024年6月2日

#333网络编程

Download history 240/week @ 2024-05-29 219/week @ 2024-06-05 25/week @ 2024-06-12 9/week @ 2024-06-26 247/week @ 2024-07-03 238/week @ 2024-07-10 99/week @ 2024-07-17 159/week @ 2024-07-24 283/week @ 2024-07-31 792/week @ 2024-08-07

每月下载 1,357
easytier 中使用

WTFPL 许可证

150KB
3.5K SLoC

TUN 接口

Crates.io tun2 WTFPL

这个crate允许创建和使用TUN接口,目标是使其跨平台。

由于原始维护者@meh已不再有兴趣继续维护tunrepo,我们(@ssrlive, @xmh0511)创建了tun2分支仓库并继续积极更新。欢迎任何感兴趣的贡献者。如果您想成为tun2的共同贡献者和发布者,请在issues中与我联系。

对我来说,提交的PR已经很长时间没有审查,无法合并到主分支,也无法发布。这就像一个手术台上长时间未被缝合的病人。这是一种糟糕的经历。我相信很多人都有同样的感受。

使用方法

首先,将以下内容添加到您的 Cargo.toml

[dependencies]
tun2 = "2"

如果您想使用mio/tokio的TUN接口,您需要启用async功能

[dependencies]
tun2 = { version = "2", features = ["async"] }

示例

以下示例创建和配置一个TUN接口,并开始从中读取数据包。

use std::io::Read;

fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
    let mut config = tun2::Configuration::default();
    config
        .address((10, 0, 0, 9))
        .netmask((255, 255, 255, 0))
        .destination((10, 0, 0, 1))
        .up();

    #[cfg(target_os = "linux")]
    config.platform_config(|config| {
        // requiring root privilege to acquire complete functions
        config.ensure_root_privileges(true);
    });

    let mut dev = tun2::create(&config)?;
    let mut buf = [0; 4096];

    loop {
        let amount = dev.read(&mut buf)?;
        println!("{:?}", &buf[0..amount]);
    }
}

平台

支持的平台

  • Windows
  • Linux
  • macOS
  • FreeBSD
  • Android
  • iOS

Linux

您需要加载tun2模块,并且需要root权限来创建接口。

macOS & FreeBSD

tun2将根据提供的配置自动设置路由,这类似于以下操作

sudo route -n add -net 10.0.0.0/24 10.0.0.1

iOS

您可以将TUN设备的文件描述符传递给tun2来创建接口。

以下是一个在iOS上创建TUN设备并将fd传递给tun2的示例

// Swift
class PacketTunnelProvider: NEPacketTunnelProvider {
    override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
        let tunnelNetworkSettings = createTunnelSettings() // Configure TUN address, DNS, mtu, routing...
        setTunnelNetworkSettings(tunnelNetworkSettings) { [weak self] error in
            // The tunnel of this tunFd is contains `Packet Information` prifix.
            let tunFd = self?.packetFlow.value(forKeyPath: "socket.fileDescriptor") as! Int32
            DispatchQueue.global(qos: .default).async {
                start_tun(tunFd)
            }
            completionHandler(nil)
        }
    }
}
#[no_mangle]
pub extern "C" fn start_tun(fd: std::os::raw::c_int) {
    let mut rt = tokio::runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let mut cfg = tun2::Configuration::default();
        cfg.raw_fd(fd);
        #[cfg(target_os = "ios")]
        cfg.platform_config(|p_cfg| {
            p_cfg.packet_information(true);
        });
        let mut tun = tun2::create_as_async(&cfg).unwrap();
        let mut framed = tun.into_framed();
        while let Some(packet) = framed.next().await {
            ...
        }
    });
}

Windows

您需要将与您的架构匹配的wintun.dll文件复制到与可执行文件相同的目录,并以管理员身份运行您的程序。

依赖项

~0.5–12MB
~114K SLoC