Migrate to API v2
This commit is contained in:
parent
61bb0dd397
commit
8b79f11b39
3 changed files with 48 additions and 78 deletions
122
src/main.rs
122
src/main.rs
|
|
@ -1,5 +1,5 @@
|
|||
use std::io::Write;
|
||||
use std::net::{AddrParseError, IpAddr, ToSocketAddrs};
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
use std::process;
|
||||
|
||||
use log::debug;
|
||||
|
|
@ -7,7 +7,7 @@ use log::debug;
|
|||
use clap::{Parser, Subcommand};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
const BASE_URL: &str = "https://api.azirevpn.com/v1";
|
||||
const BASE_URL: &str = "https://api.azirevpn.com/v2";
|
||||
|
||||
/// AzireVPN client
|
||||
#[derive(Parser, Debug)]
|
||||
|
|
@ -37,18 +37,16 @@ struct ConfigOpts {
|
|||
#[derive(Subcommand, Debug)]
|
||||
enum Command {
|
||||
/// Prints the list of VPN endpoints
|
||||
Endpoints,
|
||||
Locations,
|
||||
|
||||
/// Prints WireGuard config
|
||||
Config(ConfigOpts),
|
||||
|
||||
/// Checks connection status
|
||||
Check,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Endpoints {
|
||||
wireguard: String,
|
||||
struct Locations {
|
||||
status: String,
|
||||
locations: Vec<Location>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
|
@ -57,36 +55,27 @@ struct Location {
|
|||
city: String,
|
||||
country: String,
|
||||
iso: String,
|
||||
endpoints: Endpoints,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Locations {
|
||||
locations: Vec<Location>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct CheckResult {
|
||||
connected: bool,
|
||||
ip: String, // XXX
|
||||
location: Option<String>,
|
||||
pool: String,
|
||||
pubkey: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct WireguardConfig {
|
||||
status: String,
|
||||
data: WireguardConfigData,
|
||||
ipv4: WireguardConfigIpv4,
|
||||
ipv6: WireguardConfigIpv6,
|
||||
dns: Vec<IpAddr>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
struct WireguardConfigData {
|
||||
public_key: String,
|
||||
address: String,
|
||||
endpoint: String,
|
||||
|
||||
#[serde(rename = "DNS")]
|
||||
dns: String,
|
||||
struct WireguardConfigIpv4 {
|
||||
address: Ipv4Addr,
|
||||
netmask: u8,
|
||||
}
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct WireguardConfigIpv6 {
|
||||
address: Ipv6Addr,
|
||||
netmask: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -95,34 +84,17 @@ struct WireguardKeyPair {
|
|||
private_key: String,
|
||||
}
|
||||
|
||||
impl WireguardConfigData {
|
||||
fn addresses(&self) -> Result<Vec<ipnet::IpNet>, ipnet::AddrParseError> {
|
||||
self.address
|
||||
.split(',')
|
||||
.map(|s: &str| -> Result<ipnet::IpNet, ipnet::AddrParseError> { s.trim().parse() })
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn dns(&self) -> Result<Vec<IpAddr>, AddrParseError> {
|
||||
self.dns
|
||||
.split(',')
|
||||
.map(|s: &str| -> Result<IpAddr, AddrParseError> { s.trim().parse() })
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), anyhow::Error> {
|
||||
env_logger::init();
|
||||
let opts = Opts::parse();
|
||||
match &opts.command {
|
||||
Command::Endpoints => list_endpoints(&opts)?,
|
||||
Command::Locations => list_locations(&opts)?,
|
||||
Command::Config(get_config_opts) => get_config(&opts, get_config_opts)?,
|
||||
Command::Check => check(&opts)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn list_endpoints(opts: &Opts) -> Result<(), anyhow::Error> {
|
||||
fn list_locations(opts: &Opts) -> Result<(), anyhow::Error> {
|
||||
let locations: Locations = get_locations()?;
|
||||
if opts.json {
|
||||
println!("{}", serde_json::to_string(&locations)?);
|
||||
|
|
@ -135,7 +107,8 @@ fn list_endpoints(opts: &Opts) -> Result<(), anyhow::Error> {
|
|||
println!("City: {}", location.city);
|
||||
println!("Country: {}", location.country);
|
||||
println!("Country code: {}", location.iso);
|
||||
println!("WireGuard endpoint: {}", location.endpoints.wireguard);
|
||||
println!("Pool: {}", location.pool);
|
||||
println!("Pubkey: {}", location.pubkey);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -151,33 +124,46 @@ fn get_config(_opts: &Opts, config_opts: &ConfigOpts) -> Result<(), anyhow::Erro
|
|||
debug!("location = {:?}", &location);
|
||||
let keys = generage_keys()?;
|
||||
debug!("keys = {:?}", &keys);
|
||||
let config: WireguardConfig = ureq::post(&location.endpoints.wireguard)
|
||||
let url = format!("{}/ip/add", BASE_URL);
|
||||
let config: WireguardConfig = ureq::post(&url)
|
||||
.send_form(&[
|
||||
("username", &config_opts.username),
|
||||
("token", &config_opts.token),
|
||||
("pubkey", &keys.public_key),
|
||||
("key", &keys.public_key),
|
||||
])?
|
||||
.into_json()?;
|
||||
debug!("response = {:?}", &config);
|
||||
debug!("config = {:?}", &config);
|
||||
|
||||
write_config(&mut std::io::stdout().lock(), config_opts, &config, &keys)
|
||||
write_config(
|
||||
&mut std::io::stdout().lock(),
|
||||
config_opts,
|
||||
location,
|
||||
&config,
|
||||
&keys,
|
||||
)
|
||||
}
|
||||
|
||||
fn write_config(
|
||||
output: &mut dyn Write,
|
||||
config_opts: &ConfigOpts,
|
||||
location: &Location,
|
||||
config: &WireguardConfig,
|
||||
keys: &WireguardKeyPair,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
writeln!(output, "[Interface]")?;
|
||||
writeln!(output, "PrivateKey = {}", &keys.private_key)?;
|
||||
let addresses = config.data.addresses()?;
|
||||
let allowed_addresses = addresses
|
||||
.iter()
|
||||
.filter(|addr| addr.addr().is_ipv4() || !config_opts.no_ipv6);
|
||||
let allowed_addresses = if config_opts.no_ipv6 {
|
||||
vec![IpAddr::V4(config.ipv4.address)]
|
||||
} else {
|
||||
vec![
|
||||
IpAddr::V4(config.ipv4.address),
|
||||
IpAddr::V6(config.ipv6.address),
|
||||
]
|
||||
};
|
||||
write_list(output, "Address = ", allowed_addresses)?;
|
||||
if !config_opts.no_dns {
|
||||
let dns_addrs = config.data.dns()?;
|
||||
let dns_addrs = &config.dns;
|
||||
let allowed_dns_addrs = dns_addrs
|
||||
.iter()
|
||||
.filter(|addr| addr.is_ipv4() || !config_opts.no_ipv6);
|
||||
|
|
@ -186,10 +172,9 @@ fn write_config(
|
|||
writeln!(output)?;
|
||||
|
||||
writeln!(output, "[Peer]")?;
|
||||
writeln!(output, "PublicKey = {}", &config.data.public_key)?;
|
||||
writeln!(output, "PublicKey = {}", &location.pubkey)?;
|
||||
|
||||
let endpoint_addrs = config.data.endpoint.to_socket_addrs()?;
|
||||
write_list(output, "Endpoint = ", endpoint_addrs)?;
|
||||
writeln!(output, "Endpoint = {}:51820", &location.pool)?;
|
||||
|
||||
let allowed_ips: &[&str] = if config_opts.no_ipv6 {
|
||||
&["0.0.0.0/0"]
|
||||
|
|
@ -217,21 +202,6 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn check(opts: &Opts) -> Result<(), anyhow::Error> {
|
||||
let url = format!("{}/check", BASE_URL);
|
||||
let result: CheckResult = ureq::get(&url).call()?.into_json()?;
|
||||
if opts.json {
|
||||
println!("{}", serde_json::to_string(&result)?);
|
||||
} else {
|
||||
println!("Connected: {:?}", result.connected);
|
||||
println!("IP: {}", result.ip);
|
||||
if let Some(location) = result.location {
|
||||
println!("Location: {}", location);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_locations() -> Result<Locations, anyhow::Error> {
|
||||
let url = format!("{}/locations", BASE_URL);
|
||||
let locations: Locations = ureq::get(&url).call()?.into_json()?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue