Skip to content

Commit 9295503

Browse files
authored
Merge pull request #289 from jamesmcm/vopono1011
Vopono v0.10.11
2 parents 62b6026 + 403eaed commit 9295503

27 files changed

+941
-148
lines changed

Cargo.toml

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "vopono"
33
description = "Launch applications via VPN tunnels using temporary network namespaces"
4-
version = "0.10.10"
4+
version = "0.10.11"
55
authors = ["James McMurray <[email protected]>"]
66
edition = "2021"
77
license = "GPL-3.0-or-later"
@@ -19,15 +19,15 @@ directories-next = "2"
1919
log = "0.4"
2020
pretty_env_logger = "0.5"
2121
clap = { version = "4", features = ["derive"] }
22-
which = "6"
22+
which = "7"
2323
dialoguer = "0.11"
2424
compound_duration = "1"
2525
signal-hook = "0.3"
2626
walkdir = "2"
2727
chrono = "0.4"
2828
bs58 = "0.5"
29-
nix = { version = "0.28", features = ["signal", "process"] }
30-
config = "0.14"
29+
nix = { version = "0.29", features = ["signal", "process"] }
30+
config = "0.15"
3131
basic_tcp_proxy = "0.3.2"
3232
strum = "0.26"
3333
strum_macros = "0.26"

USERGUIDE.md

+21-11
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ necessary):
135135
136136
```bash
137137
$ paru -S vopono-bin
138-
$ vopono sync
138+
$ vopono sync --protocol wireguard
139139
```
140140
141141
Run vopono:
@@ -168,7 +168,7 @@ create the OpenVPN configuration files and server lists.
168168
169169
```bash
170170
$ paru -S vopono-bin
171-
$ vopono sync
171+
$ vopono sync --protocol openvpn
172172
```
173173
174174
Run vopono:
@@ -548,9 +548,11 @@ BitTorrent leaking for both the OpenVPN and Wireguard configurations.
548548
### AzireVPN
549549
550550
AzireVPN users can use [their security check page](https://www.azirevpn.com/check)
551-
for the same (note the instructions on disabling WebRTC). I noticed that
552-
when using IPv6 with OpenVPN it incorrectly states you are not connected
553-
via AzireVPN though (Wireguard works correctly).
551+
for the same (note the instructions on disabling WebRTC).
552+
553+
#### OpenVPN Sync
554+
555+
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.
554556
555557
### ProtonVPN
556558
@@ -653,23 +655,31 @@ I recommend using [MozWire](https://github.com/NilsIrl/MozWire) to manage this.
653655
iVPN Wireguard keypairs must be uploaded manually, as the Client Area is
654656
behind a captcha login.
655657
658+
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.
659+
656660
### NordVPN
661+
657662
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.
658663
664+
### AzireVPN
665+
666+
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.
667+
668+
After 30 days you will need to restart vopono to re-create the port forwarding mapping.
669+
670+
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.
671+
672+
Note AzireVPN sometimes has some issues with rate limiting when generating the OpenVPN config files.
673+
659674
## Tunnel Port Forwarding
660675
661676
Some providers allow port forwarding inside the tunnel, so you can open
662677
some ports inside the network namespace which can be accessed via the
663678
Wireguard/OpenVPN tunnel (this can be important for BitTorrent
664679
connectivity, etc.).
665680
666-
For iVPN port forwarding also works the same way, however it is **only
667-
supported for OpenVPN** on iVPN's side. So remember to pass
668-
`--protocol openvpn -o PORTNUMBER` when trying it! Enable port
669-
forwarding in the [Port Forwarding page in the iVPN client area](https://www.ivpn.net/clientarea/vpn/273887).
670-
671681
For AirVPN you must enable the port in [the client area webpage](https://airvpn.org/ports/),
672-
and then use `--protocol openvpn -o PORTNUMBER` as for iVPN.
682+
and then use `--protocol openvpn -o PORTNUMBER`.
673683
674684
## Dependencies
675685

src/args.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl<T: IntoEnumIterator + Clone + Display> ValueEnum for WrappedArg<T> {
2525
let use_input = input.trim().to_string();
2626

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

70+
/// Suppress all output including application output. Note RUST_LOG=off can be used to suppress only vopono log/error output.
71+
#[clap(long = "silent")]
72+
pub silent: bool,
73+
7074
/// read sudo password from program specified in SUDO_ASKPASS environment variable
7175
#[clap(short = 'A', long = "askpass")]
7276
pub askpass: bool,

src/args_config.rs

-2
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,8 @@ impl ArgsConfig {
129129
let hosts = command_else_config_option!(hosts, command, config);
130130
let open_ports = command_else_config_option!(open_ports, command, config);
131131
let forward = command_else_config_option!(forward, command, config);
132-
dbg!(&command.postup); // TODO
133132
let postup = command_else_config_option!(postup, command, config)
134133
.and_then(|p| shellexpand::full(&p).ok().map(|s| s.into_owned()));
135-
dbg!(&postup);
136134
let predown = command_else_config_option!(predown, command, config)
137135
.and_then(|p| shellexpand::full(&p).ok().map(|s| s.into_owned()));
138136
let group = command_else_config_option!(group, command, config);

src/exec.rs

+31-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use vopono_core::config::vpn::{verify_auth, Protocol};
1717
use vopono_core::network::application_wrapper::ApplicationWrapper;
1818
use vopono_core::network::netns::NetworkNamespace;
1919
use vopono_core::network::network_interface::NetworkInterface;
20+
use vopono_core::network::port_forwarding::azirevpn::AzireVpnPortForwarding;
2021
use vopono_core::network::port_forwarding::natpmpc::Natpmpc;
2122
use vopono_core::network::port_forwarding::piapf::Piapf;
2223
use vopono_core::network::port_forwarding::Forwarder;
@@ -25,7 +26,12 @@ use vopono_core::network::sysctl::SysCtl;
2526
use vopono_core::util::{get_config_from_alias, get_existing_namespaces, get_target_subnet};
2627
use vopono_core::util::{parse_command_str, vopono_dir};
2728

28-
pub fn exec(command: ExecCommand, uiclient: &dyn UiClient, verbose: bool) -> anyhow::Result<()> {
29+
pub fn exec(
30+
command: ExecCommand,
31+
uiclient: &dyn UiClient,
32+
verbose: bool,
33+
silent: bool,
34+
) -> anyhow::Result<()> {
2935
// this captures all sigint signals
3036
// ignore for now, they are automatically passed on to the child
3137
let signals = Signals::new([SIGINT])?;
@@ -63,7 +69,7 @@ pub fn exec(command: ExecCommand, uiclient: &dyn UiClient, verbose: bool) -> any
6369
);
6470
synch(
6571
parsed_command.provider.clone(),
66-
Some(parsed_command.protocol.clone()),
72+
&Some(parsed_command.protocol.clone()),
6773
uiclient,
6874
)?;
6975
}
@@ -233,7 +239,7 @@ pub fn exec(command: ExecCommand, uiclient: &dyn UiClient, verbose: bool) -> any
233239
}
234240

235241
if !parsed_command.create_netns_only {
236-
run_application(&parsed_command, forwarder, &ns, signals)?;
242+
run_application(&parsed_command, forwarder, &ns, signals, silent)?;
237243
} else {
238244
info!(
239245
"Created netns {} - will leave network namespace alive until ctrl+C received",
@@ -543,6 +549,26 @@ fn provider_port_forwarding(
543549
parsed_command.port_forwarding_callback.as_ref(),
544550
)?))
545551
}
552+
Some(VpnProvider::AzireVPN) => {
553+
let azirevpn = vopono_core::config::providers::azirevpn::AzireVPN {};
554+
let access_token = azirevpn.read_access_token()?;
555+
556+
if parsed_command.port_forwarding_callback.is_some() {
557+
warn!("Port forwarding callback not supported for AzireVPN - ignoring --port-forwarding-callback");
558+
}
559+
if ns.wireguard.is_none() {
560+
log::error!(
561+
"AzireVPN Port Forwarding in vopono is only supported for Wireguard"
562+
)
563+
}
564+
let endpoint_ip = ns.wireguard.as_ref().map(|wg| wg.interface_addresses[0]);
565+
// TODO: Is OpenVPN possible? Could not get it to work manually
566+
567+
endpoint_ip
568+
.map(|ip| AzireVpnPortForwarding::new(ns, &access_token, ip))
569+
.transpose()?
570+
.map(|fwd| Box::new(fwd) as Box<dyn Forwarder>)
571+
}
546572
Some(p) => {
547573
error!("Port forwarding not supported for the selected provider: {} - ignoring --port-forwarding", p);
548574
None
@@ -568,6 +594,7 @@ fn run_application(
568594
forwarder: Option<Box<dyn Forwarder>>,
569595
ns: &NetworkNamespace,
570596
signals: SignalsInfo,
597+
silent: bool,
571598
) -> anyhow::Result<()> {
572599
let application = ApplicationWrapper::new(
573600
ns,
@@ -576,6 +603,7 @@ fn run_application(
576603
parsed_command.group.clone(),
577604
parsed_command.working_directory.clone().map(PathBuf::from),
578605
forwarder,
606+
silent,
579607
)?;
580608

581609
let pid = application.handle.id();

src/main.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,16 @@ fn main() -> anyhow::Result<()> {
2626
let app = args::App::parse();
2727
// Set up logging
2828
let mut builder = pretty_env_logger::formatted_timed_builder();
29-
let log_level = if app.verbose {
30-
LevelFilter::Debug
31-
} else {
32-
LevelFilter::Info
33-
};
34-
builder.filter_level(log_level);
29+
builder.parse_default_env();
30+
if app.verbose {
31+
builder.filter_level(LevelFilter::Debug);
32+
}
33+
if app.silent {
34+
if app.verbose {
35+
warn!("Verbose and silent flags are mutually exclusive, ignoring verbose flag");
36+
}
37+
builder.filter_level(LevelFilter::Off);
38+
}
3539
builder.init();
3640

3741
let uiclient = CliClient {};
@@ -51,9 +55,10 @@ fn main() -> anyhow::Result<()> {
5155
} else {
5256
debug!("pactl not found, will not set PULSE_SERVER");
5357
}
58+
let verbose = app.verbose && !app.silent;
5459
elevate_privileges(app.askpass)?;
5560
clean_dead_namespaces()?;
56-
exec::exec(cmd, &uiclient, app.verbose)?
61+
exec::exec(cmd, &uiclient, verbose, app.silent)?
5762
}
5863
args::Command::List(listcmd) => {
5964
clean_dead_locks()?;
@@ -62,11 +67,11 @@ fn main() -> anyhow::Result<()> {
6267
args::Command::Synch(synchcmd) => {
6368
// If provider given then sync that, else prompt with menu
6469
if synchcmd.vpn_provider.is_none() {
65-
sync_menu(&uiclient)?;
70+
sync_menu(&uiclient, synchcmd.protocol.map(|x| x.to_variant()))?;
6671
} else {
6772
synch(
6873
synchcmd.vpn_provider.unwrap().to_variant(),
69-
synchcmd.protocol.map(|x| x.to_variant()),
74+
&synchcmd.protocol.map(|x| x.to_variant()),
7075
&uiclient,
7176
)?;
7277
}

src/sync.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use vopono_core::util::set_config_permissions;
88

99
use crate::args::WrappedArg;
1010

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

3636
Ok(())
3737
}
3838

3939
pub fn synch(
4040
provider: VpnProvider,
41-
protocol: Option<Protocol>,
41+
protocol: &Option<Protocol>,
4242
uiclient: &dyn UiClient,
4343
) -> anyhow::Result<()> {
4444
// TODO: Separate availability from functionality, so we can filter disabled protocols from the UI
@@ -67,6 +67,7 @@ pub fn synch(
6767
error!("vopono sync not supported for None protocol");
6868
}
6969
// TODO: Fix this asking for same credentials twice
70+
// Move auth and auth caching to base part of provider then share it for both
7071
None => {
7172
if let Ok(p) = provider.get_dyn_wireguard_provider() {
7273
info!("Starting Wireguard configuration...");

vopono_core/Cargo.toml

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "vopono_core"
33
description = "Library code for running VPN connections in network namespaces"
4-
version = "0.1.10"
4+
version = "0.1.11"
55
edition = "2021"
66
authors = ["James McMurray <[email protected]>"]
77
license = "GPL-3.0-or-later"
@@ -14,9 +14,9 @@ keywords = ["vopono", "vpn", "wireguard", "openvpn", "netns"]
1414
anyhow = "1"
1515
directories-next = "2"
1616
log = "0.4"
17-
which = "6"
17+
which = "7"
1818
users = "0.11"
19-
nix = { version = "0.28", features = ["user", "signal", "fs", "process"] }
19+
nix = { version = "0.29", features = ["user", "signal", "fs", "process"] }
2020
serde = { version = "1", features = ["derive", "std"] }
2121
csv = "1"
2222
regex = "1"
@@ -30,18 +30,19 @@ reqwest = { default-features = false, version = "0.12", features = [
3030
"json",
3131
"rustls-tls",
3232
] } # TODO: Can we remove Tokio dependency?
33-
sysinfo = "0.30"
33+
sysinfo = "0.33"
3434
base64 = "0.22"
3535
x25519-dalek = { version = "2", features = ["static_secrets"] }
3636
strum = "0.26"
3737
strum_macros = "0.26"
38-
zip = "0.6"
38+
zip = "2"
3939
maplit = "1"
40-
webbrowser = "0.8"
40+
webbrowser = "1"
4141
serde_json = "1"
4242
signal-hook = "0.3"
4343
sha2 = "0.10"
4444
tiny_http = "0.12"
4545
chrono = "0.4"
4646
json = "0.12"
4747
shell-words = "1"
48+
dns-lookup = "2"

0 commit comments

Comments
 (0)