Skip to content

Commit

Permalink
Merge pull request #289 from jamesmcm/vopono1011
Browse files Browse the repository at this point in the history
Vopono v0.10.11
  • Loading branch information
jamesmcm authored Dec 30, 2024
2 parents 62b6026 + 403eaed commit 9295503
Show file tree
Hide file tree
Showing 27 changed files with 941 additions and 148 deletions.
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "vopono"
description = "Launch applications via VPN tunnels using temporary network namespaces"
version = "0.10.10"
version = "0.10.11"
authors = ["James McMurray <[email protected]>"]
edition = "2021"
license = "GPL-3.0-or-later"
Expand All @@ -19,15 +19,15 @@ directories-next = "2"
log = "0.4"
pretty_env_logger = "0.5"
clap = { version = "4", features = ["derive"] }
which = "6"
which = "7"
dialoguer = "0.11"
compound_duration = "1"
signal-hook = "0.3"
walkdir = "2"
chrono = "0.4"
bs58 = "0.5"
nix = { version = "0.28", features = ["signal", "process"] }
config = "0.14"
nix = { version = "0.29", features = ["signal", "process"] }
config = "0.15"
basic_tcp_proxy = "0.3.2"
strum = "0.26"
strum_macros = "0.26"
Expand Down
32 changes: 21 additions & 11 deletions USERGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ necessary):
```bash
$ paru -S vopono-bin
$ vopono sync
$ vopono sync --protocol wireguard
```
Run vopono:
Expand Down Expand Up @@ -168,7 +168,7 @@ create the OpenVPN configuration files and server lists.
```bash
$ paru -S vopono-bin
$ vopono sync
$ vopono sync --protocol openvpn
```
Run vopono:
Expand Down Expand Up @@ -548,9 +548,11 @@ BitTorrent leaking for both the OpenVPN and Wireguard configurations.
### AzireVPN
AzireVPN users can use [their security check page](https://www.azirevpn.com/check)
for the same (note the instructions on disabling WebRTC). I noticed that
when using IPv6 with OpenVPN it incorrectly states you are not connected
via AzireVPN though (Wireguard works correctly).
for the same (note the instructions on disabling WebRTC).
#### OpenVPN Sync
Since AzireVPN now puts the OpenVPN configurations behind authentication, it is necessary to copy the value of the `az` cookie in order to authenticate `vopono sync` when generating the OpenVPN configuration files.
### ProtonVPN
Expand Down Expand Up @@ -653,23 +655,31 @@ I recommend using [MozWire](https://github.com/NilsIrl/MozWire) to manage this.
iVPN Wireguard keypairs must be uploaded manually, as the Client Area is
behind a captcha login.
Note [iVPN no longer supports port forwarding](https://www.ivpn.net/blog/gradual-removal-of-port-forwarding). At the time of writing, ProtonVPN is the best provider with this service.
### NordVPN
Starting 27 June 2023, the required user credentials are no longer your NordVPN login details but need to be generated in the user control panel, under Services → NordVPN. Scroll down and locate the Manual Setup tab, then click on Set up NordVPN manually and follow instructions. Copy your service credentials and re-sync NordVPN configuration inside Vopono.
### AzireVPN
For AzireVPN port forwarding is only possible for Wireguard and can be enabled by using `--port-forwarding`. This will create a port forwarding mapping for the current Wireguard device for 30 days.
After 30 days you will need to restart vopono to re-create the port forwarding mapping.
Note vopono attempts to delete the created mapping when vopono is closed, but this may not always succeed. However, it will use an existing mapping for the chosen device and server pair, if one still exists on AzireVPN's side.
Note AzireVPN sometimes has some issues with rate limiting when generating the OpenVPN config files.
## Tunnel Port Forwarding
Some providers allow port forwarding inside the tunnel, so you can open
some ports inside the network namespace which can be accessed via the
Wireguard/OpenVPN tunnel (this can be important for BitTorrent
connectivity, etc.).
For iVPN port forwarding also works the same way, however it is **only
supported for OpenVPN** on iVPN's side. So remember to pass
`--protocol openvpn -o PORTNUMBER` when trying it! Enable port
forwarding in the [Port Forwarding page in the iVPN client area](https://www.ivpn.net/clientarea/vpn/273887).
For AirVPN you must enable the port in [the client area webpage](https://airvpn.org/ports/),
and then use `--protocol openvpn -o PORTNUMBER` as for iVPN.
and then use `--protocol openvpn -o PORTNUMBER`.
## Dependencies
Expand Down
6 changes: 5 additions & 1 deletion src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl<T: IntoEnumIterator + Clone + Display> ValueEnum for WrappedArg<T> {
let use_input = input.trim().to_string();

let found = if ignore_case {
T::iter().find(|x| x.to_string().to_ascii_lowercase() == use_input.to_ascii_lowercase())
T::iter().find(|x| x.to_string().eq_ignore_ascii_case(&use_input))
} else {
T::iter().find(|x| x.to_string() == use_input)
};
Expand Down Expand Up @@ -67,6 +67,10 @@ pub struct App {
#[clap(short = 'v', long = "verbose")]
pub verbose: bool,

/// Suppress all output including application output. Note RUST_LOG=off can be used to suppress only vopono log/error output.
#[clap(long = "silent")]
pub silent: bool,

/// read sudo password from program specified in SUDO_ASKPASS environment variable
#[clap(short = 'A', long = "askpass")]
pub askpass: bool,
Expand Down
2 changes: 0 additions & 2 deletions src/args_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,8 @@ impl ArgsConfig {
let hosts = command_else_config_option!(hosts, command, config);
let open_ports = command_else_config_option!(open_ports, command, config);
let forward = command_else_config_option!(forward, command, config);
dbg!(&command.postup); // TODO
let postup = command_else_config_option!(postup, command, config)
.and_then(|p| shellexpand::full(&p).ok().map(|s| s.into_owned()));
dbg!(&postup);
let predown = command_else_config_option!(predown, command, config)
.and_then(|p| shellexpand::full(&p).ok().map(|s| s.into_owned()));
let group = command_else_config_option!(group, command, config);
Expand Down
34 changes: 31 additions & 3 deletions src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use vopono_core::config::vpn::{verify_auth, Protocol};
use vopono_core::network::application_wrapper::ApplicationWrapper;
use vopono_core::network::netns::NetworkNamespace;
use vopono_core::network::network_interface::NetworkInterface;
use vopono_core::network::port_forwarding::azirevpn::AzireVpnPortForwarding;
use vopono_core::network::port_forwarding::natpmpc::Natpmpc;
use vopono_core::network::port_forwarding::piapf::Piapf;
use vopono_core::network::port_forwarding::Forwarder;
Expand All @@ -25,7 +26,12 @@ use vopono_core::network::sysctl::SysCtl;
use vopono_core::util::{get_config_from_alias, get_existing_namespaces, get_target_subnet};
use vopono_core::util::{parse_command_str, vopono_dir};

pub fn exec(command: ExecCommand, uiclient: &dyn UiClient, verbose: bool) -> anyhow::Result<()> {
pub fn exec(
command: ExecCommand,
uiclient: &dyn UiClient,
verbose: bool,
silent: bool,
) -> anyhow::Result<()> {
// this captures all sigint signals
// ignore for now, they are automatically passed on to the child
let signals = Signals::new([SIGINT])?;
Expand Down Expand Up @@ -63,7 +69,7 @@ pub fn exec(command: ExecCommand, uiclient: &dyn UiClient, verbose: bool) -> any
);
synch(
parsed_command.provider.clone(),
Some(parsed_command.protocol.clone()),
&Some(parsed_command.protocol.clone()),
uiclient,
)?;
}
Expand Down Expand Up @@ -233,7 +239,7 @@ pub fn exec(command: ExecCommand, uiclient: &dyn UiClient, verbose: bool) -> any
}

if !parsed_command.create_netns_only {
run_application(&parsed_command, forwarder, &ns, signals)?;
run_application(&parsed_command, forwarder, &ns, signals, silent)?;
} else {
info!(
"Created netns {} - will leave network namespace alive until ctrl+C received",
Expand Down Expand Up @@ -543,6 +549,26 @@ fn provider_port_forwarding(
parsed_command.port_forwarding_callback.as_ref(),
)?))
}
Some(VpnProvider::AzireVPN) => {
let azirevpn = vopono_core::config::providers::azirevpn::AzireVPN {};
let access_token = azirevpn.read_access_token()?;

if parsed_command.port_forwarding_callback.is_some() {
warn!("Port forwarding callback not supported for AzireVPN - ignoring --port-forwarding-callback");
}
if ns.wireguard.is_none() {
log::error!(
"AzireVPN Port Forwarding in vopono is only supported for Wireguard"
)
}
let endpoint_ip = ns.wireguard.as_ref().map(|wg| wg.interface_addresses[0]);
// TODO: Is OpenVPN possible? Could not get it to work manually

endpoint_ip
.map(|ip| AzireVpnPortForwarding::new(ns, &access_token, ip))
.transpose()?
.map(|fwd| Box::new(fwd) as Box<dyn Forwarder>)
}
Some(p) => {
error!("Port forwarding not supported for the selected provider: {} - ignoring --port-forwarding", p);
None
Expand All @@ -568,6 +594,7 @@ fn run_application(
forwarder: Option<Box<dyn Forwarder>>,
ns: &NetworkNamespace,
signals: SignalsInfo,
silent: bool,
) -> anyhow::Result<()> {
let application = ApplicationWrapper::new(
ns,
Expand All @@ -576,6 +603,7 @@ fn run_application(
parsed_command.group.clone(),
parsed_command.working_directory.clone().map(PathBuf::from),
forwarder,
silent,
)?;

let pid = application.handle.id();
Expand Down
23 changes: 14 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ fn main() -> anyhow::Result<()> {
let app = args::App::parse();
// Set up logging
let mut builder = pretty_env_logger::formatted_timed_builder();
let log_level = if app.verbose {
LevelFilter::Debug
} else {
LevelFilter::Info
};
builder.filter_level(log_level);
builder.parse_default_env();
if app.verbose {
builder.filter_level(LevelFilter::Debug);
}
if app.silent {
if app.verbose {
warn!("Verbose and silent flags are mutually exclusive, ignoring verbose flag");
}
builder.filter_level(LevelFilter::Off);
}
builder.init();

let uiclient = CliClient {};
Expand All @@ -51,9 +55,10 @@ fn main() -> anyhow::Result<()> {
} else {
debug!("pactl not found, will not set PULSE_SERVER");
}
let verbose = app.verbose && !app.silent;
elevate_privileges(app.askpass)?;
clean_dead_namespaces()?;
exec::exec(cmd, &uiclient, app.verbose)?
exec::exec(cmd, &uiclient, verbose, app.silent)?
}
args::Command::List(listcmd) => {
clean_dead_locks()?;
Expand All @@ -62,11 +67,11 @@ fn main() -> anyhow::Result<()> {
args::Command::Synch(synchcmd) => {
// If provider given then sync that, else prompt with menu
if synchcmd.vpn_provider.is_none() {
sync_menu(&uiclient)?;
sync_menu(&uiclient, synchcmd.protocol.map(|x| x.to_variant()))?;
} else {
synch(
synchcmd.vpn_provider.unwrap().to_variant(),
synchcmd.protocol.map(|x| x.to_variant()),
&synchcmd.protocol.map(|x| x.to_variant()),
&uiclient,
)?;
}
Expand Down
7 changes: 4 additions & 3 deletions src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use vopono_core::util::set_config_permissions;

use crate::args::WrappedArg;

pub fn sync_menu(uiclient: &dyn UiClient) -> anyhow::Result<()> {
pub fn sync_menu(uiclient: &dyn UiClient, protocol: Option<Protocol>) -> anyhow::Result<()> {
let variants = WrappedArg::<VpnProvider>::value_variants()
.iter()
.filter(|x| {
Expand All @@ -30,15 +30,15 @@ pub fn sync_menu(uiclient: &dyn UiClient) -> anyhow::Result<()> {
.into_iter()
.flat_map(|x| WrappedArg::<VpnProvider>::from_str(&variants[x], true))
{
synch(provider.to_variant(), None, uiclient)?;
synch(provider.to_variant(), &protocol, uiclient)?;
}

Ok(())
}

pub fn synch(
provider: VpnProvider,
protocol: Option<Protocol>,
protocol: &Option<Protocol>,
uiclient: &dyn UiClient,
) -> anyhow::Result<()> {
// TODO: Separate availability from functionality, so we can filter disabled protocols from the UI
Expand Down Expand Up @@ -67,6 +67,7 @@ pub fn synch(
error!("vopono sync not supported for None protocol");
}
// TODO: Fix this asking for same credentials twice
// Move auth and auth caching to base part of provider then share it for both
None => {
if let Ok(p) = provider.get_dyn_wireguard_provider() {
info!("Starting Wireguard configuration...");
Expand Down
13 changes: 7 additions & 6 deletions vopono_core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "vopono_core"
description = "Library code for running VPN connections in network namespaces"
version = "0.1.10"
version = "0.1.11"
edition = "2021"
authors = ["James McMurray <[email protected]>"]
license = "GPL-3.0-or-later"
Expand All @@ -14,9 +14,9 @@ keywords = ["vopono", "vpn", "wireguard", "openvpn", "netns"]
anyhow = "1"
directories-next = "2"
log = "0.4"
which = "6"
which = "7"
users = "0.11"
nix = { version = "0.28", features = ["user", "signal", "fs", "process"] }
nix = { version = "0.29", features = ["user", "signal", "fs", "process"] }
serde = { version = "1", features = ["derive", "std"] }
csv = "1"
regex = "1"
Expand All @@ -30,18 +30,19 @@ reqwest = { default-features = false, version = "0.12", features = [
"json",
"rustls-tls",
] } # TODO: Can we remove Tokio dependency?
sysinfo = "0.30"
sysinfo = "0.33"
base64 = "0.22"
x25519-dalek = { version = "2", features = ["static_secrets"] }
strum = "0.26"
strum_macros = "0.26"
zip = "0.6"
zip = "2"
maplit = "1"
webbrowser = "0.8"
webbrowser = "1"
serde_json = "1"
signal-hook = "0.3"
sha2 = "0.10"
tiny_http = "0.12"
chrono = "0.4"
json = "0.12"
shell-words = "1"
dns-lookup = "2"
Loading

0 comments on commit 9295503

Please sign in to comment.