mirror of https://github.com/dswd/vpncloud.git
First Windows plan
This commit is contained in:
parent
edd0e7a29f
commit
82e3ffedf3
|
@ -43,12 +43,6 @@ version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "boxfnonce"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.4.0"
|
version = "3.4.0"
|
||||||
|
@ -106,16 +100,6 @@ version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826"
|
checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "daemonize"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "70c24513e34f53b640819f0ac9f705b673fcf4006d7aab8778bee72ebfc89815"
|
|
||||||
dependencies = [
|
|
||||||
"boxfnonce",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "discard"
|
name = "discard"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
@ -267,31 +251,6 @@ version = "0.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nix"
|
|
||||||
version = "0.14.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"cc",
|
|
||||||
"cfg-if 0.1.10",
|
|
||||||
"libc",
|
|
||||||
"void",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nix"
|
|
||||||
version = "0.19.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"cc",
|
|
||||||
"cfg-if 1.0.0",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.5.2"
|
version = "1.5.2"
|
||||||
|
@ -310,16 +269,6 @@ version = "0.2.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "privdrop"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ebd4c2739642e70439d1c0d9545beec45c1e54128739b3cda29bf2c366028c87"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"nix 0.19.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error"
|
name = "proc-macro-error"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
@ -555,16 +504,6 @@ version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "signal"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2f6ce83b159ab6984d2419f495134972b48754d13ff2e3f8c998339942b56ed9"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"nix 0.14.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.5.1"
|
version = "1.5.1"
|
||||||
|
@ -838,29 +777,20 @@ version = "0.9.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "void"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vpncloud"
|
name = "vpncloud"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"daemonize",
|
|
||||||
"fnv",
|
"fnv",
|
||||||
"igd",
|
"igd",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"privdrop",
|
|
||||||
"rand 0.8.0",
|
"rand 0.8.0",
|
||||||
"ring",
|
"ring",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"signal",
|
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"structopt",
|
"structopt",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
|
|
@ -18,15 +18,15 @@ serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_yaml = "0.8"
|
serde_yaml = "0.8"
|
||||||
log = { version = "0.4", features = ["std"] }
|
log = { version = "0.4", features = ["std"] }
|
||||||
signal = "0.7"
|
#signal = "0.7"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
fnv = "1"
|
fnv = "1"
|
||||||
yaml-rust = "0.4"
|
yaml-rust = "0.4"
|
||||||
igd = { version = "0.11", optional = true }
|
igd = { version = "0.11", optional = true }
|
||||||
daemonize = "0.4"
|
#daemonize = "0.4"
|
||||||
ring = "0.16"
|
ring = "0.16"
|
||||||
privdrop = "0.5"
|
#privdrop = "0.5"
|
||||||
byteorder = "1.3"
|
byteorder = "1.3"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
smallvec = "1.5"
|
smallvec = "1.5"
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
# VpnCloud for Windows
|
||||||
|
|
||||||
|
## Toolchain
|
||||||
|
|
||||||
|
rustup target add x86_64-pc-windows-gnu
|
||||||
|
rustup toolchain install stable-x86_64-pc-windows-gnu
|
||||||
|
apt-get install mingw64
|
||||||
|
|
||||||
|
## Problems
|
||||||
|
|
||||||
|
### Running VpnCloud
|
||||||
|
|
||||||
|
**Problem:**
|
||||||
|
|
||||||
|
- Library "daemonize" does not compile
|
||||||
|
- Windows uses "Services" instead of daemonized processes
|
||||||
|
- Library "privdrop" does not compile
|
||||||
|
- Is dropping privileges in Windows services even a thing?
|
||||||
|
- Library "signal" does not compile
|
||||||
|
- Windows services work differently, no Ctrl-C handling needed
|
||||||
|
- Normal Windows programs can't stay active when the user logs out
|
||||||
|
|
||||||
|
**Potential solution:**
|
||||||
|
|
||||||
|
- Wrap VpnCloud as Windows service
|
||||||
|
- https://github.com/mullvad/windows-service-rs
|
||||||
|
- Do not support dropping privileges under Windows
|
||||||
|
|
||||||
|
### Polling solution
|
||||||
|
|
||||||
|
**Problem:**
|
||||||
|
|
||||||
|
- Epoll is Linux only
|
||||||
|
- RawFd is Unix only
|
||||||
|
|
||||||
|
**Potential solution:**
|
||||||
|
|
||||||
|
Use multi-threading to remove the need to wait on multiple events at the same time:
|
||||||
|
|
||||||
|
- One thread waits on the device and sends to the socket
|
||||||
|
- One thread waits on the socket and sends to the device and handles the control traffic
|
||||||
|
|
||||||
|
Problems to solve:
|
||||||
|
|
||||||
|
- Synchronization is slow
|
||||||
|
- Do not use locking in hot code, cache shared data locally and synchronize periodically
|
||||||
|
|
||||||
|
### Tun/Tap devices
|
||||||
|
|
||||||
|
**Problem:**
|
||||||
|
|
||||||
|
Tun/Tap works completely different on Windows
|
||||||
|
|
||||||
|
- Drivers need to be signed by Microsoft, complicated process
|
||||||
|
|
||||||
|
**Potential solution:**
|
||||||
|
|
||||||
|
Use existing Tun & Tap drivers:
|
||||||
|
|
||||||
|
- (Old) TapWindows from OpenVPN project
|
||||||
|
- https://community.openvpn.net/openvpn/wiki/GettingTapWindows
|
||||||
|
- https://github.com/Tazdevil971/tap-windows
|
||||||
|
|
||||||
|
- (New) WinTun from Wireguard
|
||||||
|
- https://www.wintun.net/
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
**Problem:**
|
||||||
|
|
||||||
|
- Windows users are not used to write config files and execute commands
|
||||||
|
- Windows setup is more complicated than in Linux (install Drivers, register Services, etc.)
|
||||||
|
|
||||||
|
**Potential solution:**
|
||||||
|
|
||||||
|
- Create configuration UI
|
25
src/main.rs
25
src/main.rs
|
@ -189,30 +189,9 @@ fn run<P: Protocol>(config: Config) {
|
||||||
cloud.add_reconnect_peer(addr);
|
cloud.add_reconnect_peer(addr);
|
||||||
}
|
}
|
||||||
if config.daemonize {
|
if config.daemonize {
|
||||||
info!("Running process as daemon");
|
error!("Daemonize not supported under windows");
|
||||||
let mut daemonize = daemonize::Daemonize::new();
|
|
||||||
if let Some(user) = config.user {
|
|
||||||
daemonize = daemonize.user(&user as &str);
|
|
||||||
}
|
|
||||||
if let Some(group) = config.group {
|
|
||||||
daemonize = daemonize.group(&group as &str);
|
|
||||||
}
|
|
||||||
if let Some(pid_file) = config.pid_file {
|
|
||||||
daemonize = daemonize.pid_file(pid_file).chown_pid_file(true);
|
|
||||||
// Give child process some time to write PID file
|
|
||||||
daemonize = daemonize.exit_action(|| thread::sleep(std::time::Duration::from_millis(10)));
|
|
||||||
}
|
|
||||||
try_fail!(daemonize.start(), "Failed to daemonize: {}");
|
|
||||||
} else if config.user.is_some() || config.group.is_some() {
|
} else if config.user.is_some() || config.group.is_some() {
|
||||||
info!("Dropping privileges");
|
error!("Privdrop not supported under windows");
|
||||||
let mut pd = privdrop::PrivDrop::default();
|
|
||||||
if let Some(user) = config.user {
|
|
||||||
pd = pd.user(user);
|
|
||||||
}
|
|
||||||
if let Some(group) = config.group {
|
|
||||||
pd = pd.group(group);
|
|
||||||
}
|
|
||||||
try_fail!(pd.apply(), "Failed to drop privileges: {}");
|
|
||||||
}
|
}
|
||||||
cloud.run();
|
cloud.run();
|
||||||
if let Some(script) = config.ifdown {
|
if let Some(script) = config.ifdown {
|
||||||
|
|
|
@ -12,7 +12,6 @@ use crate::error::Error;
|
||||||
|
|
||||||
#[cfg(not(target_os = "linux"))] use time;
|
#[cfg(not(target_os = "linux"))] use time;
|
||||||
|
|
||||||
use signal::{trap::Trap, Signal};
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
@ -272,7 +271,6 @@ impl fmt::Display for Bytes {
|
||||||
|
|
||||||
pub struct CtrlC {
|
pub struct CtrlC {
|
||||||
dummy_time: Instant,
|
dummy_time: Instant,
|
||||||
trap: Trap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CtrlC {
|
impl CtrlC {
|
||||||
|
@ -281,15 +279,14 @@ impl CtrlC {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn was_pressed(&self) -> bool {
|
pub fn was_pressed(&self) -> bool {
|
||||||
self.trap.wait(self.dummy_time).is_some()
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CtrlC {
|
impl Default for CtrlC {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let dummy_time = Instant::now();
|
let dummy_time = Instant::now();
|
||||||
let trap = Trap::trap(&[Signal::SIGINT, Signal::SIGTERM, Signal::SIGQUIT]);
|
Self { dummy_time }
|
||||||
Self { dummy_time, trap }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue