completed a basic version of the project which can fetch wireguard connection details, add address and wireguard peer details to the router. Also added License
This commit is contained in:
parent
0e7857626c
commit
13ef0ba5d1
26
Cargo.lock
generated
26
Cargo.lock
generated
|
@ -302,6 +302,15 @@ version = "2.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
|
||||
|
||||
[[package]]
|
||||
name = "ipnetwork"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.3"
|
||||
|
@ -360,6 +369,21 @@ version = "2.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "mikrotik"
|
||||
version = "0.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e0da58feff66690e8458a59dfe54dbb3ec9e710435443a07a4022788d3df3ab"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"ipnetwork",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.16"
|
||||
|
@ -490,6 +514,8 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
|||
name = "pia-mikrotik"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ipnetwork",
|
||||
"mikrotik",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"thiserror",
|
||||
|
|
|
@ -6,6 +6,8 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
ipnetwork = "0.20.0"
|
||||
mikrotik = "0.0.15"
|
||||
reqwest = { version= "0.11.11", features=["json", "rustls-tls"]}
|
||||
serde = { version = "1.0.143", features = ["derive"]}
|
||||
thiserror = "1.0.32"
|
||||
|
|
22
LICENSE
Normal file
22
LICENSE
Normal file
|
@ -0,0 +1,22 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 Ishan Jain
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
122
src/main.rs
122
src/main.rs
|
@ -1,9 +1,21 @@
|
|||
use reqwest::{Certificate, Client, ClientBuilder};
|
||||
use ipnetwork::{IpNetwork, Ipv4Network};
|
||||
use mikrotik::{
|
||||
interface::wireguard::{AddWireguardPeerInput, AllowedAddresses, WireguardPeer},
|
||||
ip::address,
|
||||
};
|
||||
use reqwest::{Certificate, Client, ClientBuilder, Url};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
io,
|
||||
net::{IpAddr, Ipv4Addr},
|
||||
str::FromStr,
|
||||
};
|
||||
use thiserror::Error;
|
||||
use tokio::{fs::File, io::AsyncReadExt};
|
||||
|
||||
// TODO(ishan): Interface name should not hardcoded to be `pia` and should be user configurable
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PError {
|
||||
#[error(transparent)]
|
||||
|
@ -11,20 +23,110 @@ pub enum PError {
|
|||
|
||||
#[error(transparent)]
|
||||
IoError(#[from] io::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
MikrotikError(#[from] mikrotik::ClientError),
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), PError> {
|
||||
let token = get_token().await?;
|
||||
|
||||
println!("{:?}", token);
|
||||
|
||||
// TODO(ishan): In future, give an option to specify exit node.
|
||||
// for now, we assume de-frankfurt, would prefer SG but some issues in the path to SG right now
|
||||
let response = register_wireguard_pub_key(&token.token).await?;
|
||||
|
||||
// TODO(ishan):
|
||||
// 1. List all addresses in `pia` interface, remove everything except for the address we just
|
||||
// received in response. DONE
|
||||
// 2. List all peers attached to `pia` interface, remove all peers except for the peer details
|
||||
// we just received in response. DONE
|
||||
// 3. Check if the tunnel dies on it's own after some time and we if need to do something to
|
||||
// keep it active.
|
||||
|
||||
println!("{:?}", response);
|
||||
|
||||
add_address(&response).await?;
|
||||
|
||||
add_peer(&response).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn add_peer(ip: &RegisterWireguardPubKeyResponse) -> Result<(), PError> {
|
||||
let mut mclient = mikrotik::Client::new(
|
||||
Url::from_str("https://10.0.99.1").unwrap(),
|
||||
"pia".to_string(),
|
||||
"qwertyuiop".to_string(),
|
||||
true,
|
||||
)?;
|
||||
|
||||
let peers = mikrotik::interface::wireguard::list_peers(&mut mclient)
|
||||
.await?
|
||||
.into_iter()
|
||||
.filter(|peer| peer.interface == "pia");
|
||||
|
||||
mikrotik::interface::wireguard::add_peer(
|
||||
&mut mclient,
|
||||
AddWireguardPeerInput {
|
||||
allowed_address: AllowedAddresses(vec![IpNetwork::V4(
|
||||
Ipv4Network::new(Ipv4Addr::new(0, 0, 0, 0), 0).unwrap(),
|
||||
)]),
|
||||
comment: Some("Managed by pia-mikrotik".to_string()),
|
||||
disabled: false,
|
||||
endpoint_address: Some(IpAddr::from_str(&ip.server_ip).unwrap()),
|
||||
endpoint_port: ip.server_port,
|
||||
interface: "pia".to_string(),
|
||||
persistent_keepalive: Some(25),
|
||||
preshared_key: None,
|
||||
public_key: ip.server_key.clone(),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
for peer in peers {
|
||||
mikrotik::interface::wireguard::remove_peer(&mut mclient, &peer.id).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn add_address(ip: &RegisterWireguardPubKeyResponse) -> Result<(), PError> {
|
||||
let mut mclient = mikrotik::Client::new(
|
||||
Url::from_str("https://10.0.99.1").unwrap(),
|
||||
"pia".to_string(),
|
||||
"qwertyuiop".to_string(),
|
||||
true,
|
||||
)?;
|
||||
|
||||
// This represents all the addresses on `pia` interface.
|
||||
// All but `ip.peer_ip` address have to be removed
|
||||
let mut addresses: HashMap<String, String> = address::list(&mut mclient)
|
||||
.await?
|
||||
.into_iter()
|
||||
.filter(|addr| addr.interface == "pia")
|
||||
.map(|addr| (addr.address, addr.id))
|
||||
.collect();
|
||||
|
||||
if addresses.contains_key(&ip.peer_ip) {
|
||||
addresses.remove(&ip.peer_ip);
|
||||
} else {
|
||||
mikrotik::ip::address::add(
|
||||
&mut mclient,
|
||||
address::AddAddressInput {
|
||||
address: ip.peer_ip.clone(),
|
||||
comment: Some("Managed by pia-mikrotik".to_string()),
|
||||
disabled: false,
|
||||
interface: "pia".to_string(),
|
||||
network: None,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
for (_, id) in addresses.into_iter() {
|
||||
mikrotik::ip::address::remove(&mut mclient, &id).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -38,22 +140,14 @@ async fn read_certificate() -> Result<Certificate, PError> {
|
|||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RegisterWireguardPubKeyResponse {
|
||||
pub status: String,
|
||||
#[serde(rename = "server_key")]
|
||||
pub server_key: String,
|
||||
#[serde(rename = "server_port")]
|
||||
pub server_port: i64,
|
||||
#[serde(rename = "server_ip")]
|
||||
pub server_port: u16,
|
||||
pub server_ip: String,
|
||||
#[serde(rename = "server_vip")]
|
||||
pub server_vip: String,
|
||||
#[serde(rename = "peer_ip")]
|
||||
pub peer_ip: String,
|
||||
#[serde(rename = "peer_pubkey")]
|
||||
pub peer_pubkey: String,
|
||||
#[serde(rename = "dns_servers")]
|
||||
pub dns_servers: Vec<String>,
|
||||
}
|
||||
|
||||
|
@ -71,7 +165,7 @@ async fn register_wireguard_pub_key(
|
|||
|
||||
let response = client
|
||||
.get(format!(
|
||||
"https://de-frankfurt.privacy.network:1337/addKey?pt={}&pubkey={}",
|
||||
"https://sg.privacy.network:1337/addKey?pt={}&pubkey={}",
|
||||
urlencoding::encode(token),
|
||||
urlencoding::encode(&pubkey)
|
||||
))
|
||||
|
|
Loading…
Reference in New Issue
Block a user