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

feat: node discovery via DNS #2045

Merged
merged 80 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
09a7973
feat: combine discovery services
Frando Mar 4, 2024
a088781
refactor: impl from iterator for combined discovery
Frando Mar 6, 2024
42f1f3b
tests: add tests for combined discovery
Frando Mar 6, 2024
8bd2ea3
chore: fmt
Frando Mar 6, 2024
6008c66
chore: fix doc link
Frando Mar 6, 2024
5a0fd66
chore: clippy
Frando Mar 6, 2024
4c81604
refactor: better controls for discovery tasks
Frando Mar 7, 2024
19e9ae7
cleanup
Frando Mar 7, 2024
2db91c8
docs and cleanup
Frando Mar 7, 2024
ed52ced
more docs
Frando Mar 7, 2024
25c847b
chore: clippy & doclinks
Frando Mar 7, 2024
b5f9728
better tracing logs
Frando Mar 7, 2024
adbc41f
fix instrumentation
Frando Mar 7, 2024
9d62fea
refactor: do not require static lifetime on discovery streams
Frando Mar 7, 2024
b5d5d55
chore: clippy
Frando Mar 7, 2024
b380b19
rename to ConcurrentDiscovery
Frando Mar 7, 2024
9383427
chore: doc link
Frando Mar 7, 2024
646de44
feat: add iroh-dns crate
Frando Feb 27, 2024
ae3e0e7
feat: discover nodes over DNS by default
Frando Feb 27, 2024
89fffc9
fix: only republish if derp url changes
Frando Feb 27, 2024
8f26558
fix(iroh-dns): do not log secret key
Frando Feb 27, 2024
58ad6f5
feat: allow to connect via node id only
Frando Feb 27, 2024
04611f2
fix: feature flags
Frando Feb 27, 2024
6ee0f97
chore: fmt
Frando Feb 27, 2024
aa4cd94
chore: fmt and clippy
Frando Feb 27, 2024
3839856
chore: remove obsolete files
Frando Feb 27, 2024
d257c0b
refactor: use z32 encoding for pkarr domain names
Frando Feb 28, 2024
b4b85de
refactor: cleanup
Frando Mar 4, 2024
1389d44
refactor: move iroh-dns into iroh-net, add docs, cleanup
Frando Mar 7, 2024
785c79b
Merge remote-tracking branch 'origin/main' into feat/dns
Frando Mar 18, 2024
9f21f40
fix: make NodeDiscoveryConfig pub
Frando Mar 18, 2024
44c5cc6
chore: fmt
Frando Mar 18, 2024
be08b9b
cleanup: better namings
Frando Mar 18, 2024
e0012b5
fix Cargo.lock after rebase
Frando Mar 18, 2024
d339b5c
Merge branch 'main' into feat/dns
Frando Mar 18, 2024
6c17aea
Merge branch 'main' into feat/dns
Frando Mar 21, 2024
0c47f28
tests: add tests for DNS discovery
Frando Mar 21, 2024
3531449
refactor: cleanup dns tests
Frando Mar 21, 2024
1932c5c
chore: clippy
Frando Mar 21, 2024
443285b
refactor: make pkarr relay client reusable for derper
Frando Mar 21, 2024
c819958
Merge remote-tracking branch 'origin/main' into feat/dns
Frando Mar 21, 2024
e519f8d
rebase fixup
Frando Mar 21, 2024
7ccae59
chore: clippy & doclinks
Frando Mar 21, 2024
c3e8f0a
Merge remote-tracking branch 'origin/main' into feat/dns
Frando Mar 25, 2024
f798084
refactor: use DNS resolver from MagicEndpoint
Frando Mar 25, 2024
a7f8ea0
Merge remote-tracking branch 'origin/main' into feat/dns
Frando Mar 25, 2024
ce48317
tests: add end-to-end test
Frando Mar 25, 2024
d1465f7
fixup
Frando Mar 25, 2024
c7cab05
Merge remote-tracking branch 'origin/main' into feat/dns
Frando Mar 25, 2024
536e3bd
cleanup
Frando Mar 25, 2024
9e5759d
cleanup
Frando Mar 25, 2024
180a651
chore: clippy
Frando Mar 25, 2024
877de7e
chore: clippy
Frando Mar 25, 2024
5d9df01
tests: improve dns discovery tests
Frando Mar 25, 2024
428f811
tests: increase timeout because windows is slow
Frando Mar 26, 2024
a21eadf
remove debug leftovers
Frando Mar 26, 2024
e12180a
Merge remote-tracking branch 'origin/main' into feat/dns
Frando Mar 26, 2024
c3252b6
Update iroh-net/src/discovery/dns.rs
Frando Mar 28, 2024
3d14417
Merge remote-tracking branch 'origin/main' into feat/dns
Frando Apr 2, 2024
7b3a0e6
Merge branch 'main' into feat/dns
Arqu Apr 2, 2024
e43d008
refactor(dns): use one DNS record per attribute (#2150)
Frando Apr 8, 2024
ed0b6a4
change: move from testdns.iroh.link to dns.iroh.link
Frando Apr 8, 2024
1ee96ba
refactor: renames for clarity
Frando Apr 8, 2024
b30358d
Merge remote-tracking branch 'origin/main' into feat/dns
Frando Apr 8, 2024
6ac8954
chore: fmt
Frando Apr 8, 2024
4524018
tests: cleanups and improvements
Frando Apr 3, 2024
2e136a5
feat: republishing in pkarr publisher
Frando Apr 3, 2024
c47d0dc
fix: improve pkarr publisher
Frando Apr 8, 2024
a172e6c
fix: magic endpoint constructor in tests
Frando Apr 8, 2024
bc5c05b
fix: pkarr republishing
Frando Apr 8, 2024
15740c9
deps: axum
Frando Apr 8, 2024
134aeb4
fix: remove online test, will hit rate limits
Frando Apr 8, 2024
3f2f543
cleanups
Frando Apr 8, 2024
bf92de5
refactor: make PkarrRelayClient public
Frando Apr 10, 2024
cb2454e
feat: make attribute parsing generic and pub
Frando Apr 10, 2024
b857a13
Merge remote-tracking branch 'origin/main' into feat/dns
Frando Apr 10, 2024
e6f56d3
feat: pkarr relay with DNS server (#2167)
Frando Apr 11, 2024
f58dcce
Merge branch 'main' into feat/dns
rklaehn Apr 12, 2024
7b84d45
Merge branch 'main' into feat/dns
rklaehn Apr 12, 2024
22a01d1
chore: fix iroh-dns-server cargo.toml
Frando Apr 15, 2024
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
620 changes: 403 additions & 217 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ members = [
"iroh",
"iroh-bytes",
"iroh-base",
"iroh-dns-server",
"iroh-gossip",
"iroh-metrics",
"iroh-net",
Expand Down
14 changes: 13 additions & 1 deletion iroh-base/src/node_addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use anyhow::Context;
use serde::{Deserialize, Serialize};
use url::Url;

use crate::key::PublicKey;
use crate::key::{NodeId, PublicKey};

/// A peer and it's addressing information.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
Expand Down Expand Up @@ -63,6 +63,12 @@ impl From<(PublicKey, Option<RelayUrl>, &[SocketAddr])> for NodeAddr {
}
}

impl From<NodeId> for NodeAddr {
fn from(node_id: NodeId) -> Self {
NodeAddr::new(node_id)
}
}

/// Addressing information to connect to a peer.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
pub struct AddrInfo {
Expand Down Expand Up @@ -142,6 +148,12 @@ impl FromStr for RelayUrl {
}
}

impl From<RelayUrl> for Url {
fn from(value: RelayUrl) -> Self {
value.0
}
}

/// Dereference to the wrapped [`Url`].
///
/// Note that [`DerefMut`] is not implemented on purpose, so this type has more flexibility
Expand Down
5 changes: 0 additions & 5 deletions iroh-cli/src/commands/blob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,6 @@ impl BlobCommands {
return Err(anyhow::anyhow!("The input arguments refer to a collection of blobs and output is set to STDOUT. Only single blobs may be passed in this case."));
}

if node_addr.info.is_empty() {
return Err(anyhow::anyhow!(
"no relay url provided and no direct addresses provided"
));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

let tag = match tag {
Some(tag) => SetTagOption::Named(Tag::from(tag)),
None => SetTagOption::Auto,
Expand Down
54 changes: 54 additions & 0 deletions iroh-dns-server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[package]
name = "iroh-dns-server"
version = "0.13.0"
edition = "2021"
description = "A pkarr relay and DNS server"
license = "MIT OR Apache-2.0"
authors = ["Frando <[email protected]>", "n0 team"]
repository = "https://github.com/n0-computer/iroh"
keywords = ["networking", "pkarr", "dns", "dns-server", "iroh"]
readme = "README.md"

[dependencies]
anyhow = "1.0.80"
async-trait = "0.1.77"
axum = { version = "0.7.4", features = ["macros"] }
axum-server = { version = "0.6.0", features = ["tls-rustls"] }
base64-url = "2.0.2"
bytes = "1.5.0"
clap = { version = "4.5.1", features = ["derive"] }
derive_more = { version = "1.0.0-beta.1", features = ["debug", "display", "into", "from"] }
dirs-next = "2.0.0"
futures = "0.3.30"
governor = "0.6.3"
hickory-proto = "0.24.0"
hickory-server = { version = "0.24.0", features = ["dns-over-rustls"] }
http = "1.0.0"
iroh-metrics = { version = "0.13.0", path = "../iroh-metrics" }
lru = "0.12.3"
parking_lot = "0.12.1"
pkarr = { version = "1.1.2", features = [ "async", "relay"], default_features = false }
rcgen = "0.12.1"
redb = "2.0.0"
regex = "1.10.3"
rustls = "0.21"
rustls-pemfile = "1"
serde = { version = "1.0.197", features = ["derive"] }
struct_iterable = "0.1.1"
strum = { version = "0.26.1", features = ["derive"] }
tokio = { version = "1.36.0", features = ["full"] }
tokio-rustls = "0.24"
tokio-rustls-acme = { version = "0.3", features = ["axum"] }
tokio-stream = "0.1.14"
tokio-util = "0.7.10"
toml = "0.8.10"
tower-http = { version = "0.5.2", features = ["cors", "trace"] }
tower_governor = "0.3.2"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
url = "2.5.0"
z32 = "1.1.1"

[dev-dependencies]
hickory-resolver = "0.24.0"
iroh-net = { version = "0.13.0", path = "../iroh-net" }
38 changes: 38 additions & 0 deletions iroh-dns-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# iroh-dns-server

A server that functions as a [pkarr](https://github.com/Nuhvi/pkarr/) relay and
[DNS](https://de.wikipedia.org/wiki/Domain_Name_System) server.

This server compiles to a binary `iroh-dns-server`. It needs a config file, of
which there are two examples included:

- [`config.dev.toml`](./config.dev.toml) - suitable for local development
- [`config.prod.toml`](./config.dev.toml) - suitable for production, after
adjusting the domain names and IP addresses

The server will expose the following services:

- A DNS server listening on UDP and TCP for DNS queries
- A HTTP and/or HTTPS server which provides the following routes:
- `/pkarr`: `GET` and `PUT` for pkarr signed packets
- `/dns-query`: Answer DNS queries over
[DNS-over-HTTPS](https://datatracker.ietf.org/doc/html/rfc8484)

All received and valid pkarr signed packets will be served over DNS. The pkarr
packet origin will be appended with the origin as configured by this server.

# License

This project is licensed under either of

- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.
18 changes: 18 additions & 0 deletions iroh-dns-server/config.dev.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[http]
port = 8080
bind_addr = "127.0.0.1"

[https]
port = 8443
bind_addr = "127.0.0.1"
domains = ["localhost"]
cert_mode = "self_signed"

[dns]
port = 5300
bind_addr = "127.0.0.1"
default_soa = "dns1.irohdns.example hostmaster.irohdns.example 0 10800 3600 604800 3600"
default_ttl = 900
origins = ["irohdns.example.", "."]
rr_a = "127.0.0.1"
rr_ns = "ns1.irohdns.example."
13 changes: 13 additions & 0 deletions iroh-dns-server/config.prod.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[https]
port = 443
domains = ["irohdns.example.org"]
cert_mode = "lets_encrypt"
letsencrypt_prod = true

[dns]
port = 53
default_soa = "dns1.irohdns.example.org hostmaster.irohdns.example.org 0 10800 3600 604800 3600"
default_ttl = 30
origins = ["irohdns.example.org", "."]
rr_a = "203.0.10.10"
rr_ns = "ns1.irohdns.example.org."
33 changes: 33 additions & 0 deletions iroh-dns-server/examples/convert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use std::str::FromStr;

use clap::Parser;
use iroh_net::NodeId;

#[derive(Debug, Parser)]
struct Cli {
#[clap(subcommand)]
command: Command,
}

#[derive(Debug, Parser)]
enum Command {
NodeToPkarr { node_id: String },
PkarrToNode { z32_pubkey: String },
}

fn main() -> anyhow::Result<()> {
let args = Cli::parse();
match args.command {
Command::NodeToPkarr { node_id } => {
let node_id = NodeId::from_str(&node_id)?;
let public_key = pkarr::PublicKey::try_from(*node_id.as_bytes())?;
println!("{}", public_key.to_z32())
}
Command::PkarrToNode { z32_pubkey } => {
let public_key = pkarr::PublicKey::try_from(z32_pubkey.as_str())?;
let node_id = NodeId::from_bytes(public_key.as_bytes())?;
println!("{}", node_id)
}
}
Ok(())
}
106 changes: 106 additions & 0 deletions iroh-dns-server/examples/publish.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use std::str::FromStr;

use anyhow::{bail, Result};
use clap::{Parser, ValueEnum};
use iroh_net::{
discovery::{
dns::N0_DNS_NODE_ORIGIN,
pkarr_publish::{PkarrRelayClient, N0_DNS_PKARR_RELAY},
},
dns::node_info::{to_z32, NodeInfo, IROH_TXT_NAME},
key::SecretKey,
NodeId,
};
use url::Url;

const LOCALHOST_PKARR: &str = "http://localhost:8080/pkarr";
const EXAMPLE_ORIGIN: &str = "irohdns.example";

#[derive(ValueEnum, Clone, Debug, Default, Copy, strum::Display)]
#[strum(serialize_all = "kebab-case")]
pub enum Env {
/// Use the pkarr relay run by number0.
#[default]
Default,
/// Use a relay listening at http://localhost:8080
Dev,
}

/// Publish a record to an irohdns server.
///
/// You have to set the IROH_SECRET environment variable to the node secret for which to publish.
#[derive(Parser, Debug)]
struct Cli {
/// Environment to publish to.
#[clap(value_enum, short, long, default_value_t = Env::Default)]
env: Env,
/// Pkarr Relay URL. If set, the --env option will be ignored.
#[clap(long, conflicts_with = "env")]
pkarr_relay: Option<Url>,
/// Home relay server to publish for this node
relay_url: Url,
/// Create a new node secret if IROH_SECRET is unset. Only for development / debugging.
#[clap(short, long)]
create: bool,
}

#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
let args = Cli::parse();

let secret_key = match std::env::var("IROH_SECRET") {
Ok(s) => SecretKey::from_str(&s)?,
Err(_) if args.create => {
let s = SecretKey::generate();
println!("Generated a new node secret. To reuse, set");
println!("IROH_SECRET={s}");
s
}
Err(_) => {
bail!("Environtment variable IROH_SECRET is not set. To create a new secret, use the --create option.")
}
};

let node_id = secret_key.public();
let pkarr_relay = match (args.pkarr_relay, args.env) {
(Some(pkarr_relay), _) => pkarr_relay,
(None, Env::Default) => N0_DNS_PKARR_RELAY.parse().expect("valid url"),
(None, Env::Dev) => LOCALHOST_PKARR.parse().expect("valid url"),
};

println!("announce {node_id}:");
println!(" relay={}", args.relay_url);
println!();
println!("publish to {pkarr_relay} ...");

let pkarr = PkarrRelayClient::new(pkarr_relay);
let node_info = NodeInfo::new(node_id, Some(args.relay_url));
let signed_packet = node_info.to_pkarr_signed_packet(&secret_key, 30)?;
pkarr.publish(&signed_packet).await?;

println!("signed packet published.");
println!("resolve with:");

match args.env {
Env::Default => {
println!(" cargo run --example resolve -- node {}", node_id);
println!(" dig {} TXT", fmt_domain(&node_id, N0_DNS_NODE_ORIGIN))
}
Env::Dev => {
println!(
" cargo run --example resolve -- --env dev node {}",
node_id
);
println!(
" dig @localhost -p 5300 {} TXT",
fmt_domain(&node_id, EXAMPLE_ORIGIN)
)
}
}
Ok(())
}

fn fmt_domain(node_id: &NodeId, origin: &str) -> String {
format!("{}.{}.{}", IROH_TXT_NAME, to_z32(node_id), origin)
}
Loading
Loading