Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
ssrlive committed Nov 4, 2024
2 parents 83f1f1c + 7a4968a commit 569ee7a
Show file tree
Hide file tree
Showing 46 changed files with 3,655 additions and 1,630 deletions.
11 changes: 11 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[registries.crates-io]
protocol = "sparse"

[build]
# target = ["x86_64-unknown-linux-musl"]
# target = ["x86_64-unknown-linux-gnu"]
# target = ["aarch64-linux-android"]
# target = ["aarch64-apple-ios"]
# target = ["x86_64-pc-windows-msvc"]
# target = ["x86_64-apple-darwin"]
# target = ["x86_64-unknown-freebsd"]
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "daily"
100 changes: 100 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: Push or PR

on:
[push, pull_request]

env:
CARGO_TERM_COLOR: always

jobs:
build_n_test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
- name: rustfmt
if: ${{ !cancelled() }}
run: cargo fmt --all -- --check
- name: check
if: ${{ !cancelled() }}
run: cargo check --verbose
- name: clippy
if: ${{ !cancelled() }}
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Build
if: ${{ !cancelled() }}
run: |
cargo build --verbose --examples --tests --all-features --features="async tokio/rt-multi-thread"
cargo clean
cargo build --verbose --examples --tests --no-default-features
- name: Abort on error
if: ${{ failure() }}
run: echo "Some of jobs failed" && false

build_n_test_android:
strategy:
fail-fast: false
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Install cargo ndk and rust compiler for android target
if: ${{ !cancelled() }}
run: |
cargo install --locked cargo-ndk
rustup target add x86_64-linux-android
- name: clippy
if: ${{ !cancelled() }}
run: cargo ndk -t x86_64 clippy --all-features --features="async tokio/rt-multi-thread" -- -D warnings
- name: Build
if: ${{ !cancelled() }}
run: |
cargo ndk -t x86_64 rustc --verbose --all-features --features="async tokio/rt-multi-thread" --lib --crate-type=cdylib
- name: Abort on error
if: ${{ failure() }}
run: echo "Android build job failed" && false

build_n_test_ios:
strategy:
fail-fast: false
runs-on: macos-latest

steps:
- uses: actions/checkout@v4
- name: Install cargo lipo and rust compiler for ios target
if: ${{ !cancelled() }}
run: |
cargo install --locked cargo-lipo
rustup target add x86_64-apple-ios aarch64-apple-ios
- name: clippy
if: ${{ !cancelled() }}
run: cargo clippy --target x86_64-apple-ios --all-features --features="async tokio/rt-multi-thread" -- -D warnings
- name: Build
if: ${{ !cancelled() }}
run: |
cargo lipo --verbose --all-features --features="async tokio/rt-multi-thread"
- name: Abort on error
if: ${{ failure() }}
run: echo "iOs build job failed" && false

semver:
name: Check semver
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Check semver
if: ${{ !cancelled() }}
uses: obi1kenobi/cargo-semver-checks-action@v2
- name: Abort on error
if: ${{ failure() }}
run: echo "Semver check failed" && false
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.vscode/
.VSCodeCounter/
build/
tmp/
target/
**/*.rs.bk
Cargo.lock
wintun.dll
78 changes: 58 additions & 20 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,45 +1,83 @@
[package]
name = "tun"
version = "0.5.5"
edition = "2018"

authors = ["meh. <[email protected]>"]
version = "0.8.0"
edition = "2021"
authors = ["meh. <[email protected]>", "@ssrlive"]
license = "WTFPL"

description = "TUN device creation and handling."
repository = "https://github.com/meh/rust-tun"
keywords = ["tun", "network", "tunnel", "bindings"]

[lib]
crate-type = ["staticlib", "cdylib", "lib"]

[dependencies]
libc = "0.2"
bytes = { version = "1" }
cfg-if = "1"
futures-core = { version = "0.3", optional = true }
libc = { version = "0.2", features = ["extra_traits"] }
log = "0.4"
thiserror = "1"
tokio = { version = "1", features = [
"net",
"macros",
"io-util",
], optional = true }
tokio-util = { version = "0.7", features = ["codec"], optional = true }

[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "android"))'.dependencies]
tokio = { version = "1", features = ["net", "macros"], optional = true }
tokio-util = { version = "0.6", features = ["codec"], optional = true }
bytes = { version = "1", optional = true }
byteorder = { version = "1", optional = true }
# This is only for the `ready` macro.
futures-core = { version = "0.3", optional = true }
[target.'cfg(unix)'.dependencies]
nix = { version = "0.29", features = ["ioctl"] }

[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
ioctl = { version = "0.6", package = "ioctl-sys" }
[target.'cfg(target_os = "windows")'.dependencies]
futures = { version = "0.3", optional = true }
windows-sys = { version = "0.59", features = [
"Win32_Foundation",
"Win32_Security",
"Win32_Security_WinTrust",
"Win32_Security_Cryptography",
"Win32_System_Threading",
"Win32_UI_WindowsAndMessaging",
"Win32_System_LibraryLoader",
] }
wintun-bindings = { version = "^0.7.7", features = [
"panic_on_unsent_packets",
"verify_binary_signature",
"async",
] }

[target.'cfg(any(target_os = "macos", target_os = "freebsd"))'.dependencies]
ipnet = "2"

[dev-dependencies]
packet = "0.1"
ctrlc2 = { version = "3", features = ["tokio", "termination"] }
env_logger = "0.11"
futures = "0.3"
packet = "0.1"
serde_json = "1"
tokio = { version = "1", features = ["rt-multi-thread"] }

[features]
async = ["tokio", "tokio-util", "bytes", "byteorder", "futures-core"]
default = []
# default = ["async"]
async = [
"tokio",
"futures-core",
"futures",
"tokio-util",
"wintun-bindings/async",
]

[package.metadata.docs.rs]
features = ["async"]

[[example]]
name = "read-async"
required-features = [ "async", "tokio/rt-multi-thread" ]
required-features = ["async"]

[[example]]
name = "read-async-codec"
required-features = [ "async", "tokio/rt-multi-thread" ]
required-features = ["async"]

[[example]]
name = "ping-tun"
required-features = [ "async", "tokio/rt-multi-thread" ]
required-features = ["async"]
83 changes: 51 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
TUN interfaces [![Crates.io](https://img.shields.io/crates/v/tun.svg)](https://crates.io/crates/tun) ![tun](https://docs.rs/tun/badge.svg) ![WTFPL](http://img.shields.io/badge/license-WTFPL-blue.svg)
TUN interfaces
==============
[![Crates.io](https://img.shields.io/crates/v/tun.svg)](https://crates.io/crates/tun)
[![tun](https://docs.rs/tun/badge.svg)](https://docs.rs/tun/latest/tun/)
![WTFPL](http://img.shields.io/badge/license-WTFPL-blue.svg)

This crate allows the creation and usage of TUN interfaces, the aim is to make this cross-platform.

Usage
Expand All @@ -8,20 +12,14 @@ First, add the following to your `Cargo.toml`:

```toml
[dependencies]
tun = "0.5"
```

Next, add this to your crate root:

```rust
extern crate tun;
tun = "0.7"
```

If you want to use the TUN interface with mio/tokio, you need to enable the `async` feature:

```toml
[dependencies]
tun = { version = "0.5", features = ["async"] }
tun = { version = "0.7", features = ["async"] }
```

Example
Expand All @@ -32,53 +30,65 @@ packets from it.
```rust
use std::io::Read;

extern crate tun;

fn main() {
let mut config = tun::Configuration::default();
config.address((10, 0, 0, 1))
.netmask((255, 255, 255, 0))
.up();

#[cfg(target_os = "linux")]
config.platform(|config| {
config.packet_information(true);
});
fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
let mut config = tun::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 = tun::create(&config).unwrap();
let mut buf = [0; 4096];
let mut dev = tun::create(&config)?;
let mut buf = [0; 4096];

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

Platforms
=========
Not every platform is supported.
## Supported Platforms

- [x] Windows
- [x] Linux
- [x] macOS
- [x] FreeBSD
- [x] Android
- [x] iOS


Linux
-----
You will need the `tun` module to be loaded and root is required to create
interfaces.

macOS
macOS & FreeBSD
-----
It just werks, but you have to set up routing manually.
`tun` will automatically set up a route according to the provided configuration, which does a similar thing like this:
> sudo route -n add -net 10.0.0.0/24 10.0.0.1

iOS
----
You can pass the file descriptor of the TUN device to `rust-tun` to create the interface.
You can pass the file descriptor of the TUN device to `tun` to create the interface.

Here is an example to create the TUN device on iOS and pass the `fd` to `rust-tun`:
Here is an example to create the TUN device on iOS and pass the `fd` to `tun`:
```swift
// 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)
Expand All @@ -96,6 +106,10 @@ pub extern "C" fn start_tun(fd: std::os::raw::c_int) {
rt.block_on(async {
let mut cfg = tun::Configuration::default();
cfg.raw_fd(fd);
#[cfg(target_os = "ios")]
cfg.platform_config(|p_cfg| {
p_cfg.packet_information(true);
});
let mut tun = tun::create_as_async(&cfg).unwrap();
let mut framed = tun.into_framed();
while let Some(packet) = framed.next().await {
Expand All @@ -104,3 +118,8 @@ pub extern "C" fn start_tun(fd: std::os::raw::c_int) {
});
}
```

Windows
-----
You need to copy the [wintun.dll](https://wintun.net/) file which matches your architecture to
the same directory as your executable and run your program as administrator.
Loading

0 comments on commit 569ee7a

Please sign in to comment.