Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add port forwarding for ProtonVPN connections #240

Merged
merged 2 commits into from
Nov 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ directories-next = "2"
log = "0.4"
pretty_env_logger = "0.5"
clap = { version = "4", features = ["derive"] }
which = "4"
dialoguer = "0.10"
which = "5"
dialoguer = "0.11"
compound_duration = "1"
signal-hook = "0.3"
walkdir = "2"
Expand Down
43 changes: 22 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,31 @@ lynx all running through different VPN connections:

## Supported Providers

| Provider | OpenVPN support | Wireguard support |
| --------------------- | --------------- | ----------------- |
| Mullvad | ✅ | ✅ |
| AzireVPN | ✅ | ✅ |
| iVPN | ✅ | ✅ |
| PrivateInternetAccess | ✅ | ✅\*\* |
| ProtonVPN | ✅ | ❓\* |
| MozillaVPN | ❌ | ✅ |
| NordVPN | ✅ | ❌ |
| HMA (HideMyAss) | ✅ | ❌ |
| AirVPN | ✅ | ❌ |
| Cloudflare Warp\*\*\* | ❌ | ❌ |

\* For ProtonVPN you can generate and download specific Wireguard config
| Provider | OpenVPN support | Wireguard support |
| ----------------------- | --------------- | ----------------- |
| Mullvad | ✅ | ✅ |
| AzireVPN | ✅ | ✅ |
| iVPN | ✅ | ✅ |
| PrivateInternetAccess | ✅ | ✅\* |
| ProtonVPN | ✅\*\* | ✅\*\*\* |
| MozillaVPN | ❌ | ✅ |
| NordVPN | ✅ | ❌ |
| HMA (HideMyAss) | ✅ | ❌ |
| AirVPN | ✅ | ❌ |
| Cloudflare Warp\*\*\*\* | ❌ | ❌ |

\* Port forwarding is not currently supported for PrivateInternetAccess. PRs welcome.

\*\* See the [User Guide](USERGUIDE.md) for authentication instructions for generating the OpenVPN config files via `vopono sync`. You must copy the authentication header of the form `AUTH-xxx=yyy` where `yyy` is the value of the `x-pm-uid` header in the same request when logged in, in your web browser.

\*\*\* For ProtonVPN you can generate and download specific Wireguard config
files, and use them as a custom provider config. See the [User Guide](USERGUIDE.md)
for details - note that port forwarding is currently not supported for ProtonVPN.
for details. [Port Forwarding](https://protonvpn.com/support/port-forwarding-manual-setup/) is supported with the `--protonvpn-port-forwarding` argument for both OpenVPN and Wireguard (with `--provider custom --custom xxx.conf --protocol wireguard` ), note for OpenVPN you must generate the OpenVPN config files appending `+pmp` to your OpenVPN username, and you must choose servers which support this feature (e.g. at the time of writing, the Romania servers do). The assigned port is then printed to the terminal where vopono was launched - this should then be set in any applications that require it.

\*\* Port forwarding is not currently supported for PrivateInternetAccess.

\*\*\* Cloudflare Warp uses its own protocol. Set both the provider and
protocol to `warp`. Note you must first register with `sudo warp-cli
register` and then run it once with `sudo warp-svc` and `sudo warp-cli
connect` outside of vopono. Please verify this works first before trying
it with vopono.
\*\*\*\* Cloudflare Warp uses its own protocol. Set both the provider and
protocol to `warp`. Note you must first register with `sudo warp-cli register` and then run it once with `sudo warp-svc` and `sudo warp-cli connect` outside of vopono. Please verify this works first before trying it with vopono.


## Usage

Expand Down
50 changes: 39 additions & 11 deletions USERGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -438,21 +438,60 @@ Mullvad wireguard usa-us52.conf

## VPN Provider specific details

### Mullvad

Mullvad users can use [mullvad.net/en/check](https://mullvad.net/en/check/) to
check the security of their browser's connection. This was used with the
Mullvad configuration to verify that there is no DNS leaking or
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).

### ProtonVPN

#### OpenVPN Sync and authentication

ProtonVPN users must log-in to the dashboard via a web browser during
the `vopono sync` process in order to copy the `AUTH-*` cookie to
access the OpenVPN configuration files, and the OpenVPN specific
credentials to use them.

Note that there may be multiple `AUTH-xxx=yyy` cookies - the specific one we need is where `xxx` is equal to the value of the `x-pm-uid` header in the same request.

![AUTH cookie example](protonvpn_header.png)

#### Wireguard servers

Due to the way Wireguard configuration generation is handled, this should be
generated online and then used as a custom configuration, e.g.:

```bash
$ vopono -v exec --provider custom --custom testwg-UK-17.conf --protocol wireguard --protonvpn-port-forwarding firefox-developer-edition
```

#### Port Forwarding

Port forwarding can be enabled with the `--protonvpn-port-forwarding` argument, but requires using a server that supports port forwarding.

Note for OpenVPN you must generate the OpenVPN config files appending `+pmp` to your OpenVPN username (i.e. what will be written to `~/.config/vopono/proton/openvpn/auth.txt`)

Note the usual `-o` / `--open-ports` argument has no effect here as we only know the port number assigned after connecting to ProtonVPN.

The port you are allocated will then be printed to the console like:
```
2023-11-04T14:47:31.416Z INFO vopono::exec > ProtonVPN Port Forwarding on port 62508
```

And that is the port you would then set up in applications that require it.

### Cloudflare Warp

Cloudflare Warp users must first register with Warp via the CLI client:
```
$ sudo warp-cli register
Expand All @@ -470,17 +509,6 @@ $ vopono -v exec --no-killswitch --provider warp --protocol warp firefox-develop

### VPN Provider limitations

#### ProtonVPN

Due to the way Wireguard configuration is handled, this should be
generated online and then used as a custom configuration, e.g.:

```bash
$ vopono -v exec --provider custom --custom testwg-UK-17.conf --protocol wireguard firefox-developer-edition
```

Note that port forwarding is currently not supported for ProtonVPN.

#### PrivateInternetAccess

Wireguard support for PrivateInternetAccess (PIA) requires the use of a
Expand Down
Binary file added protonvpn_header.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ pub struct ExecCommand {
/// Useful for accessing services on the host locally
#[clap(long = "allow-host-access")]
pub allow_host_access: bool,

/// Enable port forwarding for ProtonVPN connections
#[clap(long = "protonvpn-port-forwarding")]
pub protonvpn_port_forwarding: bool,
}

#[derive(Parser)]
Expand Down
17 changes: 7 additions & 10 deletions src/cli_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,23 @@ impl UiClient for CliClient {
}

fn get_input(&self, inp: Input) -> anyhow::Result<String> {
let mut d = dialoguer::Input::<String>::new();

d.with_prompt(&inp.prompt);
let mut d = dialoguer::Input::<String>::new().with_prompt(&inp.prompt);

if inp.validator.is_some() {
d.validate_with(inp.validator.unwrap());
d = d.validate_with(inp.validator.unwrap());
};

Ok(d.interact()?)
}

fn get_input_numeric_u16(&self, inp: InputNumericu16) -> anyhow::Result<u16> {
let mut d = dialoguer::Input::<u16>::new();
d.with_prompt(&inp.prompt);
let mut d = dialoguer::Input::<u16>::new().with_prompt(&inp.prompt);

if inp.default.is_some() {
d.default(inp.default.unwrap());
d = d.default(inp.default.unwrap());
}
if inp.validator.is_some() {
d.validate_with(inp.validator.unwrap());
d = d.validate_with(inp.validator.unwrap());
}

Ok(d.interact()?)
Expand All @@ -66,9 +63,9 @@ impl UiClient for CliClient {
fn get_password(&self, pw: Password) -> anyhow::Result<String> {
let mut req = dialoguer::Password::new();
if pw.confirm {
req.with_confirmation("Confirm password", "Passwords did not match");
req = req.with_confirmation("Confirm password", "Passwords did not match");
};
req.with_prompt(pw.prompt);
req = req.with_prompt(pw.prompt);
Ok(req.interact()?)
}
}
Loading
Loading