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 PIA Wireguard support #183

Merged
merged 2 commits into from
Aug 21, 2022
Merged

Add PIA Wireguard support #183

merged 2 commits into from
Aug 21, 2022

Conversation

mobad
Copy link
Contributor

@mobad mobad commented Aug 21, 2022

Wireguard with PIA works a bit differently:

  • Before you connect you must call their addKey API on the server
    you're connecting to
  • PersistentKeepalive is necessary as if there is no network traffic your key will be removed

Resolves #9

Wireguard with PIA works a bit differently:
- Before you connect you must call their addKey API on the server
  you're connecting to
- PersistentKeepalive is necessary as if there is no network traffic your key will be removed
@mobad
Copy link
Contributor Author

mobad commented Aug 21, 2022

@jamesmcm This is what I have so far.

The way things work is during sync we generate a Wireguard config with some placeholder values, then on wireguard_preup we get the values we need then overwrite the config file, then the Wireguard stuff connects using the new config.

I wasn't able to keep everything I needed directly in the Wireguard config files so I had to add some stuff to a config.txt which is created on sync. It contains: user, pass, pubkey, mapping of domain->IP (This is needed to validate TLS cert on addKey)

Only some small changes were needed outside of pia/wireguard.
I had to add support for PersistentKeepalive which unfortunately touched some other configurations.
If we need to add more then it might make sense to turn it in to a builder but for just this one it seems like overkill.

I also added FromStr and TryInto for Wireguard config but I didn't convert the other usages in the other configs and in the Wireguard setup but it would probably be a good idea for the future.

I'll clean up the clippy lints tomorrow but let me know if you have any comments or suggestions.

@jamesmcm
Copy link
Owner

Thanks, it looks good, I like the wireguard_preup solution!

Could you please fix the 8 Clippy issues:

 error: unneeded `return` statement
   --> vopono_core/src/config/providers/pia/wireguard.rs:104:39
    |
104 |             PiaToken::Ok { token } => return Ok(token),
    |                                       ^^^^^^^^^^^^^^^^ help: remove `return`: `Ok(token)`
    |
    = note: `-D clippy::needless-return` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_return

error: unneeded `return` statement
   --> vopono_core/src/config/providers/pia/wireguard.rs:105:42
    |
105 |             PiaToken::Err { message } => return Err(anyhow!("{}", message)),
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `Err(anyhow!("{}", message))`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_return

error: unneeded `return` statement
   --> vopono_core/src/config/providers/pia/wireguard.rs:132:60
    |
132 |             WireguardServerInfoRequest::Ok(server_info) => return Ok(server_info),
    |                                                            ^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `Ok(server_info)`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_return

error: unneeded `return` statement
   --> vopono_core/src/config/providers/pia/wireguard.rs:133:60
    |
133 |             WireguardServerInfoRequest::Err { message } => return Err(anyhow!("{}", message)),
    |                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `Err(anyhow!("{}", message))`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_return

error: using `clone` on type `std::net::IpAddr` which implements the `Copy` trait
   --> vopono_core/src/config/providers/pia/wireguard.rs:123:27
    |
123 |             .resolve(cn, (ip.clone(), PrivateInternetAccess::PORT).into())
    |                           ^^^^^^^^^^ help: try dereferencing it: `*ip`
    |
    = note: `-D clippy::clone-on-copy` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy

error: useless conversion to the same type: `std::net::IpAddr`
   --> vopono_core/src/config/providers/pia/wireguard.rs:198:25
    |
198 |                         IpAddr::from(wg_server.ip),
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `IpAddr::from()`: `wg_server.ip`
    |
    = note: `-D clippy::useless-conversion` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion

error: useless conversion to the same type: `std::net::IpAddr`
   --> vopono_core/src/config/providers/pia/wireguard.rs:246:55
    |
246 |         wg_config.interface.address = vec![IpNet::new(server_info.peer_ip.into(), 32)?];
    |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `server_info.peer_ip`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion

error: this expression creates a reference which is immediately dereferenced by the compiler
   --> vopono_core/src/network/wireguard.rs:547:26
    |
547 |             .replace_all(&config_string, "$key = \"$value\"")
    |                          ^^^^^^^^^^^^^^ help: change this to: `config_string`
    |
    = note: `-D clippy::needless-borrow` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

They're mainly just small changes for redundant code - you can run clippy locally with cargo clippy

@jamesmcm
Copy link
Owner

Thanks, it looks good - is there anything to add to the README or USERGUIDE docs that users should be aware of?

@jamesmcm jamesmcm merged commit a5baaa2 into jamesmcm:master Aug 21, 2022
@mobad
Copy link
Contributor Author

mobad commented Aug 21, 2022

I think the main thing would be if you're running in to connection problems then try a sync (server could have been deleted etc) but I think that applies to most providers. Otherwise it should appear identical to a normal wg provider to the user.

The connection should last until the server reboots but I haven't had a chance to test leaving it running for a long time yet but it should perform identically to the official https://github.com/pia-foss/manual-connections/blob/master/connect_to_wireguard_with_token.sh

@jamesmcm jamesmcm mentioned this pull request Aug 21, 2022
@coquizen
Copy link
Contributor

Does this provide a namespaced environment variable for port forwards? For example, if you are trying to run transmission-daemon, you would want to specify which port to use to accept peer connections.

@jamesmcm
Copy link
Owner

vopono exec -o {portnumber} ... should allow port forwarding that way e.g. over the tunnel to the internet, and -f {portnumber} for exposing the port on the app inside the netns to the host e.g. the web interface for transmission-daemon.

@coquizen
Copy link
Contributor

coquizen commented Apr 21, 2023

Except PIA provides a random port number on each connect init:

When you connect to the server location of your choice that offers port forwarding, a random port will automatically be assigned.

@jamesmcm
Copy link
Owner

Oh it seems this PR doesn't do it atm, but I think the best approach if possible would be to get that port (from the API?) and then always open that port (there we can use the existing code) and print it out for the user.

I don't have a PIA account to test this with atm though.

@mobad
Copy link
Contributor Author

mobad commented Apr 22, 2023

@coquizen The problem with doing it in vopono is that with port forwarding you not only get a random port you also need to confirm that you're still using it every 15 min by polling an API.
The way I do it is I have a script that I call instead of my torrent client which then runs the get_token and port_forwarding scripts from https://github.com/pia-foss/manual-connections and configures my torrent client with the port.

#!/bin/bash

export PF_GATEWAY="$(sudo wg | sed -rn "s/.*endpoint: (.*):.*/\1/p")"
export PF_HOSTNAME="fake"

/opt/manual-connections/get_token.sh
export PIA_TOKEN="$(awk 'NR == 1' /tmp/pia-token)"

rm /tmp/piaport.run 2>/dev/null
/opt/manual-connections/port_forwarding.sh &

while [[ ! -e /tmp/piaport.run ]]; do
    echo "No port"
    sleep 1
done

qbitPort.sh

/usr/bin/qbittorrent

pids="$(jobs -p)"
kill $pids
wait $pids

qbitPort gets that random port then configures it in qbittorrent but it should be possible to do something similar with transmission

#!/bin/bash

read port < /tmp/piaport.run
enable="false"
if [[ "$port" == "" ]]; then
	port=0
	enable="true"
fi

sed "s/\(Session\\\Port=\).*/\1$port/" -i ~/.config/qBittorrent/qBittorrent.conf
curl -Lsm5 -A '' 'https://127.0.0.1:8181/api/v2/app/setPreferences' -d "json=%7B%22listen_port%22%3A$port%2C%22upnp%22%3A$enable%7D"

Both scripts are pretty rough but should be enough to get things working for you with a bit of work.
Oh I think I also modified port_forwarding to write the port to /tmp/piaport.run and changed where get_token writes the token to and made it run without root.

If anyone figures out a better way lemme know.

@jamesmcm
Copy link
Owner

Thanks, I think we could run that in a thread while vopono is running i.e. the loop on line 133 https://github.com/pia-foss/manual-connections/blob/master/port_forwarding.sh#L133-L156

It's a bit similar to how we handle the Ctrl+C SIGINT signals to ensure it kills all parts.

But both modifying the open port dynamically, and creating a thread for this (which should also handle errors) will be a fair amount of PIA-specific code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add PrivateInternetAccess Wireguard support
3 participants