1
This commit is contained in:
Evan Pratten 2023-08-01 20:05:28 -04:00
parent 33a2dd685f
commit c12c260696
5 changed files with 188 additions and 56 deletions

View File

@ -1,56 +1,2 @@
[package]
name = "protomask"
version = "0.2.0"
authors = ["Evan Pratten <ewpratten@gmail.com>"]
edition = "2021"
description = "A user space NAT64 implementation"
readme = "README.md"
homepage = "https://github.com/ewpratten/protomask"
documentation = "https://docs.rs/protomask"
repository = "https://github.com/ewpratten/protomask"
license = "GPL-3.0"
keywords = []
categories = []
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
protomask-tun = { path = "protomask-tun", version = "0.1.0" }
tokio = { version = "1.29.1", features = [
"macros",
"rt-multi-thread",
# "process",
"sync"
] }
clap = { version = "4.3.11", features = ["derive"] }
serde = { version = "1.0.171", features = ["derive"] }
ipnet = { version = "2.8.0", features = ["serde"] }
hyper = { version = "0.14.27", features = ["server", "http1", "tcp"] }
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
toml = "0.7.6"
log = "0.4.19"
fern = "0.6.2"
serde_path_to_error = "0.1.13"
thiserror = "1.0.43"
tun-tap = "0.1.3"
bimap = "0.6.3"
pnet_packet = "0.34.0"
rtnetlink = "0.13.0"
futures = "0.3.28"
prometheus = "0.13.3"
lazy_static = "1.4.0"
[[bin]]
name = "protomask"
path = "src/cli/main.rs"
[package.metadata.deb]
section = "network"
assets = [
["target/release/protomask", "/usr/local/bin/protomask", "755"],
["./protomask.toml", "/etc/protomask.toml", "644"],
["README.md", "usr/share/doc/protomask/README.md", "644"]
]
conf-files = ["/etc/protomask.toml"]
depends = []
maintainer-scripts = "./debian/"
systemd-units = { enable = false }
[workspace]
members = ["libs/easy-tun"]

20
libs/easy-tun/Cargo.toml Normal file
View File

@ -0,0 +1,20 @@
[package]
name = "easy-tun"
version = "0.1.0"
authors = ["Evan Pratten <ewpratten@gmail.com>"]
edition = "2021"
description = "TUN interfaces made easy"
readme = "README.md"
homepage = "https://github.com/ewpratten/protomask/libs/easy-tun"
documentation = "https://docs.rs/easy-tun"
repository = "https://github.com/ewpratten/protomask"
license = "GPL-3.0"
keywords = []
categories = []
[dependencies]
tokio = { version = "^1.29.1", features = ["sync", "rt"] }
log = "^0.4"
libc = "^0.2"
ioctl-gen = "^0.1.1"
rtnetlink = "^0.13.0"

0
libs/easy-tun/README.md Normal file
View File

110
libs/easy-tun/src/lib.rs Normal file
View File

@ -0,0 +1,110 @@
use std::{
fs::{File, OpenOptions},
future::Future,
mem::size_of,
os::fd::{AsRawFd, IntoRawFd, RawFd},
};
use ioctl_gen::{ioc, iow};
use libc::{__c_anonymous_ifr_ifru, ifreq, ioctl, IFF_NO_PI, IFF_TUN, IF_NAMESIZE};
/// A TUN device
pub struct Tun {
/// Internal file descriptor for the TUN device
fd: File,
/// Device name
name: String,
/// Handle on the RTNETLINK connection
rt_connection_future: Box<dyn Future<Output = ()>>,
/// Handle on the RTNETLINK socket
rt_handle: rtnetlink::Handle,
/// Link index of the TUN device
link_index: u32,
}
impl Tun {
/// Creates a new Tun device with the given name.
///
/// The `name` argument must be less than the system's `IFNAMSIZ` constant,
/// and may contain a `%d` format specifier to allow for multiple devices with the same name.
pub fn new(dev: &str) -> Result<Self, std::io::Error> {
// Get a file descriptor for `/dev/net/tun`
log::trace!("Opening /dev/net/tun");
let fd = OpenOptions::new()
.read(true)
.write(true)
.open("/dev/net/tun")?;
// Copy the device name into a C string with padding
// NOTE: No zero padding is needed because we pre-init the array to all 0s
let mut dev_cstr = [0i8; IF_NAMESIZE];
let dev_bytes: Vec<i8> = dev.as_bytes().iter().map(|c| *c as i8).collect();
let dev_len = dev_bytes.len().min(IF_NAMESIZE);
log::trace!("Device name length after truncation: {}", dev_len);
dev_cstr[..dev_len].copy_from_slice(&dev_bytes[..dev_len]);
// Build an `ifreq` struct to send to the kernel
let mut ifr = ifreq {
ifr_name: dev_cstr,
ifr_ifru: __c_anonymous_ifr_ifru {
ifru_flags: (IFF_TUN | IFF_NO_PI) as i16,
},
};
// Make an ioctl call to create the TUN device
log::trace!("Calling ioctl to create TUN device");
let err = unsafe {
ioctl(
fd.as_raw_fd(),
iow!('T', 202, size_of::<usize>()) as u64,
&mut ifr,
)
};
log::trace!("ioctl returned: {}", err);
// Check for errors
if err < 0 {
log::error!("ioctl failed: {}", err);
return Err(std::io::Error::last_os_error());
}
// Get the name of the device
let name = unsafe { std::ffi::CStr::from_ptr(ifr.ifr_name.as_ptr()) }
.to_str()
.unwrap()
.to_string();
// Create an rtnetlink connection
let (rt_connection, rt_handle, _) = rtnetlink::new_connection().map_err(|err| {
log::error!("Failed to open rtnetlink connection");
log::error!("{}", err);
err
})?;
// Build the TUN struct
Ok(Self {
fd,
name,
rt_connection_future: Box::new(rt_connection),
rt_handle,
link_index: 0,
})
}
/// Get the name of the TUN device
pub fn name(&self) -> &str {
&self.name
}
}
impl AsRawFd for Tun {
fn as_raw_fd(&self) -> RawFd {
self.fd.as_raw_fd()
}
}
impl IntoRawFd for Tun {
fn into_raw_fd(self) -> RawFd {
self.fd.into_raw_fd()
}
}

56
protomask/Cargo.toml Normal file
View File

@ -0,0 +1,56 @@
[package]
name = "protomask"
version = "0.2.0"
authors = ["Evan Pratten <ewpratten@gmail.com>"]
edition = "2021"
description = "A user space NAT64 implementation"
readme = "README.md"
homepage = "https://github.com/ewpratten/protomask"
documentation = "https://docs.rs/protomask"
repository = "https://github.com/ewpratten/protomask"
license = "GPL-3.0"
keywords = []
categories = []
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
protomask-tun = { path = "protomask-tun", version = "0.1.0" }
tokio = { version = "1.29.1", features = [
"macros",
"rt-multi-thread",
# "process",
"sync"
] }
clap = { version = "4.3.11", features = ["derive"] }
serde = { version = "1.0.171", features = ["derive"] }
ipnet = { version = "2.8.0", features = ["serde"] }
hyper = { version = "0.14.27", features = ["server", "http1", "tcp"] }
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
toml = "0.7.6"
log = "0.4.19"
fern = "0.6.2"
serde_path_to_error = "0.1.13"
thiserror = "1.0.43"
tun-tap = "0.1.3"
bimap = "0.6.3"
pnet_packet = "0.34.0"
rtnetlink = "0.13.0"
futures = "0.3.28"
prometheus = "0.13.3"
lazy_static = "1.4.0"
[[bin]]
name = "protomask"
path = "src/cli/main.rs"
[package.metadata.deb]
section = "network"
assets = [
["target/release/protomask", "/usr/local/bin/protomask", "755"],
["./protomask.toml", "/etc/protomask.toml", "644"],
["README.md", "usr/share/doc/protomask/README.md", "644"]
]
conf-files = ["/etc/protomask.toml"]
depends = []
maintainer-scripts = "./debian/"
systemd-units = { enable = false }