wip: debugging tor

This commit is contained in:
Aiden McClelland
2025-08-27 15:10:54 -06:00
parent c5fa09c4d4
commit b3b031ed47
31 changed files with 521 additions and 607 deletions

View File

@@ -40,6 +40,8 @@ sudo chown 0:0 tmp/combined/lib/systemd/system/container-runtime.service
sudo cp container-runtime-failure.service tmp/combined/lib/systemd/system/container-runtime-failure.service sudo cp container-runtime-failure.service tmp/combined/lib/systemd/system/container-runtime-failure.service
sudo chown 0:0 tmp/combined/lib/systemd/system/container-runtime-failure.service sudo chown 0:0 tmp/combined/lib/systemd/system/container-runtime-failure.service
sudo cp ../core/target/$ARCH-unknown-linux-musl/release/containerbox tmp/combined/usr/bin/start-container sudo cp ../core/target/$ARCH-unknown-linux-musl/release/containerbox tmp/combined/usr/bin/start-container
echo -e '#!/bin/bash\nexec start-container $@' | sudo tee tmp/combined/usr/bin/start-cli # TODO: remove
sudo chmod +x tmp/combined/usr/bin/start-cli
sudo chown 0:0 tmp/combined/usr/bin/start-container sudo chown 0:0 tmp/combined/usr/bin/start-container
echo container-runtime | sha256sum | head -c 32 | cat - <(echo) | sudo tee tmp/combined/etc/machine-id echo container-runtime | sha256sum | head -c 32 | cat - <(echo) | sudo tee tmp/combined/etc/machine-id
cat deb-install.sh | sudo systemd-nspawn --console=pipe -D tmp/combined $QEMU /bin/bash cat deb-install.sh | sudo systemd-nspawn --console=pipe -D tmp/combined $QEMU /bin/bash

738
core/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,7 @@ if [[ "${ENVIRONMENT}" =~ (^|-)unstable($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable" RUSTFLAGS="--cfg tokio_unstable"
fi fi
alias 'rust-musl-builder'='docker run $USE_TTY --rm -e "RUSTFLAGS=$RUSTFLAGS" -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$HOME/.cargo/git":/root/.cargo/git -v "$(pwd)":/home/rust/src -w /home/rust/src -P messense/rust-musl-cross:$ARCH-musl' source ./core/builder-alias.sh
echo "FEATURES=\"$FEATURES\"" echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\"" echo "RUSTFLAGS=\"$RUSTFLAGS\""

View File

@@ -26,7 +26,7 @@ if [[ "${ENVIRONMENT}" =~ (^|-)unstable($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable" RUSTFLAGS="--cfg tokio_unstable"
fi fi
alias 'rust-musl-builder'='docker run $USE_TTY --rm -e "RUSTFLAGS=$RUSTFLAGS" -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$HOME/.cargo/git":/root/.cargo/git -v "$(pwd)":/home/rust/src -w /home/rust/src -P messense/rust-musl-cross:$ARCH-musl' source ./core/builder-alias.sh
echo "FEATURES=\"$FEATURES\"" echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\"" echo "RUSTFLAGS=\"$RUSTFLAGS\""

View File

@@ -31,7 +31,7 @@ if [[ "${ENVIRONMENT}" =~ (^|-)unstable($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable" RUSTFLAGS="--cfg tokio_unstable"
fi fi
alias 'rust-musl-builder'='docker run $USE_TTY --rm -e "RUSTFLAGS=$RUSTFLAGS" -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$HOME/.cargo/git":/root/.cargo/git -v "$(pwd)":/home/rust/src -w /home/rust/src -P messense/rust-musl-cross:$ARCH-musl' source ./core/builder-alias.sh
echo "FEATURES=\"$FEATURES\"" echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\"" echo "RUSTFLAGS=\"$RUSTFLAGS\""

View File

@@ -26,7 +26,7 @@ if [[ "${ENVIRONMENT}" =~ (^|-)unstable($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable" RUSTFLAGS="--cfg tokio_unstable"
fi fi
alias 'rust-musl-builder'='docker run $USE_TTY --rm -e "RUSTFLAGS=$RUSTFLAGS" -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$HOME/.cargo/git":/root/.cargo/git -v "$(pwd)":/home/rust/src -w /home/rust/src -P messense/rust-musl-cross:$ARCH-musl' source ./core/builder-alias.sh
echo "FEATURES=\"$FEATURES\"" echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\"" echo "RUSTFLAGS=\"$RUSTFLAGS\""

View File

@@ -26,7 +26,7 @@ if [[ "${ENVIRONMENT}" =~ (^|-)unstable($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable" RUSTFLAGS="--cfg tokio_unstable"
fi fi
alias 'rust-musl-builder'='docker run $USE_TTY --rm -e "RUSTFLAGS=$RUSTFLAGS" -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$HOME/.cargo/git":/root/.cargo/git -v "$(pwd)":/home/rust/src -w /home/rust/src -P messense/rust-musl-cross:$ARCH-musl' source ./core/builder-alias.sh
echo "FEATURES=\"$FEATURES\"" echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\"" echo "RUSTFLAGS=\"$RUSTFLAGS\""

3
core/builder-alias.sh Normal file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
alias 'rust-musl-builder'='docker run $USE_TTY --rm -e "RUSTFLAGS=$RUSTFLAGS" -e SCCACHE_GHA_ENABLED -e SCCACHE_GHA_VERSION -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$HOME/.cargo/git":/root/.cargo/git -v "$HOME/.cache/sccache":/root/.cache/sccache -v "$(pwd)":/home/rust/src -w /home/rust/src -P start9/rust-musl-cross:$ARCH-musl'

View File

@@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
arti-client = { version = "0.33", features = ["full"] } arti-client = { version = "0.33", default-features = false, git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit" }
axum = "0.8.4" axum = "0.8.4"
base64 = "0.22.1" base64 = "0.22.1"
color-eyre = "0.6.2" color-eyre = "0.6.2"

View File

@@ -64,7 +64,9 @@ arti-client = { version = "0.33", features = [
"static", "static",
"tokio", "tokio",
"ephemeral-keystore", "ephemeral-keystore",
], default-features = false } "onion-service-client",
"onion-service-service",
], default-features = false, git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit" }
aes = { version = "0.7.5", features = ["ctr"] } aes = { version = "0.7.5", features = ["ctr"] }
async-acme = { version = "0.6.0", git = "https://github.com/dr-bonez/async-acme.git", features = [ async-acme = { version = "0.6.0", git = "https://github.com/dr-bonez/async-acme.git", features = [
"use_rustls", "use_rustls",
@@ -195,7 +197,7 @@ rpassword = "7.2.0"
rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git", branch = "master" } rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git", branch = "master" }
rust-argon2 = "2.0.0" rust-argon2 = "2.0.0"
rustyline-async = "0.4.1" rustyline-async = "0.4.1"
safelog = "0.4.8" safelog = { version = "0.4.8", git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit" }
semver = { version = "1.0.20", features = ["serde"] } semver = { version = "1.0.20", features = ["serde"] }
serde = { version = "1.0", features = ["derive", "rc"] } serde = { version = "1.0", features = ["derive", "rc"] }
serde_cbor = { package = "ciborium", version = "0.2.1" } serde_cbor = { package = "ciborium", version = "0.2.1" }
@@ -227,13 +229,22 @@ tokio-stream = { version = "0.1.14", features = ["io-util", "sync", "net"] }
tokio-tar = { git = "https://github.com/dr-bonez/tokio-tar.git" } tokio-tar = { git = "https://github.com/dr-bonez/tokio-tar.git" }
tokio-tungstenite = { version = "0.26.2", features = ["native-tls", "url"] } tokio-tungstenite = { version = "0.26.2", features = ["native-tls", "url"] }
tokio-util = { version = "0.7.9", features = ["io"] } tokio-util = { version = "0.7.9", features = ["io"] }
tor-cell = { version = "0.33" } tor-cell = { version = "0.33", git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit" }
tor-hscrypto = { version = "0.33", features = ["full"] } tor-hscrypto = { version = "0.33", features = [
tor-hsservice = { version = "0.33" } "full",
tor-keymgr = { version = "0.33", features = ["ephemeral-keystore"] } ], git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit" }
tor-llcrypto = { version = "0.33", features = ["full"] } tor-hsservice = { version = "0.33", git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit" }
tor-proto = { version = "0.33" } tor-keymgr = { version = "0.33", features = [
tor-rtcompat = { version = "0.33", features = ["tokio", "rustls"] } "ephemeral-keystore",
], git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit" }
tor-llcrypto = { version = "0.33", features = [
"full",
], git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit" }
tor-proto = { version = "0.33", git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit" }
tor-rtcompat = { version = "0.33", features = [
"tokio",
"rustls",
], git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit" }
tower-service = "0.3.3" tower-service = "0.3.3"
tracing = "0.1.39" tracing = "0.1.39"
tracing-error = "0.2.0" tracing-error = "0.2.0"

View File

@@ -18,7 +18,7 @@ use models::{ActionId, PackageId};
use reqwest::{Client, Proxy}; use reqwest::{Client, Proxy};
use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::{CallRemote, Context, Empty}; use rpc_toolkit::{CallRemote, Context, Empty};
use tokio::sync::{Mutex, RwLock, broadcast, oneshot, watch}; use tokio::sync::{RwLock, broadcast, oneshot, watch};
use tokio::time::Instant; use tokio::time::Instant;
use tracing::instrument; use tracing::instrument;
@@ -32,7 +32,7 @@ use crate::db::model::package::TaskSeverity;
use crate::disk::OsPartitionInfo; use crate::disk::OsPartitionInfo;
use crate::init::{InitResult, check_time_is_synchronized}; use crate::init::{InitResult, check_time_is_synchronized};
use crate::install::PKG_ARCHIVE_DIR; use crate::install::PKG_ARCHIVE_DIR;
use crate::lxc::{ContainerId, LxcContainer, LxcManager}; use crate::lxc::LxcManager;
use crate::net::net_controller::{NetController, NetService}; use crate::net::net_controller::{NetController, NetService};
use crate::net::utils::{find_eth_iface, find_wifi_iface}; use crate::net::utils::{find_eth_iface, find_wifi_iface};
use crate::net::web_server::{UpgradableListener, WebServerAcceptorSetter}; use crate::net::web_server::{UpgradableListener, WebServerAcceptorSetter};
@@ -74,12 +74,6 @@ pub struct RpcContextSeed {
pub client: Client, pub client: Client,
pub start_time: Instant, pub start_time: Instant,
pub crons: SyncMutex<BTreeMap<Guid, NonDetachingJoinHandle<()>>>, pub crons: SyncMutex<BTreeMap<Guid, NonDetachingJoinHandle<()>>>,
// #[cfg(feature = "dev")]
pub dev: Dev,
}
pub struct Dev {
pub lxc: Mutex<BTreeMap<ContainerId, LxcContainer>>,
} }
pub struct Hardware { pub struct Hardware {
@@ -262,10 +256,6 @@ impl RpcContext {
.with_kind(crate::ErrorKind::ParseUrl)?, .with_kind(crate::ErrorKind::ParseUrl)?,
start_time: Instant::now(), start_time: Instant::now(),
crons, crons,
// #[cfg(feature = "dev")]
dev: Dev {
lxc: Mutex::new(BTreeMap::new()),
},
}); });
let res = Self(seed.clone()); let res = Self(seed.clone());

View File

@@ -19,8 +19,8 @@ use crate::account::AccountInfo;
use crate::db::model::package::AllPackageData; use crate::db::model::package::AllPackageData;
use crate::net::acme::AcmeProvider; use crate::net::acme::AcmeProvider;
use crate::net::forward::START9_BRIDGE_IFACE; use crate::net::forward::START9_BRIDGE_IFACE;
use crate::net::host::binding::{AddSslOptions, BindInfo, BindOptions, NetInfo};
use crate::net::host::Host; use crate::net::host::Host;
use crate::net::host::binding::{AddSslOptions, BindInfo, BindOptions, NetInfo};
use crate::net::utils::ipv6_is_local; use crate::net::utils::ipv6_is_local;
use crate::net::vhost::AlpnInfo; use crate::net::vhost::AlpnInfo;
use crate::prelude::*; use crate::prelude::*;

View File

@@ -10,34 +10,34 @@ use futures::future::BoxFuture;
use futures::{FutureExt, StreamExt, TryStreamExt}; use futures::{FutureExt, StreamExt, TryStreamExt};
use helpers::NonDetachingJoinHandle; use helpers::NonDetachingJoinHandle;
use hickory_client::client::Client; use hickory_client::client::Client;
use hickory_client::proto::DnsHandle;
use hickory_client::proto::runtime::TokioRuntimeProvider; use hickory_client::proto::runtime::TokioRuntimeProvider;
use hickory_client::proto::tcp::TcpClientStream; use hickory_client::proto::tcp::TcpClientStream;
use hickory_client::proto::udp::UdpClientStream; use hickory_client::proto::udp::UdpClientStream;
use hickory_client::proto::xfer::{DnsExchangeBackground, DnsRequestOptions}; use hickory_client::proto::xfer::{DnsExchangeBackground, DnsRequestOptions};
use hickory_client::proto::DnsHandle; use hickory_server::ServerFuture;
use hickory_server::authority::MessageResponseBuilder; use hickory_server::authority::MessageResponseBuilder;
use hickory_server::proto::op::{Header, ResponseCode}; use hickory_server::proto::op::{Header, ResponseCode};
use hickory_server::proto::rr::{Name, Record, RecordType}; use hickory_server::proto::rr::{Name, Record, RecordType};
use hickory_server::server::{Request, RequestHandler, ResponseHandler, ResponseInfo}; use hickory_server::server::{Request, RequestHandler, ResponseHandler, ResponseInfo};
use hickory_server::ServerFuture;
use imbl::OrdMap; use imbl::OrdMap;
use imbl_value::InternedString; use imbl_value::InternedString;
use itertools::Itertools; use itertools::Itertools;
use models::{GatewayId, OptionExt, PackageId}; use models::{GatewayId, OptionExt, PackageId};
use rpc_toolkit::{ use rpc_toolkit::{
from_fn_async, from_fn_blocking, Context, HandlerArgs, HandlerExt, ParentHandler, Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async, from_fn_blocking,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::net::{TcpListener, UdpSocket}; use tokio::net::{TcpListener, UdpSocket};
use tracing::instrument; use tracing::instrument;
use crate::context::RpcContext; use crate::context::RpcContext;
use crate::db::model::public::NetworkInterfaceInfo;
use crate::db::model::Database; use crate::db::model::Database;
use crate::db::model::public::NetworkInterfaceInfo;
use crate::net::gateway::NetworkInterfaceWatcher; use crate::net::gateway::NetworkInterfaceWatcher;
use crate::prelude::*; use crate::prelude::*;
use crate::util::io::file_string_stream; use crate::util::io::file_string_stream;
use crate::util::serde::{display_serializable, HandlerExtSerde}; use crate::util::serde::{HandlerExtSerde, display_serializable};
use crate::util::sync::{SyncRwLock, Watch}; use crate::util::sync::{SyncRwLock, Watch};
pub fn dns_api<C: Context>() -> ParentHandler<C> { pub fn dns_api<C: Context>() -> ParentHandler<C> {
@@ -349,11 +349,7 @@ impl RequestHandler for Resolver {
Header::response_from_request(request.header()), Header::response_from_request(request.header()),
&ip.into_iter() &ip.into_iter()
.filter_map(|a| { .filter_map(|a| {
if let IpAddr::V4(a) = a { if let IpAddr::V4(a) = a { Some(a) } else { None }
Some(a)
} else {
None
}
}) })
.map(|ip| { .map(|ip| {
Record::from_rdata( Record::from_rdata(
@@ -377,11 +373,7 @@ impl RequestHandler for Resolver {
Header::response_from_request(request.header()), Header::response_from_request(request.header()),
&ip.into_iter() &ip.into_iter()
.filter_map(|a| { .filter_map(|a| {
if let IpAddr::V6(a) = a { if let IpAddr::V6(a) = a { Some(a) } else { None }
Some(a)
} else {
None
}
}) })
.map(|ip| { .map(|ip| {
Record::from_rdata( Record::from_rdata(
@@ -415,9 +407,7 @@ impl RequestHandler for Resolver {
} }
} else { } else {
let query = query.original().clone(); let query = query.original().clone();
let mut streams = self let mut streams = self.client.lookup(query, DnsRequestOptions::default());
.client
.lookup(query, DnsRequestOptions::default());
let mut err = None; let mut err = None;
for stream in streams.iter_mut() { for stream in streams.iter_mut() {
match tokio::time::timeout(Duration::from_secs(5), stream.next()).await { match tokio::time::timeout(Duration::from_secs(5), stream.next()).await {

View File

@@ -16,7 +16,7 @@ use itertools::Itertools;
use models::GatewayId; use models::GatewayId;
use nix::net::if_::if_nametoindex; use nix::net::if_::if_nametoindex;
use patch_db::json_ptr::JsonPointer; use patch_db::json_ptr::JsonPointer;
use rpc_toolkit::{from_fn_async, Context, HandlerArgs, HandlerExt, ParentHandler}; use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::net::{TcpListener, TcpStream}; use tokio::net::{TcpListener, TcpStream};
@@ -24,25 +24,25 @@ use tokio::process::Command;
use ts_rs::TS; use ts_rs::TS;
use zbus::proxy::{PropertyChanged, PropertyStream, SignalStream}; use zbus::proxy::{PropertyChanged, PropertyStream, SignalStream};
use zbus::zvariant::{ use zbus::zvariant::{
DeserializeDict, Dict, OwnedObjectPath, OwnedValue, Type as ZType, Value as ZValue, DICT_ENTRY_SIG_END_STR, DeserializeDict, Dict, OwnedObjectPath, OwnedValue, Type as ZType,
DICT_ENTRY_SIG_END_STR, Value as ZValue,
}; };
use zbus::{proxy, Connection}; use zbus::{Connection, proxy};
use crate::context::{CliContext, RpcContext}; use crate::context::{CliContext, RpcContext};
use crate::db::model::public::{IpInfo, NetworkInterfaceInfo, NetworkInterfaceType};
use crate::db::model::Database; use crate::db::model::Database;
use crate::db::model::public::{IpInfo, NetworkInterfaceInfo, NetworkInterfaceType};
use crate::net::forward::START9_BRIDGE_IFACE; use crate::net::forward::START9_BRIDGE_IFACE;
use crate::net::gateway::device::DeviceProxy; use crate::net::gateway::device::DeviceProxy;
use crate::net::utils::ipv6_is_link_local; use crate::net::utils::ipv6_is_link_local;
use crate::net::web_server::Accept; use crate::net::web_server::Accept;
use crate::prelude::*; use crate::prelude::*;
use crate::util::Invoke;
use crate::util::collections::OrdMapIterMut; use crate::util::collections::OrdMapIterMut;
use crate::util::future::Until; use crate::util::future::Until;
use crate::util::io::open_file; use crate::util::io::open_file;
use crate::util::serde::{display_serializable, HandlerExtSerde}; use crate::util::serde::{HandlerExtSerde, display_serializable};
use crate::util::sync::{SyncMutex, Watch}; use crate::util::sync::{SyncMutex, Watch};
use crate::util::Invoke;
pub fn gateway_api<C: Context>() -> ParentHandler<C> { pub fn gateway_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new() ParentHandler::new()

View File

@@ -1,19 +1,20 @@
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::net::Ipv4Addr;
use clap::Parser; use clap::Parser;
use imbl_value::InternedString; use imbl_value::InternedString;
use models::GatewayId; use models::GatewayId;
use rpc_toolkit::{from_fn_async, Context, Empty, HandlerArgs, HandlerExt, ParentHandler}; use rpc_toolkit::{Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ts_rs::TS; use ts_rs::TS;
use crate::context::{CliContext, RpcContext}; use crate::context::{CliContext, RpcContext};
use crate::db::model::DatabaseModel; use crate::db::model::DatabaseModel;
use crate::net::acme::AcmeProvider; use crate::net::acme::AcmeProvider;
use crate::net::host::{all_hosts, HostApiKind}; use crate::net::host::{HostApiKind, all_hosts};
use crate::net::tor::OnionAddress; use crate::net::tor::OnionAddress;
use crate::prelude::*; use crate::prelude::*;
use crate::util::serde::{display_serializable, HandlerExtSerde}; use crate::util::serde::{HandlerExtSerde, display_serializable};
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
@@ -35,10 +36,10 @@ pub struct PublicDomainConfig {
pub acme: Option<AcmeProvider>, pub acme: Option<AcmeProvider>,
} }
fn check_duplicates(db: &DatabaseModel) -> Result<(), Error> { fn handle_duplicates(db: &mut DatabaseModel) -> Result<(), Error> {
let mut onions = BTreeSet::<OnionAddress>::new(); let mut onions = BTreeSet::<OnionAddress>::new();
let mut domains = BTreeSet::<InternedString>::new(); let mut domains = BTreeSet::<InternedString>::new();
let mut check_onion = |onion: OnionAddress| { let check_onion = |onions: &mut BTreeSet<OnionAddress>, onion: OnionAddress| {
if onions.contains(&onion) { if onions.contains(&onion) {
return Err(Error::new( return Err(Error::new(
eyre!("onion address {onion} is already in use"), eyre!("onion address {onion} is already in use"),
@@ -48,7 +49,7 @@ fn check_duplicates(db: &DatabaseModel) -> Result<(), Error> {
onions.insert(onion); onions.insert(onion);
Ok(()) Ok(())
}; };
let mut check_domain = |domain: InternedString| { let check_domain = |domains: &mut BTreeSet<InternedString>, domain: InternedString| {
if domains.contains(&domain) { if domains.contains(&domain) {
return Err(Error::new( return Err(Error::new(
eyre!("domain {domain} is already in use"), eyre!("domain {domain} is already in use"),
@@ -58,23 +59,47 @@ fn check_duplicates(db: &DatabaseModel) -> Result<(), Error> {
domains.insert(domain); domains.insert(domain);
Ok(()) Ok(())
}; };
let mut not_in_use = Vec::new();
for host in all_hosts(db) { for host in all_hosts(db) {
let host = host?; let host = host?;
let in_use = host.as_bindings().de()?.values().any(|v| v.enabled);
if !in_use {
not_in_use.push(host);
continue;
}
for onion in host.as_onions().de()? { for onion in host.as_onions().de()? {
check_onion(onion)?; check_onion(&mut onions, onion)?;
} }
for domain in host.as_public_domains().keys()? { for domain in host.as_public_domains().keys()? {
check_domain(domain)?; check_domain(&mut domains, domain)?;
} }
for domain in host.as_private_domains().de()? { for domain in host.as_private_domains().de()? {
check_domain(domain)?; check_domain(&mut domains, domain)?;
}
}
for host in not_in_use {
host.as_onions_mut()
.mutate(|o| Ok(o.retain(|o| !onions.contains(o))))?;
host.as_public_domains_mut()
.mutate(|d| Ok(d.retain(|d, _| !domains.contains(d))))?;
host.as_private_domains_mut()
.mutate(|d| Ok(d.retain(|d| !domains.contains(d))))?;
for onion in host.as_onions().de()? {
check_onion(&mut onions, onion)?;
}
for domain in host.as_public_domains().keys()? {
check_domain(&mut domains, domain)?;
}
for domain in host.as_private_domains().de()? {
check_domain(&mut domains, domain)?;
} }
} }
Ok(()) Ok(())
} }
pub fn address_api<C: Context, Kind: HostApiKind>( pub fn address_api<C: Context, Kind: HostApiKind>()
) -> ParentHandler<C, Kind::Params, Kind::InheritedParams> { -> ParentHandler<C, Kind::Params, Kind::InheritedParams> {
ParentHandler::<C, Kind::Params, Kind::InheritedParams>::new() ParentHandler::<C, Kind::Params, Kind::InheritedParams>::new()
.subcommand( .subcommand(
"domain", "domain",
@@ -209,12 +234,12 @@ pub struct AddPublicDomainParams {
pub async fn add_public_domain<Kind: HostApiKind>( pub async fn add_public_domain<Kind: HostApiKind>(
ctx: RpcContext, ctx: RpcContext,
AddPublicDomainParams { AddPublicDomainParams {
ref fqdn, fqdn,
acme, acme,
gateway, gateway,
}: AddPublicDomainParams, }: AddPublicDomainParams,
inheritance: Kind::Inheritance, inheritance: Kind::Inheritance,
) -> Result<(), Error> { ) -> Result<Option<Ipv4Addr>, Error> {
ctx.db ctx.db
.mutate(|db| { .mutate(|db| {
if let Some(acme) = &acme { if let Some(acme) = &acme {
@@ -231,31 +256,35 @@ pub async fn add_public_domain<Kind: HostApiKind>(
Kind::host_for(&inheritance, db)? Kind::host_for(&inheritance, db)?
.as_public_domains_mut() .as_public_domains_mut()
.insert(fqdn, &PublicDomainConfig { acme, gateway })?; .insert(&fqdn, &PublicDomainConfig { acme, gateway })?;
check_duplicates(db) handle_duplicates(db)
}) })
.await .await
.result?; .result?;
Kind::sync_host(&ctx, inheritance).await?; Kind::sync_host(&ctx, inheritance).await?;
Ok(()) tokio::task::spawn_blocking(|| {
crate::net::dns::query_dns(ctx, crate::net::dns::QueryDnsParams { fqdn })
})
.await
.with_kind(ErrorKind::Unknown)?
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser)]
pub struct RemoveDomainParams { pub struct RemoveDomainParams {
pub domain: InternedString, pub fqdn: InternedString,
} }
pub async fn remove_public_domain<Kind: HostApiKind>( pub async fn remove_public_domain<Kind: HostApiKind>(
ctx: RpcContext, ctx: RpcContext,
RemoveDomainParams { domain }: RemoveDomainParams, RemoveDomainParams { fqdn }: RemoveDomainParams,
inheritance: Kind::Inheritance, inheritance: Kind::Inheritance,
) -> Result<(), Error> { ) -> Result<(), Error> {
ctx.db ctx.db
.mutate(|db| { .mutate(|db| {
Kind::host_for(&inheritance, db)? Kind::host_for(&inheritance, db)?
.as_public_domains_mut() .as_public_domains_mut()
.remove(&domain) .remove(&fqdn)
}) })
.await .await
.result?; .result?;
@@ -279,7 +308,7 @@ pub async fn add_private_domain<Kind: HostApiKind>(
Kind::host_for(&inheritance, db)? Kind::host_for(&inheritance, db)?
.as_private_domains_mut() .as_private_domains_mut()
.mutate(|d| Ok(d.insert(fqdn)))?; .mutate(|d| Ok(d.insert(fqdn)))?;
check_duplicates(db) handle_duplicates(db)
}) })
.await .await
.result?; .result?;
@@ -290,7 +319,7 @@ pub async fn add_private_domain<Kind: HostApiKind>(
pub async fn remove_private_domain<Kind: HostApiKind>( pub async fn remove_private_domain<Kind: HostApiKind>(
ctx: RpcContext, ctx: RpcContext,
RemoveDomainParams { domain }: RemoveDomainParams, RemoveDomainParams { fqdn: domain }: RemoveDomainParams,
inheritance: Kind::Inheritance, inheritance: Kind::Inheritance,
) -> Result<(), Error> { ) -> Result<(), Error> {
ctx.db ctx.db
@@ -332,7 +361,7 @@ pub async fn add_onion<Kind: HostApiKind>(
Kind::host_for(&inheritance, db)? Kind::host_for(&inheritance, db)?
.as_onions_mut() .as_onions_mut()
.mutate(|a| Ok(a.insert(onion)))?; .mutate(|a| Ok(a.insert(onion)))?;
check_duplicates(db) handle_duplicates(db)
}) })
.await .await
.result?; .result?;

View File

@@ -1,11 +1,11 @@
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use std::str::FromStr; use std::str::FromStr;
use clap::builder::ValueParserFactory;
use clap::Parser; use clap::Parser;
use clap::builder::ValueParserFactory;
use imbl::OrdSet; use imbl::OrdSet;
use models::{FromStrParser, GatewayId, HostId}; use models::{FromStrParser, GatewayId, HostId};
use rpc_toolkit::{from_fn_async, Context, Empty, HandlerArgs, HandlerExt, ParentHandler}; use rpc_toolkit::{Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ts_rs::TS; use ts_rs::TS;
@@ -16,7 +16,7 @@ use crate::net::gateway::InterfaceFilter;
use crate::net::host::HostApiKind; use crate::net::host::HostApiKind;
use crate::net::vhost::AlpnInfo; use crate::net::vhost::AlpnInfo;
use crate::prelude::*; use crate::prelude::*;
use crate::util::serde::{display_serializable, HandlerExtSerde}; use crate::util::serde::{HandlerExtSerde, display_serializable};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, TS)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, TS)]
#[ts(export)] #[ts(export)]
@@ -169,8 +169,8 @@ pub struct AddSslOptions {
pub alpn: Option<AlpnInfo>, pub alpn: Option<AlpnInfo>,
} }
pub fn binding<C: Context, Kind: HostApiKind>( pub fn binding<C: Context, Kind: HostApiKind>()
) -> ParentHandler<C, Kind::Params, Kind::InheritedParams> { -> ParentHandler<C, Kind::Params, Kind::InheritedParams> {
ParentHandler::<C, Kind::Params, Kind::InheritedParams>::new() ParentHandler::<C, Kind::Params, Kind::InheritedParams>::new()
.subcommand( .subcommand(
"list", "list",

View File

@@ -127,14 +127,16 @@ pub fn host_for<'a>(
}) })
} }
pub fn all_hosts(db: &DatabaseModel) -> impl Iterator<Item = Result<&Model<Host>, Error>> { pub fn all_hosts(db: &mut DatabaseModel) -> impl Iterator<Item = Result<&mut Model<Host>, Error>> {
[Ok(db.as_public().as_server_info().as_network().as_host())] use patch_db::DestructureMut;
let destructured = db.as_public_mut().destructure_mut();
[Ok(destructured.server_info.as_network_mut().as_host_mut())]
.into_iter() .into_iter()
.chain( .chain(
[db.as_public().as_package_data().as_entries()] [destructured.package_data.as_entries_mut()]
.into_iter() .into_iter()
.flatten_ok() .flatten_ok()
.map(|entry| entry.and_then(|(_, v)| v.as_hosts().as_entries())) .map(|entry| entry.and_then(|(_, v)| v.as_hosts_mut().as_entries_mut()))
.flatten_ok() .flatten_ok()
.map_ok(|(_, v)| v), .map_ok(|(_, v)| v),
) )

View File

@@ -3,7 +3,7 @@ use std::net::{Ipv4Addr, SocketAddr};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use color_eyre::eyre::eyre; use color_eyre::eyre::eyre;
use imbl::{vector, OrdMap}; use imbl::{OrdMap, vector};
use imbl_value::InternedString; use imbl_value::InternedString;
use ipnet::IpNet; use ipnet::IpNet;
use models::{HostId, OptionExt, PackageId}; use models::{HostId, OptionExt, PackageId};
@@ -11,8 +11,9 @@ use tokio::sync::Mutex;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use tracing::instrument; use tracing::instrument;
use crate::db::model::public::NetworkInterfaceInfo; use crate::HOST_IP;
use crate::db::model::Database; use crate::db::model::Database;
use crate::db::model::public::NetworkInterfaceInfo;
use crate::error::ErrorCollection; use crate::error::ErrorCollection;
use crate::hostname::Hostname; use crate::hostname::Hostname;
use crate::net::dns::DnsController; use crate::net::dns::DnsController;
@@ -23,7 +24,7 @@ use crate::net::gateway::{
}; };
use crate::net::host::address::HostAddress; use crate::net::host::address::HostAddress;
use crate::net::host::binding::{AddSslOptions, BindId, BindOptions}; use crate::net::host::binding::{AddSslOptions, BindId, BindOptions};
use crate::net::host::{host_for, Host, Hosts}; use crate::net::host::{Host, Hosts, host_for};
use crate::net::service_interface::{HostnameInfo, IpHostname, OnionHostname}; use crate::net::service_interface::{HostnameInfo, IpHostname, OnionHostname};
use crate::net::tor::{OnionAddress, TorController, TorSecretKey}; use crate::net::tor::{OnionAddress, TorController, TorSecretKey};
use crate::net::utils::ipv6_is_local; use crate::net::utils::ipv6_is_local;
@@ -31,7 +32,6 @@ use crate::net::vhost::{AlpnInfo, TargetInfo, VHostController};
use crate::prelude::*; use crate::prelude::*;
use crate::service::effects::callbacks::ServiceCallbacks; use crate::service::effects::callbacks::ServiceCallbacks;
use crate::util::serde::MaybeUtf8String; use crate::util::serde::MaybeUtf8String;
use crate::HOST_IP;
pub struct NetController { pub struct NetController {
pub(crate) db: TypedPatchDb<Database>, pub(crate) db: TypedPatchDb<Database>,

View File

@@ -9,24 +9,19 @@ use arti_client::{TorClient, TorClientConfig};
use base64::Engine; use base64::Engine;
use clap::Parser; use clap::Parser;
use color_eyre::eyre::eyre; use color_eyre::eyre::eyre;
use futures::{FutureExt, Stream, StreamExt}; use futures::StreamExt;
use helpers::NonDetachingJoinHandle; use helpers::NonDetachingJoinHandle;
use imbl_value::InternedString; use imbl_value::InternedString;
use itertools::Itertools;
use lazy_static::lazy_static;
use regex::Regex;
use rpc_toolkit::{from_fn_async, Context, Empty, HandlerExt, ParentHandler}; use rpc_toolkit::{from_fn_async, Context, Empty, HandlerExt, ParentHandler};
use safelog::DisplayRedacted;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::sync::oneshot;
use tor_cell::relaycell::msg::Connected; use tor_cell::relaycell::msg::Connected;
use tor_hscrypto::pk::{HsId, HsIdKeypair}; use tor_hscrypto::pk::{HsId, HsIdKeypair};
use tor_hsservice::status::State as ArtiOnionServiceState; use tor_hsservice::status::State as ArtiOnionServiceState;
use tor_hsservice::{HsNickname, RendRequest, RunningOnionService}; use tor_hsservice::{HsNickname, RunningOnionService};
use tor_keymgr::config::ArtiKeystoreKind; use tor_keymgr::config::ArtiKeystoreKind;
use tor_proto::stream::IncomingStreamRequest; use tor_proto::client::stream::IncomingStreamRequest;
use tor_rtcompat::tokio::TokioRustlsRuntime; use tor_rtcompat::tokio::TokioRustlsRuntime;
use ts_rs::TS; use ts_rs::TS;
@@ -39,13 +34,11 @@ use crate::util::serde::{
}; };
use crate::util::sync::{SyncMutex, SyncRwLock}; use crate::util::sync::{SyncMutex, SyncRwLock};
const STARTING_HEALTH_TIMEOUT: u64 = 120; // 2min
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct OnionAddress(pub HsId); pub struct OnionAddress(pub HsId);
impl std::fmt::Display for OnionAddress { impl std::fmt::Display for OnionAddress {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt_unredacted(f) safelog::DisplayRedacted::fmt_unredacted(&self.0, f)
} }
} }
impl FromStr for OnionAddress { impl FromStr for OnionAddress {
@@ -201,7 +194,7 @@ impl std::fmt::Debug for OnionStore {
impl<'a> std::fmt::Debug for OnionStoreMap<'a> { impl<'a> std::fmt::Debug for OnionStoreMap<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
#[derive(Debug)] #[derive(Debug)]
struct KeyFor(OnionAddress); struct KeyFor(#[allow(unused)] OnionAddress);
let mut map = f.debug_map(); let mut map = f.debug_map();
for (k, v) in self.0 { for (k, v) in self.0 {
map.key(k); map.key(k);
@@ -451,7 +444,6 @@ impl TorController {
} }
pub async fn reset(&self, wipe_state: bool) -> Result<(), Error> { pub async fn reset(&self, wipe_state: bool) -> Result<(), Error> {
// todo!()
Ok(()) Ok(())
} }
@@ -488,7 +480,7 @@ impl OnionService {
.run_while(async { .run_while(async {
loop { loop {
if let Err(e) = async { if let Err(e) = async {
let (new_service, mut stream) = client.peek(|c| { let (new_service, stream) = client.peek(|c| {
c.launch_onion_service_with_hsid( c.launch_onion_service_with_hsid(
OnionServiceConfigBuilder::default() OnionServiceConfigBuilder::default()
.nickname( .nickname(
@@ -504,68 +496,81 @@ impl OnionService {
) )
.with_kind(ErrorKind::Tor) .with_kind(ErrorKind::Tor)
})?; })?;
let addr = new_service.onion_address().map(|a| safelog::DisplayRedacted::display_unredacted(&a).to_string());
let mut status_stream = new_service.status_events();
bg.add_job(async move {
while let Some(status) = status_stream.next().await {
tracing::debug!("{addr:?} status: {status:?}");
if let Some(err) = status.current_problem() {
tracing::error!("{err:?}");
}
}
});
service.replace(Some(new_service)); service.replace(Some(new_service));
let mut stream = tor_hsservice::handle_rend_requests(stream);
while let Some(req) = stream.next().await { while let Some(req) = stream.next().await {
bg.add_job({ bg.add_job({
let bg = bg.clone(); let bg = bg.clone();
let bindings = bindings.clone(); let bindings = bindings.clone();
async move { async move {
if let Err(e) = async { if let Err(e) = async {
let mut stream = let IncomingStreamRequest::Begin(begin) =
req.accept().await.with_kind(ErrorKind::Tor)?; req.request()
while let Some(req) = stream.next().await { else {
let IncomingStreamRequest::Begin(begin) = return req
req.request() .reject(tor_cell::relaycell::msg::End::new_with_reason(
else { tor_cell::relaycell::msg::EndReason::DONE,
continue; // TODO: reject instead? ))
};
let Some(target) = bindings.peek(|b| {
b.get(&begin.port()).and_then(|a| {
a.iter()
.find(|(_, rc)| {
rc.strong_count() > 0
})
.map(|(addr, _)| *addr)
})
}) else {
continue; // TODO: reject instead?
};
bg.add_job(async move {
if let Err(e) = async {
let mut outgoing =
TcpStream::connect(target)
.await
.with_kind(
ErrorKind::Network,
)?;
let mut incoming = req
.accept(Connected::new_empty())
.await
.with_kind(ErrorKind::Tor)?;
if let Err(e) =
tokio::io::copy_bidirectional(
&mut outgoing,
&mut incoming,
)
.await
{
tracing::error!("{e}");
tracing::debug!("{e:?}");
}
incoming.flush().await?;
outgoing.flush().await?;
incoming.shutdown().await?;
outgoing.shutdown().await?;
Ok::<_, Error>(())
}
.await .await
.with_kind(ErrorKind::Tor);
};
let Some(target) = bindings.peek(|b| {
b.get(&begin.port()).and_then(|a| {
a.iter()
.find(|(_, rc)| rc.strong_count() > 0)
.map(|(addr, _)| *addr)
})
}) else {
return req
.reject(tor_cell::relaycell::msg::End::new_with_reason(
tor_cell::relaycell::msg::EndReason::DONE,
))
.await
.with_kind(ErrorKind::Tor);
};
bg.add_job(async move {
if let Err(e) = async {
let mut outgoing =
TcpStream::connect(target)
.await
.with_kind(ErrorKind::Network)?;
let mut incoming = req
.accept(Connected::new_empty())
.await
.with_kind(ErrorKind::Tor)?;
if let Err(e) =
tokio::io::copy_bidirectional(
&mut outgoing,
&mut incoming,
)
.await
{ {
tracing::error!("{e}"); tracing::error!("{e}");
tracing::debug!("{e:?}"); tracing::debug!("{e:?}");
} }
}); incoming.flush().await?;
} outgoing.flush().await?;
incoming.shutdown().await?;
outgoing.shutdown().await?;
Ok::<_, Error>(())
}
.await
{
tracing::error!("{e}");
tracing::debug!("{e:?}");
}
});
Ok::<_, Error>(()) Ok::<_, Error>(())
} }
.await .await
@@ -623,6 +628,7 @@ impl OnionService {
} }
pub async fn shutdown(self) -> Result<(), Error> { pub async fn shutdown(self) -> Result<(), Error> {
self.0.service.replace(None);
self.0._thread.abort(); self.0._thread.abort();
Ok(()) Ok(())
} }

View File

@@ -6,8 +6,8 @@ use std::task::Poll;
use std::time::Duration; use std::time::Duration;
use axum::Router; use axum::Router;
use futures::future::Either;
use futures::FutureExt; use futures::FutureExt;
use futures::future::Either;
use helpers::NonDetachingJoinHandle; use helpers::NonDetachingJoinHandle;
use hyper_util::rt::{TokioIo, TokioTimer}; use hyper_util::rt::{TokioIo, TokioTimer};
use tokio::net::{TcpListener, TcpStream}; use tokio::net::{TcpListener, TcpStream};
@@ -15,7 +15,7 @@ use tokio::sync::oneshot;
use crate::context::{DiagnosticContext, InitContext, InstallContext, RpcContext, SetupContext}; use crate::context::{DiagnosticContext, InitContext, InstallContext, RpcContext, SetupContext};
use crate::net::gateway::{ use crate::net::gateway::{
lookup_info_by_addr, NetworkInterfaceListener, SelfContainedNetworkInterfaceListener, NetworkInterfaceListener, SelfContainedNetworkInterfaceListener, lookup_info_by_addr,
}; };
use crate::net::static_server::{ use crate::net::static_server::{
diagnostic_ui_router, init_ui_router, install_ui_router, main_ui_router, redirecter, refresher, diagnostic_ui_router, init_ui_router, install_ui_router, main_ui_router, redirecter, refresher,

View File

@@ -11,14 +11,14 @@ use crate::service::effects::prelude::*;
use crate::service::persistent_container::Subcontainer; use crate::service::persistent_container::Subcontainer;
use crate::util::Invoke; use crate::util::Invoke;
#[cfg(feature = "container-runtime")] #[cfg(feature = "start-container")]
mod sync; mod sync;
#[cfg(not(feature = "container-runtime"))] #[cfg(not(feature = "start-container"))]
mod sync_dummy; mod sync_dummy;
pub use sync::*; pub use sync::*;
#[cfg(not(feature = "container-runtime"))] #[cfg(not(feature = "start-container"))]
use sync_dummy as sync; use sync_dummy as sync;
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]

View File

@@ -82,7 +82,7 @@ impl BackgroundJobRunner {
cx: &mut std::task::Context<'_>, cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> { ) -> std::task::Poll<Self::Output> {
let this = self.project(); let this = self.project();
this.runner.poll(cx); let _ = this.runner.poll(cx);
this.fut.poll(cx) this.fut.poll(cx)
} }
} }

View File

@@ -6,8 +6,8 @@ use std::os::unix::prelude::MetadataExt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::pin::Pin; use std::pin::Pin;
use std::str::FromStr; use std::str::FromStr;
use std::sync::atomic::AtomicU64;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::AtomicU64;
use std::task::{Poll, Waker}; use std::task::{Poll, Waker};
use std::time::Duration; use std::time::Duration;
@@ -22,7 +22,7 @@ use nix::unistd::{Gid, Uid};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::fs::{File, OpenOptions}; use tokio::fs::{File, OpenOptions};
use tokio::io::{ use tokio::io::{
duplex, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, DuplexStream, ReadBuf, WriteHalf, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, DuplexStream, ReadBuf, WriteHalf, duplex,
}; };
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::sync::{Notify, OwnedMutexGuard}; use tokio::sync::{Notify, OwnedMutexGuard};

View File

@@ -5,8 +5,8 @@ use std::sync::atomic::AtomicUsize;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::task::{Poll, Waker}; use std::task::{Poll, Waker};
use futures::stream::BoxStream;
use futures::Stream; use futures::Stream;
use futures::stream::BoxStream;
use crate::prelude::*; use crate::prelude::*;

View File

@@ -193,7 +193,7 @@ export class PublicDomainService {
), ),
250, 250,
) )
} else if (ip === wanIp) { } else if (ip !== wanIp) {
setTimeout( setTimeout(
() => () =>
this.showDns( this.showDns(

View File

@@ -167,10 +167,9 @@ export class InterfaceTorDomainsComponent {
const loader = this.loader.open('Saving').subscribe() const loader = this.loader.open('Saving').subscribe()
try { try {
let onion = key const onion = key
? await this.api.addTorKey({ key }) ? await this.api.addTorKey({ key })
: await this.api.generateTorKey({}) : await this.api.generateTorKey({})
onion = `${onion}.onion`
if (this.interface.packageId) { if (this.interface.packageId) {
await this.api.pkgAddOnion({ await this.api.pkgAddOnion({

View File

@@ -114,14 +114,16 @@ export default class ServiceInterfaceRoute {
const { serviceInterfaces, hosts } = pkg const { serviceInterfaces, hosts } = pkg
const iFace = serviceInterfaces[this.interfaceId()] const iFace = serviceInterfaces[this.interfaceId()]
const key = iFace?.addressInfo.hostId || '' const key = iFace!.addressInfo.hostId || ''
const host = hosts[key] const host = hosts[key]
const port = iFace?.addressInfo.internalPort const port = iFace!.addressInfo.internalPort
if (!host || !iFace || !port) { if (!host || !iFace || !port) {
return return
} }
const binding = host.bindings[port]
const gateways = this.gatewayService.gateways() || [] const gateways = this.gatewayService.gateways() || []
return { return {
@@ -129,10 +131,13 @@ export default class ServiceInterfaceRoute {
addresses: this.interfaceService.getAddresses(iFace, host, gateways), addresses: this.interfaceService.getAddresses(iFace, host, gateways),
gateways: gateways:
gateways.map(g => ({ gateways.map(g => ({
enabled: true, enabled:
(g.public
? binding?.net.publicEnabled.includes(g.id)
: !binding?.net.privateDisabled.includes(g.id)) ?? false,
...g, ...g,
})) || [], })) || [],
torDomains: host.onions.map(o => `${o}.onion`), torDomains: host.onions,
publicDomains: getPublicDomains(host.publicDomains, gateways), publicDomains: getPublicDomains(host.publicDomains, gateways),
privateDomains: host.privateDomains, privateDomains: host.privateDomains,
} }

View File

@@ -84,6 +84,8 @@ export default class StartOsUiComponent {
if (!network || !gateways) return if (!network || !gateways) return
const binding = network.host.bindings['80']
return { return {
...this.iface, ...this.iface,
addresses: this.interfaceService.getAddresses( addresses: this.interfaceService.getAddresses(
@@ -92,10 +94,13 @@ export default class StartOsUiComponent {
gateways, gateways,
), ),
gateways: gateways.map(g => ({ gateways: gateways.map(g => ({
enabled: true, enabled:
(g.public
? binding?.net.publicEnabled.includes(g.id)
: !binding?.net.privateDisabled.includes(g.id)) ?? false,
...g, ...g,
})), })),
torDomains: network.host.onions.map(o => `${o}.onion`), torDomains: network.host.onions,
publicDomains: getPublicDomains(network.host.publicDomains, gateways), publicDomains: getPublicDomains(network.host.publicDomains, gateways),
privateDomains: network.host.privateDomains, privateDomains: network.host.privateDomains,
} }

View File

@@ -280,7 +280,7 @@ export namespace RR {
key: string key: string
} }
export type GenerateTorKeyReq = {} // net.tor.key.generate export type GenerateTorKeyReq = {} // net.tor.key.generate
export type AddTorKeyRes = string // onion address without .onion suffix export type AddTorKeyRes = string // onion address *with* .onion suffix
export type ServerBindingToggleGatewayReq = { export type ServerBindingToggleGatewayReq = {
// server.host.binding.set-gateway-enabled // server.host.binding.set-gateway-enabled

View File

@@ -1339,12 +1339,12 @@ export class MockApiService extends ApiService {
async addTorKey(params: RR.AddTorKeyReq): Promise<RR.AddTorKeyRes> { async addTorKey(params: RR.AddTorKeyReq): Promise<RR.AddTorKeyRes> {
await pauseFor(2000) await pauseFor(2000)
return 'vanityabcdefghijklmnop' return 'vanityabcdefghijklmnop.onion'
} }
async generateTorKey(params: RR.GenerateTorKeyReq): Promise<RR.AddTorKeyRes> { async generateTorKey(params: RR.GenerateTorKeyReq): Promise<RR.AddTorKeyRes> {
await pauseFor(2000) await pauseFor(2000)
return 'abcdefghijklmnopqrstuv' return 'abcdefghijklmnopqrstuv.onion'
} }
async serverBindingToggleGateway( async serverBindingToggleGateway(