Initial commit
This commit is contained in:
commit
ae9fca20ee
8 changed files with 821 additions and 0 deletions
143
src/main.rs
Normal file
143
src/main.rs
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
use std::io::Write;
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::process;
|
||||
|
||||
use clap::Clap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
const BASE_URL: &str = "https://api.azirevpn.com/v1";
|
||||
|
||||
#[derive(Clap, Debug)]
|
||||
struct Opts {
|
||||
#[clap(subcommand)]
|
||||
command: Command,
|
||||
}
|
||||
|
||||
#[derive(Clap, Debug)]
|
||||
struct GetConfigOpts {
|
||||
location: String,
|
||||
username: String,
|
||||
token: String,
|
||||
}
|
||||
|
||||
#[derive(Clap, Debug)]
|
||||
enum Command {
|
||||
List,
|
||||
GetConfig(GetConfigOpts),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Endpoints {
|
||||
wireguard: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Location {
|
||||
name: String,
|
||||
city: String,
|
||||
country: String,
|
||||
iso: String,
|
||||
endpoints: Endpoints,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Locations {
|
||||
locations: Vec<Location>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct WireguardConfig {
|
||||
status: String,
|
||||
data: WireguardConfigData,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
struct WireguardConfigData {
|
||||
public_key: String,
|
||||
address: String,
|
||||
endpoint: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct WireguardKeyPair {
|
||||
public_key: String,
|
||||
private_key: String,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), anyhow::Error> {
|
||||
let opts = Opts::parse();
|
||||
match opts.command {
|
||||
Command::List => list()?,
|
||||
Command::GetConfig(get_config_opts) => get_config(&get_config_opts)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn list() -> Result<(), anyhow::Error> {
|
||||
let locations: Locations = get_locations()?;
|
||||
println!("{:?}", &locations);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_locations() -> Result<Locations, anyhow::Error> {
|
||||
let url = format!("{}/locations", BASE_URL);
|
||||
let locations: Locations = ureq::get(&url).call()?.into_json()?;
|
||||
Ok(locations)
|
||||
}
|
||||
|
||||
fn get_config(opts: &GetConfigOpts) -> Result<(), anyhow::Error> {
|
||||
let locations = get_locations()?;
|
||||
let location = locations
|
||||
.locations
|
||||
.iter()
|
||||
.find(|location| location.name == opts.location)
|
||||
.ok_or_else(|| anyhow::anyhow!("no such location"))?;
|
||||
dbg!(&location);
|
||||
let keys = generage_keys()?;
|
||||
dbg!(&keys);
|
||||
let config: WireguardConfig = ureq::post(&location.endpoints.wireguard)
|
||||
.send_form(&[
|
||||
("username", &opts.username),
|
||||
("token", &opts.token),
|
||||
("pubkey", &keys.public_key),
|
||||
])?
|
||||
.into_json()?;
|
||||
dbg!(&config);
|
||||
let mut endpoint_addrs = config.data.endpoint.to_socket_addrs()?;
|
||||
let endpoint_addr = endpoint_addrs
|
||||
.next()
|
||||
.ok_or_else(|| anyhow::anyhow!("no endpoint address received"))?;
|
||||
dbg!(&endpoint_addr);
|
||||
println!(
|
||||
r"[Interface]
|
||||
PrivateKey = {}
|
||||
Address = {}
|
||||
|
||||
[Peer]
|
||||
PublicKey = {}
|
||||
Endpoint = {}
|
||||
AllowedIPs = 0.0.0.0/0 #, ::/0",
|
||||
&keys.private_key, &config.data.address, &config.data.public_key, &endpoint_addr
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generage_keys() -> Result<WireguardKeyPair, anyhow::Error> {
|
||||
let privkey = process::Command::new("wg").arg("genkey").output()?.stdout;
|
||||
let mut pubkey_cmd = process::Command::new("wg")
|
||||
.arg("pubkey")
|
||||
.stdin(process::Stdio::piped())
|
||||
.stdout(process::Stdio::piped())
|
||||
.spawn()?;
|
||||
pubkey_cmd
|
||||
.stdin
|
||||
.as_mut()
|
||||
.expect("no stdin")
|
||||
.write_all(&privkey)?;
|
||||
let pubkey = pubkey_cmd.wait_with_output()?.stdout;
|
||||
Ok(WireguardKeyPair {
|
||||
private_key: String::from_utf8(privkey)?.trim_end().to_string(),
|
||||
public_key: String::from_utf8(pubkey)?.trim_end().to_string(),
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue