Add Support for IPV6 and Arbitrary Server Address
Add IPV6 support for Apple Devices Note: Works in GUI not CLI Adds Support for Arbitrary Server Address
This commit is contained in:
parent
cca5999214
commit
2088ae6ede
20 changed files with 276 additions and 56 deletions
|
|
@ -31,7 +31,7 @@ struct BurrowStartRequest: Codable {
|
||||||
let no_pi: Bool
|
let no_pi: Bool
|
||||||
let tun_excl: Bool
|
let tun_excl: Bool
|
||||||
let tun_retrieve: Bool
|
let tun_retrieve: Bool
|
||||||
let address: String?
|
let address: [String]
|
||||||
}
|
}
|
||||||
struct StartOptions: Codable {
|
struct StartOptions: Codable {
|
||||||
let tun: TunOptions
|
let tun: TunOptions
|
||||||
|
|
@ -51,7 +51,7 @@ struct BurrowResult<T>: Codable where T: Codable {
|
||||||
|
|
||||||
struct ServerConfigData: Codable {
|
struct ServerConfigData: Codable {
|
||||||
struct InternalConfig: Codable {
|
struct InternalConfig: Codable {
|
||||||
let address: String?
|
let address: [String]
|
||||||
let name: String?
|
let name: String?
|
||||||
let mtu: Int32?
|
let mtu: Int32?
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
command: BurrowStartRequest(
|
command: BurrowStartRequest(
|
||||||
Start: BurrowStartRequest.StartOptions(
|
Start: BurrowStartRequest.StartOptions(
|
||||||
tun: BurrowStartRequest.TunOptions(
|
tun: BurrowStartRequest.TunOptions(
|
||||||
name: nil, no_pi: false, tun_excl: false, tun_retrieve: true, address: nil
|
name: nil, no_pi: false, tun_excl: false, tun_retrieve: true, address: []
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -46,12 +46,21 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
|
|
||||||
private func generateTunSettings(from: ServerConfigData) -> NETunnelNetworkSettings? {
|
private func generateTunSettings(from: ServerConfigData) -> NETunnelNetworkSettings? {
|
||||||
let cfig = from.ServerConfig
|
let cfig = from.ServerConfig
|
||||||
guard let addr = cfig.address else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Using a makeshift remote tunnel address
|
|
||||||
let nst = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "1.1.1.1")
|
let nst = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "1.1.1.1")
|
||||||
nst.ipv4Settings = NEIPv4Settings(addresses: [addr], subnetMasks: ["255.255.255.0"])
|
var v4Addresses = [String]()
|
||||||
|
var v6Addresses = [String]()
|
||||||
|
for addr in cfig.address {
|
||||||
|
if IPv4Address(addr) != nil {
|
||||||
|
v6Addresses.append(addr)
|
||||||
|
}
|
||||||
|
if IPv6Address(addr) != nil {
|
||||||
|
v4Addresses.append(addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nst.ipv4Settings = NEIPv4Settings(addresses: v4Addresses, subnetMasks: v4Addresses.map { _ in
|
||||||
|
"255.255.255.0"
|
||||||
|
})
|
||||||
|
nst.ipv6Settings = NEIPv6Settings(addresses: v6Addresses, networkPrefixLengths: v6Addresses.map { _ in 64 })
|
||||||
logger.log("Initialized ipv4 settings: \(nst.ipv4Settings)")
|
logger.log("Initialized ipv4 settings: \(nst.ipv4Settings)")
|
||||||
return nst
|
return nst
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
Cargo.lock
generated
16
Cargo.lock
generated
|
|
@ -1074,7 +1074,7 @@ dependencies = [
|
||||||
"httpdate",
|
"httpdate",
|
||||||
"itoa",
|
"itoa",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2 0.5.5",
|
"socket2",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
@ -2114,16 +2114,6 @@ version = "1.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "socket2"
|
|
||||||
version = "0.4.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.5.5"
|
version = "0.5.5"
|
||||||
|
|
@ -2305,7 +2295,7 @@ dependencies = [
|
||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2 0.5.5",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
|
|
@ -2547,7 +2537,7 @@ dependencies = [
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
"socket2 0.4.10",
|
"socket2",
|
||||||
"ssri",
|
"ssri",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
FROM docker.io/library/rust:1.74.0-slim-bookworm AS builder
|
FROM docker.io/library/rust:1.76.0-slim-bookworm AS builder
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
ARG LLVM_VERSION=16
|
ARG LLVM_VERSION=16
|
||||||
|
|
|
||||||
25
Makefile
25
Makefile
|
|
@ -1,4 +1,4 @@
|
||||||
tun_num := $(shell ifconfig | awk -F 'utun|[: ]' '/utun[0-9]/ {print $$2}' | tail -n 1)
|
tun := $(shell ifconfig -l | sed 's/ /\n/g' | grep utun | tail -n 1)
|
||||||
cargo_console := RUST_BACKTRACE=1 RUST_LOG=debug RUSTFLAGS='--cfg tokio_unstable' cargo run --all-features
|
cargo_console := RUST_BACKTRACE=1 RUST_LOG=debug RUSTFLAGS='--cfg tokio_unstable' cargo run --all-features
|
||||||
cargo_norm := RUST_BACKTRACE=1 RUST_LOG=debug cargo run
|
cargo_norm := RUST_BACKTRACE=1 RUST_LOG=debug cargo run
|
||||||
|
|
||||||
|
|
@ -19,15 +19,28 @@ start:
|
||||||
|
|
||||||
test-dns:
|
test-dns:
|
||||||
@sudo route delete 8.8.8.8
|
@sudo route delete 8.8.8.8
|
||||||
@sudo route add 8.8.8.8 -interface utun$(tun_num)
|
@sudo route add 8.8.8.8 -interface $(tun)
|
||||||
@dig @8.8.8.8 hackclub.com
|
@dig @8.8.8.8 hackclub.com
|
||||||
|
|
||||||
test-https:
|
test-https:
|
||||||
@sudo route delete 193.183.0.162
|
@sudo route delete 193.183.0.162
|
||||||
@sudo route add 193.183.0.162 -interface utun$(tun_num)
|
@sudo route add 193.183.0.162 -interface $(tun)
|
||||||
@curl -vv https://search.marginalia.nu
|
@curl -vv https://search.marginalia.nu
|
||||||
|
|
||||||
|
v4_target := 146.190.62.39
|
||||||
test-http:
|
test-http:
|
||||||
@sudo route delete 146.190.62.39
|
@sudo route delete ${v4_target}
|
||||||
@sudo route add 146.190.62.39 -interface utun$(tun_num)
|
@sudo route add ${v4_target} -interface $(tun)
|
||||||
@curl -vv 146.190.62.39:80
|
@curl -vv ${v4_target}:80
|
||||||
|
|
||||||
|
test-ipv4:
|
||||||
|
@sudo route delete ${v4_target}
|
||||||
|
@sudo route add ${v4_target} -interface $(tun)
|
||||||
|
@ping ${v4_target}
|
||||||
|
|
||||||
|
v6_target := 2001:4860:4860::8888
|
||||||
|
test-ipv6:
|
||||||
|
@sudo route delete ${v6_target}
|
||||||
|
@sudo route -n add -inet6 ${v6_target} -interface $(tun)
|
||||||
|
@echo preparing
|
||||||
|
@sudo ping6 -v ${v6_target}
|
||||||
|
|
|
||||||
38
burrow-server-compose.yml
Normal file
38
burrow-server-compose.yml
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
version: "2.1"
|
||||||
|
networks:
|
||||||
|
wg6:
|
||||||
|
enable_ipv6: true
|
||||||
|
ipam:
|
||||||
|
driver: default
|
||||||
|
config:
|
||||||
|
- subnet: "aa:bb:cc:de::/64"
|
||||||
|
services:
|
||||||
|
burrow:
|
||||||
|
image: lscr.io/linuxserver/wireguard:latest
|
||||||
|
privileged: true
|
||||||
|
container_name: burrow_server
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
- SYS_MODULE
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Asia/Calcutta
|
||||||
|
- SERVERURL=wg.burrow.rs
|
||||||
|
- SERVERPORT=51820
|
||||||
|
- PEERS=10
|
||||||
|
- PEERDNS=1.1.1.1
|
||||||
|
- INTERNAL_SUBNET=10.13.13.0
|
||||||
|
- ALLOWEDIPS=0.0.0.0/0, ::/0
|
||||||
|
- PERSISTENTKEEPALIVE_PEERS=all
|
||||||
|
- LOG_CONFS=true #optional
|
||||||
|
volumes:
|
||||||
|
- ./config:/config
|
||||||
|
- /lib/modules:/lib/modules
|
||||||
|
ports:
|
||||||
|
- 51820:51820/udp
|
||||||
|
sysctls:
|
||||||
|
- net.ipv4.conf.all.src_valid_mark=1
|
||||||
|
- net.ipv6.conf.all.disable_ipv6=0
|
||||||
|
- net.ipv6.conf.eth0.proxy_ndp=1
|
||||||
|
restart: unless-stopped
|
||||||
|
|
@ -57,7 +57,7 @@ impl TryFrom<&TunInterface> for ServerInfo {
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct ServerConfig {
|
pub struct ServerConfig {
|
||||||
pub address: Option<String>,
|
pub address: Vec<String>,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub mtu: Option<i32>,
|
pub mtu: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +65,7 @@ pub struct ServerConfig {
|
||||||
impl Default for ServerConfig {
|
impl Default for ServerConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
address: Some("10.13.13.2".to_string()), // Dummy remote address
|
address: vec!["10.13.13.2".to_string()], // Dummy remote address
|
||||||
name: None,
|
name: None,
|
||||||
mtu: None,
|
mtu: None,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@
|
||||||
source: burrow/src/daemon/command.rs
|
source: burrow/src/daemon/command.rs
|
||||||
expression: "serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions {\n tun: TunOptions { ..TunOptions::default() },\n })).unwrap()"
|
expression: "serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions {\n tun: TunOptions { ..TunOptions::default() },\n })).unwrap()"
|
||||||
---
|
---
|
||||||
{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":null}}}
|
{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":[]}}}
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@
|
||||||
source: burrow/src/daemon/command.rs
|
source: burrow/src/daemon/command.rs
|
||||||
expression: "serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions::default())).unwrap()"
|
expression: "serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions::default())).unwrap()"
|
||||||
---
|
---
|
||||||
{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":null}}}
|
{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":[]}}}
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@
|
||||||
source: burrow/src/daemon/response.rs
|
source: burrow/src/daemon/response.rs
|
||||||
expression: "serde_json::to_string(&DaemonResponse::new(Ok::<DaemonResponseData,\n String>(DaemonResponseData::ServerConfig(ServerConfig::default()))))?"
|
expression: "serde_json::to_string(&DaemonResponse::new(Ok::<DaemonResponseData,\n String>(DaemonResponseData::ServerConfig(ServerConfig::default()))))?"
|
||||||
---
|
---
|
||||||
{"result":{"Ok":{"ServerConfig":{"address":"10.13.13.2","name":null,"mtu":null}}},"id":0}
|
{"result":{"Ok":{"ServerConfig":{"address":["10.13.13.2"],"name":null,"mtu":null}}},"id":0}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ async fn try_start() -> Result<()> {
|
||||||
let mut client = DaemonClient::new().await?;
|
let mut client = DaemonClient::new().await?;
|
||||||
client
|
client
|
||||||
.send_command(DaemonCommand::Start(DaemonStartOptions {
|
.send_command(DaemonCommand::Start(DaemonStartOptions {
|
||||||
tun: TunOptions::new().address("10.13.13.2"),
|
tun: TunOptions::new().address(vec!["10.13.13.2", "::2"]),
|
||||||
}))
|
}))
|
||||||
.await
|
.await
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ pub fn initialize() {
|
||||||
tracing_subscriber::fmt::layer()
|
tracing_subscriber::fmt::layer()
|
||||||
.with_level(true)
|
.with_level(true)
|
||||||
.with_writer(std::io::stderr)
|
.with_writer(std::io::stderr)
|
||||||
|
.with_line_number(true)
|
||||||
.compact()
|
.compact()
|
||||||
.with_filter(EnvFilter::from_default_env())
|
.with_filter(EnvFilter::from_default_env())
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ pub struct Peer {
|
||||||
|
|
||||||
pub struct Interface {
|
pub struct Interface {
|
||||||
pub private_key: String,
|
pub private_key: String,
|
||||||
pub address: String,
|
pub address: Vec<String>,
|
||||||
pub listen_port: u32,
|
pub listen_port: u32,
|
||||||
pub dns: Vec<String>,
|
pub dns: Vec<String>,
|
||||||
pub mtu: Option<u32>,
|
pub mtu: Option<u32>,
|
||||||
|
|
@ -93,8 +93,8 @@ impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
interface: Interface {
|
interface: Interface {
|
||||||
private_key: "GNqIAOCRxjl/cicZyvkvpTklgQuUmGUIEkH7IXF/sEE=".into(),
|
private_key: "OEPVdomeLTxTIBvv3TYsJRge0Hp9NMiY0sIrhT8OWG8=".into(),
|
||||||
address: "10.13.13.2/24".into(),
|
address: vec!["10.13.13.2/24".into()],
|
||||||
listen_port: 51820,
|
listen_port: 51820,
|
||||||
dns: Default::default(),
|
dns: Default::default(),
|
||||||
mtu: Default::default(),
|
mtu: Default::default(),
|
||||||
|
|
@ -102,8 +102,8 @@ impl Default for Config {
|
||||||
peers: vec![Peer {
|
peers: vec![Peer {
|
||||||
endpoint: "wg.burrow.rs:51820".into(),
|
endpoint: "wg.burrow.rs:51820".into(),
|
||||||
allowed_ips: vec!["8.8.8.8/32".into(), "0.0.0.0/0".into()],
|
allowed_ips: vec!["8.8.8.8/32".into(), "0.0.0.0/0".into()],
|
||||||
public_key: "uy75leriJay0+oHLhRMpV+A5xAQ0hCJ+q7Ww81AOvT4=".into(),
|
public_key: "8GaFjVO6c4luCHG4ONO+1bFG8tO+Zz5/Gy+Geht1USM=".into(),
|
||||||
preshared_key: Some("s7lx/mg+reVEMnGnqeyYOQkzD86n2+gYnx1M9ygi08k=".into()),
|
preshared_key: Some("ha7j4BjD49sIzyF9SNlbueK0AMHghlj6+u0G3bzC698=".into()),
|
||||||
persistent_keepalive: Default::default(),
|
persistent_keepalive: Default::default(),
|
||||||
name: Default::default(),
|
name: Default::default(),
|
||||||
}],
|
}],
|
||||||
|
|
|
||||||
21
server_patch.txt
Normal file
21
server_patch.txt
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Add this to ~/server/wg0.conf upon regeneration
|
||||||
|
|
||||||
|
PostUp = iptables -A FORWARD -i %i -j ACCEPT
|
||||||
|
|
||||||
|
PostUp = iptables -A FORWARD -o %i -j ACCEPT
|
||||||
|
|
||||||
|
PostUp = iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE
|
||||||
|
|
||||||
|
PostUp = ip6tables -A FORWARD -i %i -j ACCEPT
|
||||||
|
|
||||||
|
PostUp = ip6tables -A FORWARD -o %i -j ACCEPT
|
||||||
|
|
||||||
|
PostDown = iptables -D FORWARD -i %i -j ACCEPT
|
||||||
|
|
||||||
|
PostDown = iptables -D FORWARD -o %i -j ACCEPT
|
||||||
|
|
||||||
|
PostDown = iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE
|
||||||
|
|
||||||
|
PostDown = ip6tables -D FORWARD -i %i -j ACCEPT
|
||||||
|
|
||||||
|
PostDown = ip6tables -D FORWARD -o %i -j ACCEPT
|
||||||
|
|
@ -7,7 +7,7 @@ edition = "2021"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
fehler = "1.0"
|
fehler = "1.0"
|
||||||
nix = { version = "0.26", features = ["ioctl"] }
|
nix = { version = "0.26", features = ["ioctl"] }
|
||||||
socket2 = "0.4"
|
socket2 = "0.5"
|
||||||
tokio = { version = "1.28", features = [] }
|
tokio = { version = "1.28", features = [] }
|
||||||
byteorder = "1.4"
|
byteorder = "1.4"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ pub struct TunOptions {
|
||||||
/// (Apple) Retrieve the tun interface
|
/// (Apple) Retrieve the tun interface
|
||||||
pub tun_retrieve: bool,
|
pub tun_retrieve: bool,
|
||||||
/// (Linux) The IP address of the tun interface.
|
/// (Linux) The IP address of the tun interface.
|
||||||
pub address: Option<String>,
|
pub address: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TunOptions {
|
impl TunOptions {
|
||||||
|
|
@ -44,8 +44,8 @@ impl TunOptions {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn address(mut self, address: impl ToString) -> Self {
|
pub fn address(mut self, address: Vec<impl ToString>) -> Self {
|
||||||
self.address = Some(address.to_string());
|
self.address = address.iter().map(|x| x.to_string()).collect();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ impl SysControlSocket for socket2::Socket {
|
||||||
unsafe { sys::resolve_ctl_info(self.as_raw_fd(), &mut info as *mut sys::ctl_info)? };
|
unsafe { sys::resolve_ctl_info(self.as_raw_fd(), &mut info as *mut sys::ctl_info)? };
|
||||||
|
|
||||||
let (_, addr) = unsafe {
|
let (_, addr) = unsafe {
|
||||||
socket2::SockAddr::init(|addr_storage, len| {
|
socket2::SockAddr::try_init(|addr_storage, len| {
|
||||||
*len = size_of::<sys::sockaddr_ctl>() as u32;
|
*len = size_of::<sys::sockaddr_ctl>() as u32;
|
||||||
|
|
||||||
let addr: &mut sys::sockaddr_ctl = &mut *addr_storage.cast();
|
let addr: &mut sys::sockaddr_ctl = &mut *addr_storage.cast();
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
use std::{
|
use std::{io::{Error, IoSlice}, mem, net::{Ipv4Addr, SocketAddrV4}, os::fd::{AsRawFd, FromRawFd, RawFd}, ptr};
|
||||||
io::{Error, IoSlice},
|
use std::net::{IpAddr, Ipv6Addr, SocketAddrV6};
|
||||||
mem,
|
use std::ptr::addr_of;
|
||||||
net::{Ipv4Addr, SocketAddrV4},
|
|
||||||
os::fd::{AsRawFd, FromRawFd, RawFd},
|
|
||||||
};
|
|
||||||
|
|
||||||
use byteorder::{ByteOrder, NetworkEndian};
|
use byteorder::{ByteOrder, NetworkEndian};
|
||||||
use fehler::throws;
|
use fehler::throws;
|
||||||
use libc::{c_char, iovec, writev, AF_INET, AF_INET6};
|
use libc::{c_char, iovec, writev, AF_INET, AF_INET6, sockaddr_in6};
|
||||||
|
use nix::sys::socket::SockaddrIn6;
|
||||||
use socket2::{Domain, SockAddr, Socket, Type};
|
use socket2::{Domain, SockAddr, Socket, Type};
|
||||||
use tracing::{self, instrument};
|
use tracing::{self, instrument};
|
||||||
|
|
||||||
|
|
@ -49,7 +47,7 @@ impl TunInterface {
|
||||||
pub fn retrieve() -> Option<TunInterface> {
|
pub fn retrieve() -> Option<TunInterface> {
|
||||||
(3..100)
|
(3..100)
|
||||||
.filter_map(|fd| unsafe {
|
.filter_map(|fd| unsafe {
|
||||||
let peer_addr = socket2::SockAddr::init(|storage, len| {
|
let peer_addr = socket2::SockAddr::try_init(|storage, len| {
|
||||||
*len = mem::size_of::<sys::sockaddr_ctl>() as u32;
|
*len = mem::size_of::<sys::sockaddr_ctl>() as u32;
|
||||||
libc::getpeername(fd, storage as *mut _, len);
|
libc::getpeername(fd, storage as *mut _, len);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -71,9 +69,12 @@ impl TunInterface {
|
||||||
|
|
||||||
#[throws]
|
#[throws]
|
||||||
fn configure(&self, options: TunOptions) {
|
fn configure(&self, options: TunOptions) {
|
||||||
if let Some(addr) = options.address {
|
for addr in options.address{
|
||||||
if let Ok(addr) = addr.parse() {
|
if let Ok(addr) = addr.parse::<IpAddr>() {
|
||||||
self.set_ipv4_addr(addr)?;
|
match addr {
|
||||||
|
IpAddr::V4(addr) => {self.set_ipv4_addr(addr)?}
|
||||||
|
IpAddr::V6(addr) => {self.set_ipv6_addr(addr)?}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -117,6 +118,14 @@ impl TunInterface {
|
||||||
iff
|
iff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[throws]
|
||||||
|
#[instrument]
|
||||||
|
fn in6_ifreq(&self) -> sys::in6_ifreq {
|
||||||
|
let mut iff: sys::in6_ifreq = unsafe { mem::zeroed() };
|
||||||
|
iff.ifr_name = string_to_ifname(&self.name()?);
|
||||||
|
iff
|
||||||
|
}
|
||||||
|
|
||||||
#[throws]
|
#[throws]
|
||||||
#[instrument]
|
#[instrument]
|
||||||
pub fn set_ipv4_addr(&self, addr: Ipv4Addr) {
|
pub fn set_ipv4_addr(&self, addr: Ipv4Addr) {
|
||||||
|
|
@ -136,6 +145,21 @@ impl TunInterface {
|
||||||
Ipv4Addr::from(u32::from_be(addr.sin_addr.s_addr))
|
Ipv4Addr::from(u32::from_be(addr.sin_addr.s_addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[throws]
|
||||||
|
pub fn set_ipv6_addr(&self, addr: Ipv6Addr) {
|
||||||
|
// let addr = SockAddr::from(SocketAddrV6::new(addr, 0, 0, 0));
|
||||||
|
// println!("addr: {:?}", addr);
|
||||||
|
// let mut iff = self.in6_ifreq()?;
|
||||||
|
// let sto = addr.as_storage();
|
||||||
|
// let ifadddr_ptr: *const sockaddr_in6 = addr_of!(sto).cast();
|
||||||
|
// iff.ifr_ifru.ifru_addr = unsafe { *ifadddr_ptr };
|
||||||
|
// println!("ifru addr set");
|
||||||
|
// println!("{:?}", sys::SIOCSIFADDR_IN6);
|
||||||
|
// self.perform6(|fd| unsafe { sys::if_set_addr6(fd, &iff) })?;
|
||||||
|
// tracing::info!("ipv6_addr_set");
|
||||||
|
tracing::warn!("Setting IPV6 address on MacOS CLI mode is not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
#[throws]
|
#[throws]
|
||||||
fn perform<R>(&self, perform: impl FnOnce(RawFd) -> Result<R, nix::Error>) -> R {
|
fn perform<R>(&self, perform: impl FnOnce(RawFd) -> Result<R, nix::Error>) -> R {
|
||||||
let span = tracing::info_span!("perform", fd = self.as_raw_fd());
|
let span = tracing::info_span!("perform", fd = self.as_raw_fd());
|
||||||
|
|
@ -145,6 +169,15 @@ impl TunInterface {
|
||||||
perform(socket.as_raw_fd())?
|
perform(socket.as_raw_fd())?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[throws]
|
||||||
|
fn perform6<R>(&self, perform: impl FnOnce(RawFd) -> Result<R, nix::Error>) -> R {
|
||||||
|
let span = tracing::info_span!("perform6", fd = self.as_raw_fd());
|
||||||
|
let _enter = span.enter();
|
||||||
|
|
||||||
|
let socket = Socket::new(Domain::IPV6, Type::DGRAM, None)?;
|
||||||
|
perform(socket.as_raw_fd())?
|
||||||
|
}
|
||||||
|
|
||||||
#[throws]
|
#[throws]
|
||||||
#[instrument]
|
#[instrument]
|
||||||
pub fn mtu(&self) -> i32 {
|
pub fn mtu(&self) -> i32 {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use libc::{c_char, c_int, c_short, c_uint, c_ulong, sockaddr};
|
use libc::{c_char, c_int, c_short, c_uint, c_ulong, sockaddr, sockaddr_in6, time_t};
|
||||||
pub use libc::{
|
pub use libc::{
|
||||||
c_void,
|
c_void,
|
||||||
sockaddr_ctl,
|
sockaddr_ctl,
|
||||||
|
|
@ -23,6 +23,7 @@ pub const UTUN_CONTROL_NAME: &str = "com.apple.net.utun_control";
|
||||||
pub const UTUN_OPT_IFNAME: libc::c_int = 2;
|
pub const UTUN_OPT_IFNAME: libc::c_int = 2;
|
||||||
|
|
||||||
pub const MAX_KCTL_NAME: usize = 96;
|
pub const MAX_KCTL_NAME: usize = 96;
|
||||||
|
pub const SCOPE6_ID_MAX: usize = 16;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
|
@ -74,7 +75,107 @@ pub struct ifreq {
|
||||||
pub ifr_ifru: ifr_ifru,
|
pub ifr_ifru: ifr_ifru,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct in6_addrlifetime{
|
||||||
|
pub ia6t_expire: time_t,
|
||||||
|
pub ia6t_preferred: time_t,
|
||||||
|
pub ia6t_vltime: u32,
|
||||||
|
pub ia6t_pltime: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct in6_ifstat {
|
||||||
|
pub ifs6_in_receive: u64,
|
||||||
|
pub ifs6_in_hdrerr: u64,
|
||||||
|
pub ifs6_in_toobig: u64,
|
||||||
|
pub ifs6_in_noroute: u64,
|
||||||
|
pub ifs6_in_addrerr: u64,
|
||||||
|
pub ifs6_in_protounknown: u64,
|
||||||
|
pub ifs6_in_truncated: u64,
|
||||||
|
pub ifs6_in_discard: u64,
|
||||||
|
pub ifs6_in_deliver: u64,
|
||||||
|
pub ifs6_out_forward: u64,
|
||||||
|
pub ifs6_out_request: u64,
|
||||||
|
pub ifs6_out_discard: u64,
|
||||||
|
pub ifs6_out_fragok: u64,
|
||||||
|
pub ifs6_out_fragfail: u64,
|
||||||
|
pub ifs6_out_fragcreat: u64,
|
||||||
|
pub ifs6_reass_reqd: u64,
|
||||||
|
pub ifs6_reass_ok: u64,
|
||||||
|
pub ifs6_atmfrag_rcvd: u64,
|
||||||
|
pub ifs6_reass_fail: u64,
|
||||||
|
pub ifs6_in_mcast: u64,
|
||||||
|
pub ifs6_out_mcast: u64,
|
||||||
|
pub ifs6_cantfoward_icmp6: u64,
|
||||||
|
pub ifs6_addr_expiry_cnt: u64,
|
||||||
|
pub ifs6_pfx_expiry_cnt: u64,
|
||||||
|
pub ifs6_defrtr_expiry_cnt: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct icmp6_ifstat {
|
||||||
|
pub ifs6_in_msg: u64,
|
||||||
|
pub ifs6_in_error: u64,
|
||||||
|
pub ifs6_in_dstunreach: u64,
|
||||||
|
pub ifs6_in_adminprohib: u64,
|
||||||
|
pub ifs6_in_timeexceed: u64,
|
||||||
|
pub ifs6_in_paramprob: u64,
|
||||||
|
pub ifs6_in_pkttoobig: u64,
|
||||||
|
pub ifs6_in_echo: u64,
|
||||||
|
pub ifs6_in_echoreply: u64,
|
||||||
|
pub ifs6_in_routersolicit: u64,
|
||||||
|
pub ifs6_in_routeradvert: u64,
|
||||||
|
pub ifs6_in_neighborsolicit: u64,
|
||||||
|
pub ifs6_in_neighboradvert: u64,
|
||||||
|
pub ifs6_in_redirect: u64,
|
||||||
|
pub ifs6_in_mldquery: u64,
|
||||||
|
pub ifs6_in_mldreport: u64,
|
||||||
|
pub ifs6_in_mlddone: u64,
|
||||||
|
pub ifs6_out_msg: u64,
|
||||||
|
pub ifs6_out_error: u64,
|
||||||
|
pub ifs6_out_dstunreach: u64,
|
||||||
|
pub ifs6_out_adminprohib: u64,
|
||||||
|
pub ifs6_out_timeexceed: u64,
|
||||||
|
pub ifs6_out_paramprob: u64,
|
||||||
|
pub ifs6_out_pkttoobig: u64,
|
||||||
|
pub ifs6_out_echo: u64,
|
||||||
|
pub ifs6_out_echoreply: u64,
|
||||||
|
pub ifs6_out_routersolicit: u64,
|
||||||
|
pub ifs6_out_routeradvert: u64,
|
||||||
|
pub ifs6_out_neighborsolicit: u64,
|
||||||
|
pub ifs6_out_neighboradvert: u64,
|
||||||
|
pub ifs6_out_redirect: u64,
|
||||||
|
pub ifs6_out_mldquery: u64,
|
||||||
|
pub ifs6_out_mldreport: u64,
|
||||||
|
pub ifs6_out_mlddone: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub union ifr_ifru6 {
|
||||||
|
pub ifru_addr: sockaddr_in6,
|
||||||
|
pub ifru_dstaddr: sockaddr_in6,
|
||||||
|
pub ifru_flags: c_int,
|
||||||
|
pub ifru_flags6: c_int,
|
||||||
|
pub ifru_metric: c_int,
|
||||||
|
pub ifru_intval: c_int,
|
||||||
|
pub ifru_data: *mut c_char,
|
||||||
|
pub ifru_lifetime: in6_addrlifetime, // ifru_lifetime
|
||||||
|
pub ifru_stat: in6_ifstat,
|
||||||
|
pub ifru_icmp6stat: icmp6_ifstat,
|
||||||
|
pub ifru_scope_id: [u32; SCOPE6_ID_MAX]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct in6_ifreq {
|
||||||
|
pub ifr_name: [c_char; IFNAMSIZ],
|
||||||
|
pub ifr_ifru: ifr_ifru6,
|
||||||
|
}
|
||||||
|
|
||||||
pub const SIOCSIFADDR: c_ulong = request_code_write!(b'i', 12, mem::size_of::<ifreq>());
|
pub const SIOCSIFADDR: c_ulong = request_code_write!(b'i', 12, mem::size_of::<ifreq>());
|
||||||
|
pub const SIOCSIFADDR_IN6: c_ulong = request_code_write!(b'i', 12, mem::size_of::<in6_ifreq>());
|
||||||
pub const SIOCGIFMTU: c_ulong = request_code_readwrite!(b'i', 51, mem::size_of::<ifreq>());
|
pub const SIOCGIFMTU: c_ulong = request_code_readwrite!(b'i', 51, mem::size_of::<ifreq>());
|
||||||
pub const SIOCSIFMTU: c_ulong = request_code_write!(b'i', 52, mem::size_of::<ifreq>());
|
pub const SIOCSIFMTU: c_ulong = request_code_write!(b'i', 52, mem::size_of::<ifreq>());
|
||||||
pub const SIOCGIFNETMASK: c_ulong = request_code_readwrite!(b'i', 37, mem::size_of::<ifreq>());
|
pub const SIOCGIFNETMASK: c_ulong = request_code_readwrite!(b'i', 37, mem::size_of::<ifreq>());
|
||||||
|
|
@ -97,5 +198,6 @@ ioctl_read_bad!(if_get_addr, libc::SIOCGIFADDR, ifreq);
|
||||||
ioctl_read_bad!(if_get_mtu, SIOCGIFMTU, ifreq);
|
ioctl_read_bad!(if_get_mtu, SIOCGIFMTU, ifreq);
|
||||||
ioctl_read_bad!(if_get_netmask, SIOCGIFNETMASK, ifreq);
|
ioctl_read_bad!(if_get_netmask, SIOCGIFNETMASK, ifreq);
|
||||||
ioctl_write_ptr_bad!(if_set_addr, SIOCSIFADDR, ifreq);
|
ioctl_write_ptr_bad!(if_set_addr, SIOCSIFADDR, ifreq);
|
||||||
|
ioctl_write_ptr_bad!(if_set_addr6, SIOCSIFADDR_IN6, in6_ifreq);
|
||||||
ioctl_write_ptr_bad!(if_set_mtu, SIOCSIFMTU, ifreq);
|
ioctl_write_ptr_bad!(if_set_mtu, SIOCSIFMTU, ifreq);
|
||||||
ioctl_write_ptr_bad!(if_set_netmask, SIOCSIFNETMASK, ifreq);
|
ioctl_write_ptr_bad!(if_set_netmask, SIOCSIFNETMASK, ifreq);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use std::{io::Error, net::Ipv4Addr};
|
use std::{io::Error, net::Ipv4Addr};
|
||||||
|
use std::net::Ipv6Addr;
|
||||||
|
|
||||||
use fehler::throws;
|
use fehler::throws;
|
||||||
use tun::TunInterface;
|
use tun::TunInterface;
|
||||||
|
|
@ -33,3 +34,15 @@ fn write_packets() {
|
||||||
let bytes_written = tun.send(&buf)?;
|
let bytes_written = tun.send(&buf)?;
|
||||||
assert_eq!(bytes_written, 1504);
|
assert_eq!(bytes_written, 1504);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[throws]
|
||||||
|
#[ignore = "requires interactivity"]
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
fn set_ipv6() {
|
||||||
|
let tun = TunInterface::new()?;
|
||||||
|
println!("tun name: {:?}", tun.name()?);
|
||||||
|
let targ_addr: Ipv6Addr = "::1".parse().unwrap();
|
||||||
|
println!("v6 addr: {:?}", targ_addr);
|
||||||
|
tun.set_ipv6_addr(targ_addr)?;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue