Skip to content
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
10 changes: 6 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ name = "aetherlink"
path = "src/main.rs"

[dependencies]
# Core dependencies
iroh = { version = "0.28.1", features = ["metrics"] }
# Core dependencies - using same version as pirohxy
iroh = "0.28.1"
iroh-base = "0.28.1"
iroh-net = "0.28.1"
tokio = { version = "1.41", features = ["full"] }
anyhow = "1.0"
tracing = "0.1"
Expand All @@ -37,11 +39,11 @@ bytes = "1.8"

# Utilities
directories = "5.0"
ed25519-dalek = { version = "2.1", features = ["pem"] }
rand_core = { version = "0.6", features = ["getrandom"] }
ed25519-dalek = { version = "2.1", features = ["pem", "pkcs8"] }
futures-util = "0.3"
url = "2.5"
base64 = "0.22"
shellexpand = "3.1"

[dev-dependencies]
tempfile = "3.10"
Expand Down
34 changes: 22 additions & 12 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use http_body_util::{BodyExt, Full};
use hyper::client::conn::http1;
use hyper::server::conn::http1 as server_http1;
use hyper::service::service_fn;
use hyper::{Request, Response, StatusCode, Uri};
use iroh::Endpoint;
use hyper::{Request, Response, StatusCode};
use iroh_net::endpoint::Endpoint;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::{TcpListener, TcpStream};
Expand All @@ -23,21 +23,26 @@ pub async fn create_tunnel(
local_port: u16,
bind_addr: SocketAddr,
) -> Result<()> {
use iroh_base::key::NodeId;
use std::str::FromStr;

// Parse server node ID
let server_node_id = server_id.parse()
let server_node_id = NodeId::from_str(&server_id)
.context("Invalid server node ID")?;

// Start Iroh endpoint
let endpoint = Endpoint::builder()
.secret_key(identity.secret_key.clone())
.discovery_n0()
.bind()
.alpns(vec![TUNNEL_ALPN.to_vec()])
.bind(0)
.await?;

info!("Connecting to server: {}", server_id);

// Connect to server
let conn = endpoint.connect(server_node_id, TUNNEL_ALPN).await
// Connect to server
use iroh_net::NodeAddr;
let node_addr = NodeAddr::new(server_node_id);
let conn = endpoint.connect(node_addr, &TUNNEL_ALPN).await
.context("Failed to connect to server")?;

// Register tunnel
Expand Down Expand Up @@ -127,7 +132,7 @@ pub async fn create_tunnel(

async fn handle_client_request(
stream: TcpStream,
_conn: Arc<iroh::endpoint::Connection>,
_conn: Arc<iroh_net::endpoint::Connection>,
domain: String,
local_port: u16,
) -> Result<()> {
Expand Down Expand Up @@ -223,19 +228,24 @@ pub async fn list_tunnels(
identity: Identity,
server_id: String,
) -> Result<()> {
use iroh_base::key::NodeId;
use std::str::FromStr;

// Parse server node ID
let server_node_id = server_id.parse()
let server_node_id = NodeId::from_str(&server_id)
.context("Invalid server node ID")?;

// Start Iroh endpoint
let endpoint = Endpoint::builder()
.secret_key(identity.secret_key.clone())
.discovery_n0()
.bind()
.alpns(vec![TUNNEL_ALPN.to_vec()])
.bind(0)
.await?;

// Connect to server
let conn = endpoint.connect(server_node_id, TUNNEL_ALPN).await
use iroh_net::NodeAddr;
let node_addr = NodeAddr::new(server_node_id);
let conn = endpoint.connect(node_addr, &TUNNEL_ALPN).await
.context("Failed to connect to server")?;

// Request tunnel list
Expand Down
29 changes: 14 additions & 15 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::{Context, Result};
use ed25519_dalek::{SigningKey, pkcs8::{DecodePrivateKey, EncodePrivateKey}};
use iroh::SecretKey;
use rand_core::OsRng;
use ed25519_dalek::SigningKey;
use ed25519_dalek::pkcs8::{DecodePrivateKey, EncodePrivateKey, LineEnding};
use iroh_base::key::SecretKey;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::Path;
Expand Down Expand Up @@ -76,7 +76,7 @@ impl Default for Config {

impl Identity {
pub fn generate() -> Self {
let secret_key = SecretKey::generate(&mut OsRng);
let secret_key = SecretKey::generate();
Self { secret_key }
}

Expand All @@ -89,14 +89,15 @@ impl Identity {
.with_context(|| format!("Failed to read identity file: {:?}", path))?;
let signing_key = SigningKey::from_pkcs8_pem(&pem)
.context("Failed to parse identity key")?;
Ok(Self {
secret_key: signing_key.into(),
})
let bytes = signing_key.to_bytes();
let secret_key = SecretKey::from_bytes(&bytes);
Ok(Self { secret_key })
}

pub fn to_file(&self, path: &Path) -> Result<()> {
let signing_key: SigningKey = self.secret_key.secret().clone();
let pem = signing_key.to_pkcs8_pem(ed25519_dalek::pkcs8::spki::der::pem::LineEnding::default())
let bytes = self.secret_key.to_bytes();
let signing_key = SigningKey::from_bytes(&bytes);
let pem = signing_key.to_pkcs8_pem(LineEnding::default())
.context("Failed to encode identity key")?;
std::fs::write(path, pem.as_bytes())
.with_context(|| format!("Failed to write identity file: {:?}", path))?;
Expand All @@ -113,8 +114,7 @@ mod secret_key_serde {
where
S: Serializer,
{
let signing_key: SigningKey = key.secret().clone();
let bytes = signing_key.to_bytes();
let bytes = key.to_bytes();
let encoded = STANDARD.encode(&bytes);
serializer.serialize_str(&encoded)
}
Expand All @@ -126,10 +126,9 @@ mod secret_key_serde {
let encoded = String::deserialize(deserializer)?;
let bytes = STANDARD.decode(&encoded)
.map_err(serde::de::Error::custom)?;
let signing_key = SigningKey::from_bytes(&bytes.try_into().map_err(|_| {
serde::de::Error::custom("Invalid key length")
})?);
Ok(signing_key.into())
let bytes_32: [u8; 32] = bytes.try_into()
.map_err(|_| serde::de::Error::custom("Invalid key length"))?;
Ok(SecretKey::from_bytes(&bytes_32))
}
}

Expand Down
26 changes: 11 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,17 +209,24 @@ async fn main() -> Result<()> {
}

Commands::AddServer { name, node_id } => {
let server_id = node_id.parse()
.context("Invalid node ID format")?;
use iroh_base::key::NodeId;
use std::str::FromStr;

let server_id = NodeId::from_str(&node_id)
.context("Invalid node ID format")?
.to_string();

config.servers.insert(name.clone(), server_id);
config.save(&config_path)?;

info!("✓ Added server alias '{}' → {}", name, server_id);
info!("✓ Added server alias '{}' → {}", name, node_id);
}

Commands::Authorize { client_id } => {
let client_node_id = client_id.parse()
use iroh_base::key::NodeId;
use std::str::FromStr;

let client_node_id = NodeId::from_str(&client_id)
.context("Invalid client node ID")?;

let auth_file = config_path.join("auth").join(&client_id);
Expand All @@ -241,15 +248,4 @@ async fn main() -> Result<()> {
}

Ok(())
}

mod shellexpand {
pub fn tilde(s: &str) -> std::borrow::Cow<str> {
if s.starts_with("~/") {
if let Ok(home) = std::env::var("HOME") {
return std::borrow::Cow::Owned(s.replacen("~", &home, 1));
}
}
std::borrow::Cow::Borrowed(s)
}
}
Loading
Loading