#tun #networking #tunnel #bindings

tun2

TUN设备创建和处理

34个版本 (稳定版)

新版本 2.0.8 2024年8月22日
2.0.5 2024年7月25日
1.3.1 2024年5月25日
1.2.8 2024年3月30日
0.7.22 2024年1月22日

#107网络编程

Download history 525/week @ 2024-05-03 518/week @ 2024-05-10 648/week @ 2024-05-17 713/week @ 2024-05-24 994/week @ 2024-05-31 1518/week @ 2024-06-07 2265/week @ 2024-06-14 1417/week @ 2024-06-21 1474/week @ 2024-06-28 1353/week @ 2024-07-05 1522/week @ 2024-07-12 2223/week @ 2024-07-19 1993/week @ 2024-07-26 1714/week @ 2024-08-02 2080/week @ 2024-08-09 2585/week @ 2024-08-16

每月8,854次 下载
7 个Crate(6个直接) 中使用

WTFPL 许可证

160KB
3.5K SLoC

TUN接口

Crates.io tun2 WTFPL

此Crate允许创建和使用TUN接口,目标是使其跨平台。

由于原始维护者 @meh 已不再对在 repo 上维护 tun 感兴趣,我们 (@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
~119K SLoC