From cd70fa4c32edf356dcfd35768d6851e7dcbb2893 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Thu, 18 Dec 2025 04:22:56 -0700 Subject: [PATCH] hotfixes for alpha.16 --- Makefile | 2 +- build/lib/scripts/forward-port | 58 ++++++++----- container-runtime/container-runtime.service | 1 + .../src/Adapters/Systems/SystemForStartOs.ts | 5 +- core/startos/src/action.rs | 4 +- core/startos/src/backup/backup_bulk.rs | 2 +- core/startos/src/backup/mod.rs | 2 +- core/startos/src/backup/restore.rs | 3 +- core/startos/src/backup/target/mod.rs | 5 +- core/startos/src/bins/tunnel.rs | 2 +- core/startos/src/context/rpc.rs | 5 +- core/startos/src/context/setup.rs | 2 +- core/startos/src/control.rs | 3 +- core/startos/src/db/model/package.rs | 4 +- core/startos/src/db/model/private.rs | 2 +- core/startos/src/db/model/public.rs | 3 +- core/startos/src/dependencies.rs | 3 +- core/startos/src/disk/mount/backup.rs | 2 +- .../src/disk/mount/filesystem/idmapped.rs | 3 +- core/startos/src/disk/mount/guard.rs | 3 +- core/startos/src/error.rs | 12 +-- core/startos/src/id/gateway.rs | 2 +- core/startos/src/id/host.rs | 2 +- core/startos/src/id/mod.rs | 2 +- core/startos/src/id/package.rs | 2 +- core/startos/src/id/replay.rs | 2 +- core/startos/src/id/service_interface.rs | 2 +- core/startos/src/install/mod.rs | 3 +- core/startos/src/lib.rs | 2 +- core/startos/src/logs.rs | 5 +- core/startos/src/lxc/mod.rs | 5 +- core/startos/src/net/acme.rs | 4 +- core/startos/src/net/dns.rs | 4 +- core/startos/src/net/forward.rs | 44 +++++++++- core/startos/src/net/gateway.rs | 83 +++++++++++++------ core/startos/src/net/host/address.rs | 2 +- core/startos/src/net/host/binding.rs | 4 +- core/startos/src/net/host/mod.rs | 2 +- core/startos/src/net/net_controller.rs | 21 ++++- core/startos/src/net/service_interface.rs | 3 +- core/startos/src/net/socks.rs | 2 +- core/startos/src/net/static_server.rs | 3 +- core/startos/src/net/tor/arti.rs | 3 +- core/startos/src/net/tor/ctor.rs | 2 +- core/startos/src/net/tunnel.rs | 2 +- core/startos/src/net/utils.rs | 2 +- core/startos/src/net/vhost.rs | 5 +- core/startos/src/net/web_server.rs | 4 +- core/startos/src/notifications.rs | 4 +- core/startos/src/os_install/mod.rs | 3 +- core/startos/src/registry/asset.rs | 2 +- core/startos/src/registry/info.rs | 2 +- core/startos/src/registry/mod.rs | 2 +- core/startos/src/registry/package/add.rs | 4 +- core/startos/src/registry/package/category.rs | 2 +- core/startos/src/registry/package/get.rs | 2 +- core/startos/src/registry/package/index.rs | 4 +- core/startos/src/registry/package/signer.rs | 2 +- core/startos/src/registry/signer.rs | 2 +- core/startos/src/rpc_continuations.rs | 3 +- core/startos/src/s9pk/rpc.rs | 2 +- core/startos/src/s9pk/v1/manifest.rs | 4 +- core/startos/src/s9pk/v1/reader.rs | 2 +- core/startos/src/s9pk/v2/manifest.rs | 7 +- core/startos/src/s9pk/v2/mod.rs | 4 +- core/startos/src/service/action.rs | 5 +- core/startos/src/service/effects/action.rs | 2 +- core/startos/src/service/effects/callbacks.rs | 4 +- core/startos/src/service/effects/control.rs | 4 +- .../startos/src/service/effects/dependency.rs | 5 +- core/startos/src/service/effects/health.rs | 1 - core/startos/src/service/effects/net/bind.rs | 3 +- core/startos/src/service/effects/net/host.rs | 3 +- core/startos/src/service/effects/net/info.rs | 1 - .../src/service/effects/net/interface.rs | 2 +- core/startos/src/service/mod.rs | 5 +- .../src/service/persistent_container.rs | 8 +- core/startos/src/service/rpc.rs | 5 +- core/startos/src/service/service_actor.rs | 4 +- core/startos/src/service/service_map.rs | 17 +++- core/startos/src/service/transition/backup.rs | 3 +- core/startos/src/service/uninstall.rs | 4 +- core/startos/src/sign/mod.rs | 2 +- core/startos/src/ssh.rs | 3 +- core/startos/src/status/health_check.rs | 5 +- core/startos/src/status/mod.rs | 4 +- core/startos/src/tunnel/api.rs | 68 ++++++++++++++- core/startos/src/tunnel/context.rs | 72 ++++++++-------- core/startos/src/tunnel/db.rs | 2 +- core/startos/src/tunnel/wg.rs | 5 +- core/startos/src/update/mod.rs | 2 +- core/startos/src/util/actor/concurrent.rs | 2 +- core/startos/src/util/actor/simple.rs | 2 +- core/startos/src/util/data_url.rs | 2 +- core/startos/src/util/io.rs | 2 +- core/startos/src/util/lshw.rs | 2 +- core/startos/src/util/mod.rs | 4 +- core/startos/src/util/rpc_client.rs | 2 +- core/startos/src/util/rsync.rs | 2 +- core/startos/src/util/serde.rs | 3 +- core/startos/src/util/sync.rs | 2 +- core/startos/src/version/v0_3_6_alpha_0.rs | 3 +- core/startos/src/version/v0_3_6_alpha_10.rs | 2 +- core/startos/src/version/v0_4_0_alpha_12.rs | 2 +- core/startos/src/version/v0_4_0_alpha_9.rs | 3 +- core/startos/src/volume.rs | 1 - core/startos/start-registryd.service | 2 +- core/startos/start-tunneld.service | 2 +- core/startos/startd.service | 2 +- 109 files changed, 410 insertions(+), 263 deletions(-) diff --git a/Makefile b/Makefile index 0096d1615..61daa2f33 100644 --- a/Makefile +++ b/Makefile @@ -161,7 +161,7 @@ results/$(REGISTRY_BASENAME).deb: dpkg-build.sh $(call ls-files,debian/start-reg tunnel-deb: results/$(TUNNEL_BASENAME).deb -results/$(TUNNEL_BASENAME).deb: dpkg-build.sh $(call ls-files,debian/start-tunnel) $(TUNNEL_TARGETS) +results/$(TUNNEL_BASENAME).deb: dpkg-build.sh $(call ls-files,debian/start-tunnel) $(TUNNEL_TARGETS) build/lib/scripts/forward-port PROJECT=start-tunnel PLATFORM=$(ARCH) REQUIRES=debian DEPENDS=wireguard-tools,iptables,conntrack ./build/os-compat/run-compat.sh ./dpkg-build.sh $(IMAGE_TYPE): results/$(BASENAME).$(IMAGE_TYPE) diff --git a/build/lib/scripts/forward-port b/build/lib/scripts/forward-port index d5fef3931..ec669bc02 100755 --- a/build/lib/scripts/forward-port +++ b/build/lib/scripts/forward-port @@ -5,29 +5,47 @@ if [ -z "$sip" ] || [ -z "$dip" ] || [ -z "$sport" ] || [ -z "$dport" ]; then exit 1 fi -rule_exists() { - iptables -t nat -C "$@" 2>/dev/null -} +NAME="F$(echo "$sip:$sport -> $dip:$dport" | sha256sum | head -c 15)" -apply_rule() { - if [ "$UNDO" = "1" ]; then - if rule_exists "$@"; then - iptables -t nat -D "$@" - fi - else - if ! rule_exists "$@"; then - iptables -t nat -A "$@" - fi +for kind in INPUT FORWARD ACCEPT; do + if ! iptables -C $kind -j "${NAME}_${kind}" 2> /dev/null; then + iptables -N "${NAME}_${kind}" 2> /dev/null + iptables -A $kind -j "${NAME}_${kind}" fi -} +done +for kind in PREROUTING INPUT OUTPUT POSTROUTING; do + if ! iptables -t nat -C $kind -j "${NAME}_${kind}" 2> /dev/null; then + iptables -t nat -N "${NAME}_${kind}" 2> /dev/null + iptables -t nat -A $kind -j "${NAME}_${kind}" + fi +done -apply_rule PREROUTING -p tcp -d $sip --dport $sport -j DNAT --to-destination $dip:$dport -apply_rule PREROUTING -p udp -d $sip --dport $sport -j DNAT --to-destination $dip:$dport -apply_rule OUTPUT -p tcp -d $sip --dport $sport -j DNAT --to-destination $dip:$dport -apply_rule OUTPUT -p udp -d $sip --dport $sport -j DNAT --to-destination $dip:$dport -apply_rule POSTROUTING -p tcp -d $dip --dport $dport -j MASQUERADE -apply_rule POSTROUTING -p udp -d $dip --dport $dport -j MASQUERADE +err=0 +trap 'err=1' ERR +for kind in INPUT FORWARD ACCEPT; do + iptables -F "${NAME}_${kind}" 2> /dev/null +done +for kind in PREROUTING INPUT OUTPUT POSTROUTING; do + iptables -t nat -F "${NAME}_${kind}" 2> /dev/null +done if [ "$UNDO" = 1 ]; then conntrack -D -p tcp -d $sip --dport $sport || true # conntrack returns exit 1 if no connections are active -fi \ No newline at end of file + conntrack -D -p udp -d $sip --dport $sport || true # conntrack returns exit 1 if no connections are active + exit $err +fi + +iptables -t nat -A ${NAME}_PREROUTING -d "$sip" -p tcp --dport "$sport" -j DNAT --to-destination "$dip:$dport" +iptables -t nat -A ${NAME}_PREROUTING -d "$sip" -p udp --dport "$sport" -j DNAT --to-destination "$dip:$dport" +iptables -t nat -A ${NAME}_OUTPUT -d "$sip" -p tcp --dport "$sport" -j DNAT --to-destination "$dip:$dport" +iptables -t nat -A ${NAME}_OUTPUT -d "$sip" -p udp --dport "$sport" -j DNAT --to-destination "$dip:$dport" + +iptables -t nat -A ${NAME}_PREROUTING -s "$dip/24" -d "$sip" -p tcp --dport "$sport" -j DNAT --to-destination "$dip:$dport" +iptables -t nat -A ${NAME}_PREROUTING -s "$dip/24" -d "$sip" -p udp --dport "$sport" -j DNAT --to-destination "$dip:$dport" +iptables -t nat -A ${NAME}_POSTROUTING -s "$dip/24" -d "$dip" -p tcp --dport "$dport" -j MASQUERADE +iptables -t nat -A ${NAME}_POSTROUTING -s "$dip/24" -d "$dip" -p udp --dport "$dport" -j MASQUERADE + +iptables -A ${NAME}_FORWARD -d $dip -p tcp --dport $dport -m state --state NEW -j ACCEPT +iptables -A ${NAME}_FORWARD -d $dip -p udp --dport $dport -m state --state NEW -j ACCEPT + +exit $err \ No newline at end of file diff --git a/container-runtime/container-runtime.service b/container-runtime/container-runtime.service index 2f4b03497..ed9d142f7 100644 --- a/container-runtime/container-runtime.service +++ b/container-runtime/container-runtime.service @@ -4,6 +4,7 @@ OnFailure=container-runtime-failure.service [Service] Type=simple +Environment=RUST_LOG=startos=debug ExecStart=/usr/bin/node --experimental-detect-module --trace-warnings --unhandled-rejections=warn /usr/lib/startos/init/index.js Restart=no diff --git a/container-runtime/src/Adapters/Systems/SystemForStartOs.ts b/container-runtime/src/Adapters/Systems/SystemForStartOs.ts index 1d7e8fc97..837946ca0 100644 --- a/container-runtime/src/Adapters/Systems/SystemForStartOs.ts +++ b/container-runtime/src/Adapters/Systems/SystemForStartOs.ts @@ -68,7 +68,10 @@ export class SystemForStartOs implements System { try { if (this.runningMain || this.starting) return this.starting = true - effects.constRetry = utils.once(() => effects.restart()) + effects.constRetry = utils.once(() => { + console.debug(".const() triggered") + effects.restart() + }) let mainOnTerm: () => Promise | undefined const daemons = await ( await this.abi.main({ diff --git a/core/startos/src/action.rs b/core/startos/src/action.rs index d9b5ba2d8..50e610e7c 100644 --- a/core/startos/src/action.rs +++ b/core/startos/src/action.rs @@ -1,14 +1,13 @@ use std::fmt; use clap::{CommandFactory, FromArgMatches, Parser}; -pub use crate::ActionId; -use crate::{PackageId, ReplayId}; use qrcode::QrCode; use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use tracing::instrument; use ts_rs::TS; +pub use crate::ActionId; use crate::context::{CliContext, RpcContext}; use crate::db::model::package::TaskSeverity; use crate::prelude::*; @@ -16,6 +15,7 @@ use crate::rpc_continuations::Guid; use crate::util::serde::{ HandlerExtSerde, StdinDeserializable, WithIoFormat, display_serializable, }; +use crate::{PackageId, ReplayId}; pub fn action_api() -> ParentHandler { ParentHandler::new() diff --git a/core/startos/src/backup/backup_bulk.rs b/core/startos/src/backup/backup_bulk.rs index b2795e0a4..d8bfae159 100644 --- a/core/startos/src/backup/backup_bulk.rs +++ b/core/startos/src/backup/backup_bulk.rs @@ -6,7 +6,6 @@ use chrono::Utc; use clap::Parser; use color_eyre::eyre::eyre; use imbl::OrdSet; -use crate::PackageId; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWriteExt; use tracing::instrument; @@ -14,6 +13,7 @@ use ts_rs::TS; use super::PackageBackupReport; use super::target::{BackupTargetId, PackageBackupInfo}; +use crate::PackageId; use crate::backup::os::OsBackup; use crate::backup::{BackupReport, ServerBackupReport}; use crate::context::RpcContext; diff --git a/core/startos/src/backup/mod.rs b/core/startos/src/backup/mod.rs index 3ca0b583c..a6e98b2b4 100644 --- a/core/startos/src/backup/mod.rs +++ b/core/startos/src/backup/mod.rs @@ -1,9 +1,9 @@ use std::collections::BTreeMap; -use crate::PackageId; use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; +use crate::PackageId; use crate::context::CliContext; #[allow(unused_imports)] use crate::prelude::*; diff --git a/core/startos/src/backup/restore.rs b/core/startos/src/backup/restore.rs index f06e86d45..daddd2248 100644 --- a/core/startos/src/backup/restore.rs +++ b/core/startos/src/backup/restore.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use clap::Parser; use futures::{StreamExt, stream}; -use crate::PackageId; use patch_db::json_ptr::ROOT; use serde::{Deserialize, Serialize}; use tokio::sync::Mutex; @@ -11,7 +10,6 @@ use tracing::instrument; use ts_rs::TS; use super::target::BackupTargetId; -use crate::PLATFORM; use crate::backup::os::OsBackup; use crate::context::setup::SetupResult; use crate::context::{RpcContext, SetupContext}; @@ -27,6 +25,7 @@ use crate::service::service_map::DownloadInstallFuture; use crate::setup::SetupExecuteProgress; use crate::system::sync_kiosk; use crate::util::serde::IoFormat; +use crate::{PLATFORM, PackageId}; #[derive(Deserialize, Serialize, Parser, TS)] #[serde(rename_all = "camelCase")] diff --git a/core/startos/src/backup/target/mod.rs b/core/startos/src/backup/target/mod.rs index eaeee2e7a..616cffd3b 100644 --- a/core/startos/src/backup/target/mod.rs +++ b/core/startos/src/backup/target/mod.rs @@ -9,8 +9,6 @@ use digest::OutputSizeUser; use digest::generic_array::GenericArray; use exver::Version; use imbl_value::InternedString; -use crate::util::FromStrParser; -use crate::PackageId; use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use sha2::Sha256; @@ -19,6 +17,7 @@ use tracing::instrument; use ts_rs::TS; use self::cifs::CifsBackupTarget; +use crate::PackageId; use crate::context::{CliContext, RpcContext}; use crate::db::model::DatabaseModel; use crate::disk::mount::backup::BackupMountGuard; @@ -28,10 +27,10 @@ use crate::disk::mount::filesystem::{FileSystem, MountType, ReadWrite}; use crate::disk::mount::guard::{GenericMountGuard, TmpMountGuard}; use crate::disk::util::PartitionInfo; use crate::prelude::*; -use crate::util::VersionString; use crate::util::serde::{ HandlerExtSerde, WithIoFormat, deserialize_from_str, display_serializable, serialize_display, }; +use crate::util::{FromStrParser, VersionString}; pub mod cifs; diff --git a/core/startos/src/bins/tunnel.rs b/core/startos/src/bins/tunnel.rs index 0687493ac..5c018f796 100644 --- a/core/startos/src/bins/tunnel.rs +++ b/core/startos/src/bins/tunnel.rs @@ -5,7 +5,6 @@ use std::time::Duration; use clap::Parser; use futures::FutureExt; -use crate::util::future::NonDetachingJoinHandle; use rpc_toolkit::CliApp; use tokio::signal::unix::signal; use tracing::instrument; @@ -20,6 +19,7 @@ use crate::prelude::*; use crate::tunnel::context::{TunnelConfig, TunnelContext}; use crate::tunnel::tunnel_router; use crate::tunnel::web::TunnelCertHandler; +use crate::util::future::NonDetachingJoinHandle; use crate::util::logger::LOGGER; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] diff --git a/core/startos/src/context/rpc.rs b/core/startos/src/context/rpc.rs index 4095a9e6c..f8be8af19 100644 --- a/core/startos/src/context/rpc.rs +++ b/core/startos/src/context/rpc.rs @@ -8,12 +8,10 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; use chrono::{TimeDelta, Utc}; -use crate::util::future::NonDetachingJoinHandle; use imbl::OrdMap; use imbl_value::InternedString; use itertools::Itertools; use josekit::jwk::Jwk; -use crate::{ActionId, PackageId}; use reqwest::{Client, Proxy}; use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::{CallRemote, Context, Empty}; @@ -22,7 +20,6 @@ use tokio::time::Instant; use tracing::instrument; use super::setup::CURRENT_SECRET; -use crate::DATA_DIR; use crate::account::AccountInfo; use crate::auth::Sessions; use crate::context::config::ServerConfig; @@ -45,9 +42,11 @@ use crate::service::ServiceMap; use crate::service::action::update_tasks; use crate::service::effects::callbacks::ServiceCallbacks; use crate::shutdown::Shutdown; +use crate::util::future::NonDetachingJoinHandle; use crate::util::io::delete_file; use crate::util::lshw::LshwDevice; use crate::util::sync::{SyncMutex, SyncRwLock, Watch}; +use crate::{ActionId, DATA_DIR, PackageId}; pub struct RpcContextSeed { is_closed: AtomicBool, diff --git a/core/startos/src/context/setup.rs b/core/startos/src/context/setup.rs index 3c65eeedc..49c87e001 100644 --- a/core/startos/src/context/setup.rs +++ b/core/startos/src/context/setup.rs @@ -4,7 +4,6 @@ use std::sync::Arc; use std::time::Duration; use futures::{Future, StreamExt}; -use crate::util::future::NonDetachingJoinHandle; use imbl_value::InternedString; use josekit::jwk::Jwk; use patch_db::PatchDb; @@ -28,6 +27,7 @@ use crate::progress::FullProgressTracker; use crate::rpc_continuations::{Guid, RpcContinuation, RpcContinuations}; use crate::setup::SetupProgress; use crate::shutdown::Shutdown; +use crate::util::future::NonDetachingJoinHandle; use crate::util::net::WebSocketExt; lazy_static::lazy_static! { diff --git a/core/startos/src/control.rs b/core/startos/src/control.rs index fe4a3bd30..81a7547b4 100644 --- a/core/startos/src/control.rs +++ b/core/startos/src/control.rs @@ -1,12 +1,11 @@ use clap::Parser; -use crate::PackageId; use serde::{Deserialize, Serialize}; use tracing::instrument; use ts_rs::TS; -use crate::Error; use crate::context::RpcContext; use crate::prelude::*; +use crate::{Error, PackageId}; #[derive(Deserialize, Serialize, Parser, TS)] #[serde(rename_all = "camelCase")] diff --git a/core/startos/src/db/model/package.rs b/core/startos/src/db/model/package.rs index 073a30e14..b93904dfa 100644 --- a/core/startos/src/db/model/package.rs +++ b/core/startos/src/db/model/package.rs @@ -4,8 +4,6 @@ use std::path::PathBuf; use chrono::{DateTime, Utc}; use exver::VersionRange; use imbl_value::InternedString; -use crate::util::DataUrl; -use crate::{ActionId, HealthCheckId, HostId, PackageId, ReplayId, ServiceInterfaceId}; use patch_db::HasModel; use patch_db::json_ptr::JsonPointer; use reqwest::Url; @@ -18,7 +16,9 @@ use crate::prelude::*; use crate::progress::FullProgress; use crate::s9pk::manifest::Manifest; use crate::status::StatusInfo; +use crate::util::DataUrl; use crate::util::serde::{Pem, is_partial_of}; +use crate::{ActionId, HealthCheckId, HostId, PackageId, ReplayId, ServiceInterfaceId}; #[derive(Debug, Default, Deserialize, Serialize, TS)] #[ts(export)] diff --git a/core/startos/src/db/model/private.rs b/core/startos/src/db/model/private.rs index 6e7e8fb03..d9d48ff4d 100644 --- a/core/startos/src/db/model/private.rs +++ b/core/startos/src/db/model/private.rs @@ -1,9 +1,9 @@ use std::collections::{BTreeMap, HashSet}; -use crate::PackageId; use patch_db::{HasModel, Value}; use serde::{Deserialize, Serialize}; +use crate::PackageId; use crate::auth::Sessions; use crate::backup::target::cifs::CifsTargets; use crate::net::forward::AvailablePorts; diff --git a/core/startos/src/db/model/public.rs b/core/startos/src/db/model/public.rs index dfc104101..37018cd75 100644 --- a/core/startos/src/db/model/public.rs +++ b/core/startos/src/db/model/public.rs @@ -9,7 +9,6 @@ use imbl_value::InternedString; use ipnet::IpNet; use isocountry::CountryCode; use itertools::Itertools; -use crate::{GatewayId, PackageId}; use openssl::hash::MessageDigest; use patch_db::{HasModel, Value}; use serde::{Deserialize, Serialize}; @@ -31,7 +30,7 @@ use crate::util::cpupower::Governor; use crate::util::lshw::LshwDevice; use crate::util::serde::MaybeUtf8String; use crate::version::{Current, VersionT}; -use crate::{ARCH, PLATFORM}; +use crate::{ARCH, GatewayId, PLATFORM, PackageId}; pub static DB_UI_SEED_CELL: OnceLock<&'static str> = OnceLock::new(); diff --git a/core/startos/src/dependencies.rs b/core/startos/src/dependencies.rs index f322a298e..3b6f7bd75 100644 --- a/core/startos/src/dependencies.rs +++ b/core/startos/src/dependencies.rs @@ -2,13 +2,12 @@ use std::collections::BTreeMap; use std::path::Path; use imbl_value::InternedString; -use crate::PackageId; use serde::{Deserialize, Serialize}; use ts_rs::TS; -use crate::Error; use crate::prelude::*; use crate::util::PathOrUrl; +use crate::{Error, PackageId}; #[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel, TS)] #[model = "Model"] diff --git a/core/startos/src/disk/mount/backup.rs b/core/startos/src/disk/mount/backup.rs index d79e303f3..2c89981dc 100644 --- a/core/startos/src/disk/mount/backup.rs +++ b/core/startos/src/disk/mount/backup.rs @@ -2,11 +2,11 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use color_eyre::eyre::eyre; -use crate::PackageId; use tokio::io::AsyncWriteExt; use tracing::instrument; use super::guard::{GenericMountGuard, TmpMountGuard}; +use crate::PackageId; use crate::auth::check_password; use crate::backup::target::BackupInfo; use crate::disk::mount::filesystem::ReadWrite; diff --git a/core/startos/src/disk/mount/filesystem/idmapped.rs b/core/startos/src/disk/mount/filesystem/idmapped.rs index 3e92351b7..0a351b313 100644 --- a/core/startos/src/disk/mount/filesystem/idmapped.rs +++ b/core/startos/src/disk/mount/filesystem/idmapped.rs @@ -8,7 +8,6 @@ use clap::Parser; use clap::builder::ValueParserFactory; use digest::generic_array::GenericArray; use digest::{Digest, OutputSizeUser}; -use crate::util::FromStrParser; use serde::{Deserialize, Serialize}; use sha2::Sha256; use tokio::process::Command; @@ -16,7 +15,7 @@ use ts_rs::TS; use super::FileSystem; use crate::prelude::*; -use crate::util::Invoke; +use crate::util::{FromStrParser, Invoke}; #[derive(Clone, Copy, Debug, Deserialize, Serialize, Parser, TS)] #[serde(rename_all = "camelCase")] diff --git a/core/startos/src/disk/mount/guard.rs b/core/startos/src/disk/mount/guard.rs index e806b4150..66539ef2f 100644 --- a/core/startos/src/disk/mount/guard.rs +++ b/core/startos/src/disk/mount/guard.rs @@ -4,14 +4,13 @@ use std::sync::{Arc, Weak}; use futures::Future; use lazy_static::lazy_static; -use crate::ResultExt; use tokio::sync::Mutex; use tracing::instrument; use super::filesystem::{FileSystem, MountType, ReadOnly, ReadWrite}; use super::util::unmount; -use crate::Error; use crate::util::{Invoke, Never}; +use crate::{Error, ResultExt}; pub const TMP_MOUNTPOINT: &'static str = "/media/startos/tmp"; diff --git a/core/startos/src/error.rs b/core/startos/src/error.rs index 279ba1e6b..f8554e378 100644 --- a/core/startos/src/error.rs +++ b/core/startos/src/error.rs @@ -1,7 +1,6 @@ use std::fmt::{Debug, Display}; use axum::http::StatusCode; -use tokio_rustls::rustls; use axum::http::uri::InvalidUri; use color_eyre::eyre::eyre; use num_enum::TryFromPrimitive; @@ -12,6 +11,7 @@ use rpc_toolkit::yajrc::{ }; use serde::{Deserialize, Serialize}; use tokio::task::JoinHandle; +use tokio_rustls::rustls; use ts_rs::TS; use crate::InvalidId; @@ -217,8 +217,9 @@ impl Error { source: E, kind: ErrorKind, ) -> Self { - let debug = (std::any::TypeId::of::() == std::any::TypeId::of::()) - .then(|| eyre!("{source:?}")); + let debug = (std::any::TypeId::of::() + == std::any::TypeId::of::()) + .then(|| eyre!("{source:?}")); Error { source: source.into(), debug, @@ -591,8 +592,9 @@ where fn with_ctx (ErrorKind, D), D: Display>(self, f: F) -> Result { self.map_err(|e| { let (kind, ctx) = f(&e); - let debug = (std::any::TypeId::of::() == std::any::TypeId::of::()) - .then(|| eyre!("{ctx}: {e:?}")); + let debug = (std::any::TypeId::of::() + == std::any::TypeId::of::()) + .then(|| eyre!("{ctx}: {e:?}")); let source = color_eyre::eyre::Error::from(e); let with_ctx = format!("{ctx}: {source}"); let source = source.wrap_err(with_ctx); diff --git a/core/startos/src/id/gateway.rs b/core/startos/src/id/gateway.rs index 215f91a15..46361e5d5 100644 --- a/core/startos/src/id/gateway.rs +++ b/core/startos/src/id/gateway.rs @@ -2,9 +2,9 @@ use std::convert::Infallible; use std::path::Path; use std::str::FromStr; +use imbl_value::InternedString; use serde::{Deserialize, Serialize}; use ts_rs::TS; -use imbl_value::InternedString; #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, TS)] #[ts(type = "string")] diff --git a/core/startos/src/id/host.rs b/core/startos/src/id/host.rs index 67b512f08..aea296ab5 100644 --- a/core/startos/src/id/host.rs +++ b/core/startos/src/id/host.rs @@ -1,9 +1,9 @@ use std::path::Path; use std::str::FromStr; +use imbl_value::InternedString; use serde::{Deserialize, Deserializer, Serialize}; use ts_rs::TS; -use imbl_value::InternedString; use crate::{Id, InvalidId}; diff --git a/core/startos/src/id/mod.rs b/core/startos/src/id/mod.rs index 6783b6e84..3517f30fc 100644 --- a/core/startos/src/id/mod.rs +++ b/core/startos/src/id/mod.rs @@ -1,9 +1,9 @@ use std::borrow::Borrow; use std::str::FromStr; +use imbl_value::InternedString; use regex::Regex; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use imbl_value::InternedString; mod action; mod gateway; diff --git a/core/startos/src/id/package.rs b/core/startos/src/id/package.rs index 2dc7e0ae5..e0fff3ece 100644 --- a/core/startos/src/id/package.rs +++ b/core/startos/src/id/package.rs @@ -2,9 +2,9 @@ use std::borrow::Borrow; use std::path::Path; use std::str::FromStr; +use imbl_value::InternedString; use serde::{Deserialize, Serialize, Serializer}; use ts_rs::TS; -use imbl_value::InternedString; use crate::{Id, InvalidId, SYSTEM_ID}; diff --git a/core/startos/src/id/replay.rs b/core/startos/src/id/replay.rs index 2bc169aa5..8e56bff68 100644 --- a/core/startos/src/id/replay.rs +++ b/core/startos/src/id/replay.rs @@ -2,9 +2,9 @@ use std::convert::Infallible; use std::path::Path; use std::str::FromStr; +use imbl_value::InternedString; use serde::{Deserialize, Serialize}; use ts_rs::TS; -use imbl_value::InternedString; #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, TS)] #[ts(type = "string")] diff --git a/core/startos/src/id/service_interface.rs b/core/startos/src/id/service_interface.rs index 27a3f7d82..26ec80e6f 100644 --- a/core/startos/src/id/service_interface.rs +++ b/core/startos/src/id/service_interface.rs @@ -5,8 +5,8 @@ use rpc_toolkit::clap::builder::ValueParserFactory; use serde::{Deserialize, Deserializer, Serialize}; use ts_rs::TS; -use crate::util::FromStrParser; use crate::Id; +use crate::util::FromStrParser; #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, TS)] #[ts(export, type = "string")] diff --git a/core/startos/src/install/mod.rs b/core/startos/src/install/mod.rs index 588ae3fb4..64b8ceda7 100644 --- a/core/startos/src/install/mod.rs +++ b/core/startos/src/install/mod.rs @@ -10,7 +10,6 @@ use exver::VersionRange; use futures::StreamExt; use imbl_value::{InternedString, json}; use itertools::Itertools; -use crate::util::{FromStrParser, VersionString}; use reqwest::Url; use reqwest::header::{CONTENT_LENGTH, HeaderMap}; use rpc_toolkit::HandlerArgs; @@ -31,10 +30,10 @@ use crate::rpc_continuations::{Guid, RpcContinuation}; use crate::s9pk::manifest::PackageId; use crate::s9pk::v2::SIG_CONTEXT; use crate::upload::upload; -use crate::util::Never; use crate::util::io::open_file; use crate::util::net::WebSocketExt; use crate::util::tui::choose; +use crate::util::{FromStrParser, Never, VersionString}; pub const PKG_ARCHIVE_DIR: &str = "package-data/archive"; pub const PKG_PUBLIC_DIR: &str = "package-data/public"; diff --git a/core/startos/src/lib.rs b/core/startos/src/lib.rs index 2383305ca..e15198c0e 100644 --- a/core/startos/src/lib.rs +++ b/core/startos/src/lib.rs @@ -43,8 +43,8 @@ pub mod diagnostic; pub mod disk; pub mod error; pub mod firmware; -pub mod id; pub mod hostname; +pub mod id; pub mod init; pub mod install; pub mod logs; diff --git a/core/startos/src/logs.rs b/core/startos/src/logs.rs index 17199d117..5a2ee4587 100644 --- a/core/startos/src/logs.rs +++ b/core/startos/src/logs.rs @@ -13,8 +13,6 @@ use color_eyre::eyre::eyre; use futures::stream::BoxStream; use futures::{Future, FutureExt, Stream, StreamExt, TryStreamExt}; use itertools::Itertools; -use crate::util::FromStrParser; -use crate::PackageId; use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::{ CallRemote, Context, Empty, HandlerArgs, HandlerExt, HandlerFor, ParentHandler, from_fn_async, @@ -27,13 +25,14 @@ use tokio_stream::wrappers::LinesStream; use tokio_tungstenite::tungstenite::Message; use tracing::instrument; +use crate::PackageId; use crate::context::{CliContext, RpcContext}; use crate::error::ResultExt; use crate::prelude::*; use crate::rpc_continuations::{Guid, RpcContinuation, RpcContinuations}; -use crate::util::Invoke; use crate::util::net::WebSocketExt; use crate::util::serde::Reversible; +use crate::util::{FromStrParser, Invoke}; #[pin_project::pin_project] pub struct LogStream { diff --git a/core/startos/src/lxc/mod.rs b/core/startos/src/lxc/mod.rs index 2b154309e..30734c322 100644 --- a/core/startos/src/lxc/mod.rs +++ b/core/startos/src/lxc/mod.rs @@ -7,8 +7,6 @@ use std::time::Duration; use clap::builder::ValueParserFactory; use futures::StreamExt; use imbl_value::InternedString; -use crate::util::FromStrParser; -use crate::{InvalidId, PackageId}; use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::{RpcRequest, RpcResponse}; use serde::{Deserialize, Serialize}; @@ -31,7 +29,8 @@ use crate::rpc_continuations::{Guid, RpcContinuation}; use crate::service::ServiceStats; use crate::util::io::open_file; use crate::util::rpc_client::UnixRpcClient; -use crate::util::{Invoke, new_guid}; +use crate::util::{FromStrParser, Invoke, new_guid}; +use crate::{InvalidId, PackageId}; const LXC_CONTAINER_DIR: &str = "/var/lib/lxc"; const RPC_DIR: &str = "media/startos/rpc"; // must not be absolute path diff --git a/core/startos/src/net/acme.rs b/core/startos/src/net/acme.rs index 94f00af20..1d0874c81 100644 --- a/core/startos/src/net/acme.rs +++ b/core/startos/src/net/acme.rs @@ -9,8 +9,6 @@ use clap::builder::ValueParserFactory; use futures::StreamExt; use imbl_value::InternedString; use itertools::Itertools; -use crate::error::ErrorData; -use crate::util::FromStrParser; use openssl::pkey::{PKey, Private}; use openssl::x509::X509; use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; @@ -27,10 +25,12 @@ use crate::context::{CliContext, RpcContext}; use crate::db::model::Database; use crate::db::model::public::AcmeSettings; use crate::db::{DbAccess, DbAccessByKey, DbAccessMut}; +use crate::error::ErrorData; use crate::net::ssl::should_use_cert; use crate::net::tls::{SingleCertResolver, TlsHandler}; use crate::net::web_server::Accept; use crate::prelude::*; +use crate::util::FromStrParser; use crate::util::serde::{Pem, Pkcs8Doc}; use crate::util::sync::{SyncMutex, Watch}; diff --git a/core/startos/src/net/dns.rs b/core/startos/src/net/dns.rs index 2b18cc206..7e0a09d1e 100644 --- a/core/startos/src/net/dns.rs +++ b/core/startos/src/net/dns.rs @@ -9,7 +9,6 @@ use clap::Parser; use color_eyre::eyre::eyre; use futures::future::BoxFuture; use futures::{FutureExt, StreamExt}; -use crate::util::future::NonDetachingJoinHandle; use hickory_client::client::Client; use hickory_client::proto::DnsHandle; use hickory_client::proto::runtime::TokioRuntimeProvider; @@ -23,7 +22,6 @@ use hickory_server::proto::rr::{Name, Record, RecordType}; use hickory_server::server::{Request, RequestHandler, ResponseHandler, ResponseInfo}; use imbl::OrdMap; use imbl_value::InternedString; -use crate::{GatewayId, OptionExt, PackageId}; use patch_db::json_ptr::JsonPointer; use rpc_toolkit::{ Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async, from_fn_blocking, @@ -38,9 +36,11 @@ use crate::db::model::public::NetworkInterfaceInfo; use crate::net::gateway::NetworkInterfaceWatcher; use crate::prelude::*; use crate::util::actor::background::BackgroundJobQueue; +use crate::util::future::NonDetachingJoinHandle; use crate::util::io::file_string_stream; use crate::util::serde::{HandlerExtSerde, display_serializable}; use crate::util::sync::{SyncRwLock, Watch}; +use crate::{GatewayId, OptionExt, PackageId}; pub fn dns_api() -> ParentHandler { ParentHandler::new() diff --git a/core/startos/src/net/forward.rs b/core/startos/src/net/forward.rs index 9a535fa4b..a9451e4e6 100644 --- a/core/startos/src/net/forward.rs +++ b/core/startos/src/net/forward.rs @@ -4,21 +4,21 @@ use std::sync::{Arc, Weak}; use std::time::Duration; use futures::channel::oneshot; -use crate::util::future::NonDetachingJoinHandle; use id_pool::IdPool; use iddqd::{IdOrdItem, IdOrdMap}; use imbl::OrdMap; -use crate::GatewayId; use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use tokio::process::Command; use tokio::sync::mpsc; +use crate::GatewayId; use crate::context::{CliContext, RpcContext}; use crate::db::model::public::NetworkInterfaceInfo; use crate::net::gateway::{DynInterfaceFilter, InterfaceFilter}; use crate::prelude::*; use crate::util::Invoke; +use crate::util::future::NonDetachingJoinHandle; use crate::util::serde::{HandlerExtSerde, display_serializable}; use crate::util::sync::Watch; @@ -180,11 +180,51 @@ pub struct PortForwardController { _thread: NonDetachingJoinHandle<()>, } +pub async fn add_iptables_rule(nat: bool, undo: bool, args: &[&str]) -> Result<(), Error> { + let mut cmd = Command::new("iptables"); + if nat { + cmd.arg("-t").arg("nat"); + } + if undo != !cmd.arg("-C").args(args).status().await?.success() { + let mut cmd = Command::new("iptables"); + if nat { + cmd.arg("-t").arg("nat"); + } + if undo { + cmd.arg("-D"); + } else { + cmd.arg("-A"); + } + cmd.args(args).invoke(ErrorKind::Network).await?; + } + Ok(()) +} + impl PortForwardController { pub fn new() -> Self { let (req_send, mut req_recv) = mpsc::unbounded_channel::(); let thread = NonDetachingJoinHandle::from(tokio::spawn(async move { while let Err(e) = async { + Command::new("iptables") + .arg("-P") + .arg("FORWARD") + .arg("DROP") + .invoke(ErrorKind::Network) + .await?; + add_iptables_rule( + false, + false, + &[ + "FORWARD", + "-m", + "state", + "--state", + "ESTABLISHED,RELATED", + "-j", + "ACCEPT", + ], + ) + .await?; Command::new("sysctl") .arg("-w") .arg("net.ipv4.ip_forward=1") diff --git a/core/startos/src/net/gateway.rs b/core/startos/src/net/gateway.rs index 8bb5297ac..fe90e15df 100644 --- a/core/startos/src/net/gateway.rs +++ b/core/startos/src/net/gateway.rs @@ -10,12 +10,10 @@ use std::time::Duration; use clap::Parser; use futures::future::Either; use futures::{FutureExt, Stream, StreamExt, TryStreamExt}; -use crate::util::future::NonDetachingJoinHandle; use imbl::{OrdMap, OrdSet}; use imbl_value::InternedString; use ipnet::IpNet; use itertools::Itertools; -use crate::GatewayId; use nix::net::if_::if_nametoindex; use patch_db::json_ptr::JsonPointer; use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; @@ -32,6 +30,7 @@ use zbus::zvariant::{ }; use zbus::{Connection, proxy}; +use crate::GatewayId; use crate::context::{CliContext, RpcContext}; use crate::db::model::Database; use crate::db::model::public::{IpInfo, NetworkInterfaceInfo, NetworkInterfaceType}; @@ -42,7 +41,7 @@ use crate::net::web_server::{Accept, AcceptStream, Acceptor, MetadataVisitor}; use crate::prelude::*; use crate::util::Invoke; use crate::util::collections::OrdMapIterMut; -use crate::util::future::Until; +use crate::util::future::{NonDetachingJoinHandle, Until}; use crate::util::io::open_file; use crate::util::serde::{HandlerExtSerde, display_serializable}; use crate::util::sync::{SyncMutex, Watch}; @@ -65,13 +64,15 @@ pub fn gateway_api() -> ParentHandler { for (iface, info) in res { table.add_row(row![ iface, - info.ip_info.as_ref() + info.ip_info + .as_ref() .and_then(|ip_info| ip_info.device_type) .map_or_else(|| "UNKNOWN".to_owned(), |ty| format!("{ty:?}")), info.public(), info.ip_info.as_ref().map_or_else( || "".to_owned(), - |ip_info| ip_info.subnets + |ip_info| ip_info + .subnets .iter() .map(|ipnet| match ipnet.addr() { IpAddr::V4(ip) => format!("{ip}/{}", ipnet.prefix_len()), @@ -81,8 +82,10 @@ pub fn gateway_api() -> ParentHandler { ipnet.prefix_len() ), }) - .join(", ")), - info.ip_info.as_ref() + .join(", ") + ), + info.ip_info + .as_ref() .and_then(|ip_info| ip_info.wan_ip) .map_or_else(|| "N/A".to_owned(), |ip| ip.to_string()) ]); @@ -102,26 +105,34 @@ pub fn gateway_api() -> ParentHandler { .no_display() .with_about("Indicate whether this gateway has inbound access from the WAN") .with_call_remote::(), - ).subcommand( + ) + .subcommand( "unset-public", from_fn_async(unset_public) .with_metadata("sync_db", Value::Bool(true)) .no_display() - .with_about("Allow this gateway to infer whether it has inbound access from the WAN based on its IPv4 address") + .with_about(concat!( + "Allow this gateway to infer whether it has", + " inbound access from the WAN based on its IPv4 address" + )) .with_call_remote::(), - ).subcommand("forget", + ) + .subcommand( + "forget", from_fn_async(forget_iface) .with_metadata("sync_db", Value::Bool(true)) .no_display() .with_about("Forget a disconnected gateway") - .with_call_remote::() - ).subcommand("set-name", - from_fn_async(set_name) - .with_metadata("sync_db", Value::Bool(true)) - .no_display() - .with_about("Rename a gateway") - .with_call_remote::() - ) + .with_call_remote::(), + ) + .subcommand( + "set-name", + from_fn_async(set_name) + .with_metadata("sync_db", Value::Bool(true)) + .no_display() + .with_about("Rename a gateway") + .with_call_remote::(), + ) } async fn list_interfaces( @@ -266,6 +277,9 @@ trait Ip4Config { #[zbus(property)] fn address_data(&self) -> Result, Error>; + #[zbus(property)] + fn route_data(&self) -> Result, Error>; + #[zbus(property)] fn gateway(&self) -> Result; @@ -301,6 +315,14 @@ impl TryFrom for IpNet { } } +#[derive(Clone, Debug, DeserializeDict, ZValue, ZType)] +#[zvariant(signature = "dict")] +struct RouteData { + dest: String, + prefix: u32, + table: Option, +} + #[derive(Clone, Debug, DeserializeDict, ZValue, ZType)] #[zvariant(signature = "dict")] struct NameserverData { @@ -613,6 +635,7 @@ async fn watch_ip( Ip6ConfigProxy::new(&connection, ip6_config.clone()).await?; let mut until = Until::new() .with_stream(ip4_proxy.receive_address_data_changed().await.stub()) + .with_stream(ip4_proxy.receive_route_data_changed().await.stub()) .with_stream(ip4_proxy.receive_gateway_changed().await.stub()) .with_stream( ip4_proxy.receive_nameserver_data_changed().await.stub(), @@ -680,6 +703,22 @@ async fn watch_ip( .into_iter() .map(IpNet::try_from) .try_collect()?; + let tables = ip4_proxy.route_data().await?.into_iter().filter_map(|d|d.table).collect::>(); + if !tables.is_empty() { + let rules = String::from_utf8(Command::new("ip").arg("rule").arg("list").invoke(ErrorKind::Network).await?)?; + for table in tables { + for subnet in subnets.iter().filter(|s| s.addr().is_ipv4()) { + let subnet_string = subnet.trunc().to_string(); + let rule = ["from", &subnet_string, "lookup", &table.to_string()]; + if !rules.contains(&rule.join(" ")) { + if rules.contains(&rule[..2].join(" ")) { + Command::new("ip").arg("rule").arg("del").args(&rule[..2]).invoke(ErrorKind::Network).await?; + } + Command::new("ip").arg("rule").arg("add").args(rule).invoke(ErrorKind::Network).await?; + } + } + } + } let wan_ip = if !subnets.is_empty() && !matches!( device_type, @@ -1405,12 +1444,8 @@ impl ListenerMap { &mut self, cx: &mut std::task::Context<'_>, ) -> Poll::Metadata, AcceptStream), Error>> { - for (addr, listener) in self.listeners.iter_mut() { - if let Poll::Ready((metadata, stream)) = listener.poll_accept(cx)? { - return Poll::Ready(Ok((*addr, metadata, stream))); - } - } - Poll::Pending + let (metadata, stream) = ready!(self.listeners.poll_accept(cx)?); + Poll::Ready(Ok((metadata.key, metadata.inner, stream))) } } diff --git a/core/startos/src/net/host/address.rs b/core/startos/src/net/host/address.rs index d809705fe..296b8a934 100644 --- a/core/startos/src/net/host/address.rs +++ b/core/startos/src/net/host/address.rs @@ -3,11 +3,11 @@ use std::net::Ipv4Addr; use clap::Parser; use imbl_value::InternedString; -use crate::GatewayId; use rpc_toolkit::{Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use ts_rs::TS; +use crate::GatewayId; use crate::context::{CliContext, RpcContext}; use crate::db::model::DatabaseModel; use crate::net::acme::AcmeProvider; diff --git a/core/startos/src/net/host/binding.rs b/core/startos/src/net/host/binding.rs index 805562a85..a74d351aa 100644 --- a/core/startos/src/net/host/binding.rs +++ b/core/startos/src/net/host/binding.rs @@ -4,8 +4,6 @@ use std::str::FromStr; use clap::Parser; use clap::builder::ValueParserFactory; use imbl::OrdSet; -use crate::util::FromStrParser; -use crate::{GatewayId, HostId}; use rpc_toolkit::{Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use ts_rs::TS; @@ -17,7 +15,9 @@ use crate::net::gateway::InterfaceFilter; use crate::net::host::HostApiKind; use crate::net::vhost::AlpnInfo; use crate::prelude::*; +use crate::util::FromStrParser; use crate::util::serde::{HandlerExtSerde, display_serializable}; +use crate::{GatewayId, HostId}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, TS)] #[ts(export)] diff --git a/core/startos/src/net/host/mod.rs b/core/startos/src/net/host/mod.rs index 924a97615..8f9ab15e2 100644 --- a/core/startos/src/net/host/mod.rs +++ b/core/startos/src/net/host/mod.rs @@ -5,7 +5,6 @@ use std::panic::RefUnwindSafe; use clap::Parser; use imbl_value::InternedString; use itertools::Itertools; -use crate::{HostId, PackageId}; use rpc_toolkit::{Context, Empty, HandlerExt, OrEmpty, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use ts_rs::TS; @@ -18,6 +17,7 @@ use crate::net::host::binding::{BindInfo, BindOptions, binding}; use crate::net::service_interface::HostnameInfo; use crate::net::tor::OnionAddress; use crate::prelude::*; +use crate::{HostId, PackageId}; pub mod address; pub mod binding; diff --git a/core/startos/src/net/net_controller.rs b/core/startos/src/net/net_controller.rs index 33061bb75..098726802 100644 --- a/core/startos/src/net/net_controller.rs +++ b/core/startos/src/net/net_controller.rs @@ -6,19 +6,17 @@ use color_eyre::eyre::eyre; use imbl::{OrdMap, vector}; use imbl_value::InternedString; use ipnet::IpNet; -use crate::{GatewayId, HostId, OptionExt, PackageId}; use tokio::sync::Mutex; use tokio::task::JoinHandle; use tokio_rustls::rustls::ClientConfig as TlsClientConfig; use tracing::instrument; -use crate::HOST_IP; use crate::db::model::Database; use crate::db::model::public::NetworkInterfaceType; use crate::error::ErrorCollection; use crate::hostname::Hostname; use crate::net::dns::DnsController; -use crate::net::forward::{InterfacePortForwardController, START9_BRIDGE_IFACE}; +use crate::net::forward::{InterfacePortForwardController, START9_BRIDGE_IFACE, add_iptables_rule}; use crate::net::gateway::{ AndFilter, DynInterfaceFilter, IdFilter, InterfaceFilter, NetworkInterfaceController, OrFilter, PublicFilter, SecureFilter, TypeFilter, @@ -34,6 +32,7 @@ use crate::net::vhost::{AlpnInfo, DynVHostTarget, ProxyTarget, VHostController}; use crate::prelude::*; use crate::service::effects::callbacks::ServiceCallbacks; use crate::util::serde::MaybeUtf8String; +use crate::{GatewayId, HOST_IP, HostId, OptionExt, PackageId}; pub struct NetController { pub(crate) db: TypedPatchDb, @@ -70,6 +69,22 @@ impl NetController { .de()? .0], )?); + add_iptables_rule( + false, + false, + &[ + "FORWARD", + "-i", + START9_BRIDGE_IFACE, + "-m", + "state", + "--state", + "NEW", + "-j", + "ACCEPT", + ], + ) + .await?; Ok(Self { db: db.clone(), tor, diff --git a/core/startos/src/net/service_interface.rs b/core/startos/src/net/service_interface.rs index 4c4cbf2c4..499e1a321 100644 --- a/core/startos/src/net/service_interface.rs +++ b/core/startos/src/net/service_interface.rs @@ -1,10 +1,11 @@ use std::net::{Ipv4Addr, Ipv6Addr}; use imbl_value::InternedString; -use crate::{GatewayId, HostId, ServiceInterfaceId}; use serde::{Deserialize, Serialize}; use ts_rs::TS; +use crate::{GatewayId, HostId, ServiceInterfaceId}; + #[derive(Clone, Debug, Deserialize, Serialize, TS)] #[ts(export)] #[serde(rename_all = "camelCase")] diff --git a/core/startos/src/net/socks.rs b/core/startos/src/net/socks.rs index fd4085fb3..0cd2645d7 100644 --- a/core/startos/src/net/socks.rs +++ b/core/startos/src/net/socks.rs @@ -2,7 +2,6 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::sync::Arc; use std::time::Duration; -use crate::util::future::NonDetachingJoinHandle; use socks5_impl::protocol::{Address, Reply}; use socks5_impl::server::auth::NoAuth; use socks5_impl::server::{AuthAdaptor, ClientConnection, Server}; @@ -12,6 +11,7 @@ use crate::HOST_IP; use crate::net::tor::TorController; use crate::prelude::*; use crate::util::actor::background::BackgroundJobQueue; +use crate::util::future::NonDetachingJoinHandle; pub const DEFAULT_SOCKS_LISTEN: SocketAddr = SocketAddr::V4(SocketAddrV4::new( Ipv4Addr::new(HOST_IP[0], HOST_IP[1], HOST_IP[2], HOST_IP[3]), diff --git a/core/startos/src/net/static_server.rs b/core/startos/src/net/static_server.rs index b7e50c7f8..a5ec14822 100644 --- a/core/startos/src/net/static_server.rs +++ b/core/startos/src/net/static_server.rs @@ -22,7 +22,6 @@ use http::request::Parts as RequestParts; use http::{HeaderValue, Method, StatusCode}; use imbl_value::InternedString; use include_dir::Dir; -use crate::PackageId; use new_mime_guess::MimeGuess; use openssl::hash::MessageDigest; use openssl::x509::X509; @@ -33,7 +32,6 @@ use url::Url; use crate::context::{DiagnosticContext, InitContext, InstallContext, RpcContext, SetupContext}; use crate::hostname::Hostname; -use crate::main_api; use crate::middleware::auth::{Auth, HasValidSession}; use crate::middleware::cors::Cors; use crate::middleware::db::SyncDb; @@ -49,6 +47,7 @@ use crate::sign::commitment::merkle_archive::MerkleArchiveCommitment; use crate::util::io::open_file; use crate::util::net::SyncBody; use crate::util::serde::BASE64; +use crate::{PackageId, main_api}; const NOT_FOUND: &[u8] = b"Not Found"; const METHOD_NOT_ALLOWED: &[u8] = b"Method Not Allowed"; diff --git a/core/startos/src/net/tor/arti.rs b/core/startos/src/net/tor/arti.rs index 2202d737d..71a82b41d 100644 --- a/core/startos/src/net/tor/arti.rs +++ b/core/startos/src/net/tor/arti.rs @@ -11,7 +11,6 @@ use base64::Engine; use clap::Parser; use color_eyre::eyre::eyre; use futures::{FutureExt, StreamExt}; -use crate::util::future::NonDetachingJoinHandle; use imbl_value::InternedString; use itertools::Itertools; use rpc_toolkit::{Context, Empty, HandlerExt, ParentHandler, from_fn_async}; @@ -31,7 +30,7 @@ use ts_rs::TS; use crate::context::{CliContext, RpcContext}; use crate::prelude::*; use crate::util::actor::background::BackgroundJobQueue; -use crate::util::future::Until; +use crate::util::future::{NonDetachingJoinHandle, Until}; use crate::util::io::ReadWriter; use crate::util::serde::{ BASE64, Base64, HandlerExtSerde, WithIoFormat, deserialize_from_str, display_serializable, diff --git a/core/startos/src/net/tor/ctor.rs b/core/startos/src/net/tor/ctor.rs index fb0d33f87..5ce62e137 100644 --- a/core/startos/src/net/tor/ctor.rs +++ b/core/startos/src/net/tor/ctor.rs @@ -10,7 +10,6 @@ use clap::Parser; use color_eyre::eyre::eyre; use futures::future::BoxFuture; use futures::{FutureExt, TryFutureExt, TryStreamExt}; -use crate::util::future::NonDetachingJoinHandle; use imbl::OrdMap; use imbl_value::InternedString; use lazy_static::lazy_static; @@ -31,6 +30,7 @@ use crate::logs::{LogSource, LogsParams, journalctl}; use crate::prelude::*; use crate::util::Invoke; use crate::util::collections::ordmap_retain; +use crate::util::future::NonDetachingJoinHandle; use crate::util::io::{ReadWriter, write_file_atomic}; use crate::util::serde::{ BASE64, Base64, HandlerExtSerde, WithIoFormat, deserialize_from_str, display_serializable, diff --git a/core/startos/src/net/tunnel.rs b/core/startos/src/net/tunnel.rs index d0cb5de6e..64e1ee284 100644 --- a/core/startos/src/net/tunnel.rs +++ b/core/startos/src/net/tunnel.rs @@ -1,12 +1,12 @@ use clap::Parser; use imbl_value::InternedString; -use crate::GatewayId; use patch_db::json_ptr::JsonPointer; use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use tokio::process::Command; use ts_rs::TS; +use crate::GatewayId; use crate::context::{CliContext, RpcContext}; use crate::db::model::public::{NetworkInterfaceInfo, NetworkInterfaceType}; use crate::net::host::all_hosts; diff --git a/core/startos/src/net/utils.rs b/core/startos/src/net/utils.rs index b7ce2d23b..9f3a3682c 100644 --- a/core/startos/src/net/utils.rs +++ b/core/startos/src/net/utils.rs @@ -8,11 +8,11 @@ use futures::stream::BoxStream; use futures::{StreamExt, TryStreamExt}; use imbl_value::InternedString; use ipnet::{IpNet, Ipv4Net, Ipv6Net}; -use crate::GatewayId; use nix::net::if_::if_nametoindex; use tokio::net::{TcpListener, TcpStream}; use tokio::process::Command; +use crate::GatewayId; use crate::db::model::public::{IpInfo, NetworkInterfaceType}; use crate::prelude::*; use crate::util::Invoke; diff --git a/core/startos/src/net/vhost.rs b/core/startos/src/net/vhost.rs index 3f53f1011..3f4cbd181 100644 --- a/core/startos/src/net/vhost.rs +++ b/core/startos/src/net/vhost.rs @@ -9,9 +9,7 @@ use async_acme::acme::ACME_TLS_ALPN_NAME; use color_eyre::eyre::eyre; use futures::FutureExt; use futures::future::BoxFuture; -use crate::util::future::NonDetachingJoinHandle; use imbl_value::{InOMap, InternedString}; -use crate::ResultExt; use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn}; use serde::{Deserialize, Serialize}; use tokio::net::TcpStream; @@ -24,6 +22,7 @@ use tracing::instrument; use ts_rs::TS; use visit_rs::Visit; +use crate::ResultExt; use crate::context::{CliContext, RpcContext}; use crate::db::model::Database; use crate::db::model::public::AcmeSettings; @@ -42,7 +41,7 @@ use crate::net::tls::{ use crate::net::web_server::{Accept, AcceptStream, ExtractVisitor, TcpMetadata, extract}; use crate::prelude::*; use crate::util::collections::EqSet; -use crate::util::future::WeakFuture; +use crate::util::future::{NonDetachingJoinHandle, WeakFuture}; use crate::util::serde::{HandlerExtSerde, MaybeUtf8String, display_serializable}; use crate::util::sync::{SyncMutex, Watch}; diff --git a/core/startos/src/net/web_server.rs b/core/startos/src/net/web_server.rs index 47ce920b5..25e1df79a 100644 --- a/core/startos/src/net/web_server.rs +++ b/core/startos/src/net/web_server.rs @@ -12,7 +12,6 @@ use std::time::Duration; use axum::Router; use futures::future::Either; use futures::{FutureExt, TryFutureExt}; -use crate::util::future::NonDetachingJoinHandle; use http::Extensions; use hyper_util::rt::{TokioIo, TokioTimer}; use tokio::net::TcpListener; @@ -22,6 +21,7 @@ use visit_rs::{Visit, VisitFields, Visitor}; use crate::net::static_server::{UiContext, ui_router}; use crate::prelude::*; use crate::util::actor::background::BackgroundJobQueue; +use crate::util::future::NonDetachingJoinHandle; use crate::util::io::ReadWriter; use crate::util::sync::{SyncRwLock, Watch}; @@ -483,7 +483,7 @@ where .http2() .timer(TokioTimer::new()) .enable_connect_protocol() - .keep_alive_interval(Duration::from_secs(60)) + .keep_alive_interval(Duration::from_secs(25)) .keep_alive_timeout(Duration::from_secs(300)); let (queue, mut runner) = BackgroundJobQueue::new(); queue_cell.replace(Some(queue.clone())); diff --git a/core/startos/src/notifications.rs b/core/startos/src/notifications.rs index 4a5a9db38..4aac251f5 100644 --- a/core/startos/src/notifications.rs +++ b/core/startos/src/notifications.rs @@ -7,17 +7,17 @@ use clap::Parser; use clap::builder::ValueParserFactory; use color_eyre::eyre::eyre; use imbl_value::InternedString; -use crate::util::FromStrParser; -use crate::PackageId; use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use tracing::instrument; use ts_rs::TS; +use crate::PackageId; use crate::backup::BackupReport; use crate::context::{CliContext, RpcContext}; use crate::db::model::DatabaseModel; use crate::prelude::*; +use crate::util::FromStrParser; use crate::util::serde::{HandlerExtSerde, const_true}; // #[command(subcommands(list, delete, delete_before, create))] diff --git a/core/startos/src/os_install/mod.rs b/core/startos/src/os_install/mod.rs index 0449b55d8..6ff9292b6 100644 --- a/core/startos/src/os_install/mod.rs +++ b/core/startos/src/os_install/mod.rs @@ -2,13 +2,11 @@ use std::path::{Path, PathBuf}; use clap::Parser; use color_eyre::eyre::eyre; -use crate::Error; use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use tokio::process::Command; use ts_rs::TS; -use crate::ARCH; use crate::context::config::ServerConfig; use crate::context::{CliContext, InstallContext}; use crate::disk::OsPartitionInfo; @@ -25,6 +23,7 @@ use crate::s9pk::merkle_archive::source::multi_cursor_file::MultiCursorFile; use crate::util::Invoke; use crate::util::io::{TmpDir, delete_file, open_file}; use crate::util::serde::IoFormat; +use crate::{ARCH, Error}; mod gpt; mod mbr; diff --git a/core/startos/src/registry/asset.rs b/core/startos/src/registry/asset.rs index e8856c9ae..aa26ded04 100644 --- a/core/startos/src/registry/asset.rs +++ b/core/startos/src/registry/asset.rs @@ -3,7 +3,6 @@ use std::path::Path; use std::sync::Arc; use chrono::{DateTime, Utc}; -use crate::util::future::NonDetachingJoinHandle; use reqwest::Client; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWrite; @@ -20,6 +19,7 @@ use crate::sign::commitment::merkle_archive::MerkleArchiveCommitment; use crate::sign::commitment::{Commitment, Digestable}; use crate::sign::{AnySignature, AnyVerifyingKey}; use crate::upload::UploadingFile; +use crate::util::future::NonDetachingJoinHandle; #[derive(Debug, Deserialize, Serialize, TS)] #[serde(rename_all = "camelCase")] diff --git a/core/startos/src/registry/info.rs b/core/startos/src/registry/info.rs index 4afedbfb5..c80057a13 100644 --- a/core/startos/src/registry/info.rs +++ b/core/startos/src/registry/info.rs @@ -4,7 +4,6 @@ use std::path::PathBuf; use clap::Parser; use imbl_value::InternedString; use itertools::Itertools; -use crate::util::DataUrl; use rpc_toolkit::{Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use ts_rs::TS; @@ -13,6 +12,7 @@ use crate::context::CliContext; use crate::prelude::*; use crate::registry::context::RegistryContext; use crate::registry::package::index::Category; +use crate::util::DataUrl; use crate::util::serde::{HandlerExtSerde, WithIoFormat}; pub fn info_api() -> ParentHandler> { diff --git a/core/startos/src/registry/mod.rs b/core/startos/src/registry/mod.rs index 8bea37624..74b35e7e2 100644 --- a/core/startos/src/registry/mod.rs +++ b/core/startos/src/registry/mod.rs @@ -3,7 +3,6 @@ use std::collections::{BTreeMap, BTreeSet}; use axum::Router; use futures::future::ready; use imbl_value::InternedString; -use crate::util::DataUrl; use rpc_toolkit::{Context, HandlerExt, ParentHandler, Server, from_fn_async}; use serde::{Deserialize, Serialize}; use ts_rs::TS; @@ -19,6 +18,7 @@ use crate::registry::os::index::OsIndex; use crate::registry::package::index::PackageIndex; use crate::registry::signer::SignerInfo; use crate::rpc_continuations::Guid; +use crate::util::DataUrl; use crate::util::serde::HandlerExtSerde; pub mod admin; diff --git a/core/startos/src/registry/package/add.rs b/core/startos/src/registry/package/add.rs index 271a6c7cc..421b5d73f 100644 --- a/core/startos/src/registry/package/add.rs +++ b/core/startos/src/registry/package/add.rs @@ -4,13 +4,12 @@ use std::sync::Arc; use clap::Parser; use imbl_value::InternedString; use itertools::Itertools; -use crate::util::VersionString; -use crate::PackageId; use rpc_toolkit::HandlerArgs; use serde::{Deserialize, Serialize}; use ts_rs::TS; use url::Url; +use crate::PackageId; use crate::context::CliContext; use crate::prelude::*; use crate::progress::{FullProgressTracker, ProgressTrackerWriter, ProgressUnits}; @@ -23,6 +22,7 @@ use crate::s9pk::v2::SIG_CONTEXT; use crate::sign::commitment::merkle_archive::MerkleArchiveCommitment; use crate::sign::ed25519::Ed25519; use crate::sign::{AnySignature, AnyVerifyingKey, SignatureScheme}; +use crate::util::VersionString; use crate::util::io::TrackingIO; #[derive(Debug, Deserialize, Serialize, TS)] diff --git a/core/startos/src/registry/package/category.rs b/core/startos/src/registry/package/category.rs index e4899bef0..92d9e7f99 100644 --- a/core/startos/src/registry/package/category.rs +++ b/core/startos/src/registry/package/category.rs @@ -2,11 +2,11 @@ use std::collections::BTreeMap; use clap::Parser; use imbl_value::InternedString; -use crate::PackageId; use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use ts_rs::TS; +use crate::PackageId; use crate::context::CliContext; use crate::prelude::*; use crate::registry::context::RegistryContext; diff --git a/core/startos/src/registry/package/get.rs b/core/startos/src/registry/package/get.rs index b395343d2..775795429 100644 --- a/core/startos/src/registry/package/get.rs +++ b/core/startos/src/registry/package/get.rs @@ -5,10 +5,10 @@ use clap::{Parser, ValueEnum}; use exver::{ExtendedVersion, VersionRange}; use imbl_value::{InternedString, json}; use itertools::Itertools; -use crate::PackageId; use serde::{Deserialize, Serialize}; use ts_rs::TS; +use crate::PackageId; use crate::context::CliContext; use crate::prelude::*; use crate::progress::{FullProgressTracker, ProgressUnits}; diff --git a/core/startos/src/registry/package/index.rs b/core/startos/src/registry/package/index.rs index 1877da597..5213ac184 100644 --- a/core/startos/src/registry/package/index.rs +++ b/core/startos/src/registry/package/index.rs @@ -3,12 +3,11 @@ use std::collections::{BTreeMap, BTreeSet}; use chrono::Utc; use exver::{Version, VersionRange}; use imbl_value::InternedString; -use crate::util::{DataUrl, VersionString}; -use crate::PackageId; use serde::{Deserialize, Serialize}; use ts_rs::TS; use url::Url; +use crate::PackageId; use crate::prelude::*; use crate::registry::asset::RegistryAsset; use crate::registry::context::RegistryContext; @@ -20,6 +19,7 @@ use crate::s9pk::manifest::{Alerts, Description, HardwareRequirements}; use crate::s9pk::merkle_archive::source::FileSource; use crate::sign::commitment::merkle_archive::MerkleArchiveCommitment; use crate::sign::{AnySignature, AnyVerifyingKey}; +use crate::util::{DataUrl, VersionString}; #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[serde(rename_all = "camelCase")] diff --git a/core/startos/src/registry/package/signer.rs b/core/startos/src/registry/package/signer.rs index 69d37b092..d577d1e7a 100644 --- a/core/startos/src/registry/package/signer.rs +++ b/core/startos/src/registry/package/signer.rs @@ -2,11 +2,11 @@ use std::collections::BTreeMap; use clap::Parser; use exver::VersionRange; -use crate::PackageId; use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use ts_rs::TS; +use crate::PackageId; use crate::context::CliContext; use crate::prelude::*; use crate::registry::admin::display_package_signers; diff --git a/core/startos/src/registry/signer.rs b/core/startos/src/registry/signer.rs index 8f2dddd64..3a4fc2d0d 100644 --- a/core/startos/src/registry/signer.rs +++ b/core/startos/src/registry/signer.rs @@ -3,7 +3,6 @@ use std::str::FromStr; use clap::builder::ValueParserFactory; use itertools::Itertools; -use crate::util::FromStrParser; use serde::{Deserialize, Serialize}; use ts_rs::TS; use url::Url; @@ -11,6 +10,7 @@ use url::Url; use crate::prelude::*; use crate::sign::commitment::Digestable; use crate::sign::{AnySignature, AnyVerifyingKey, SignatureScheme}; +use crate::util::FromStrParser; #[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[serde(rename_all = "camelCase")] diff --git a/core/startos/src/rpc_continuations.rs b/core/startos/src/rpc_continuations.rs index c894391b7..aa3f24236 100644 --- a/core/startos/src/rpc_continuations.rs +++ b/core/startos/src/rpc_continuations.rs @@ -12,14 +12,13 @@ use clap::builder::ValueParserFactory; use futures::future::BoxFuture; use futures::{Future, FutureExt}; use imbl_value::InternedString; -use crate::util::FromStrParser; use tokio::sync::{Mutex as AsyncMutex, broadcast}; use ts_rs::TS; #[allow(unused_imports)] use crate::prelude::*; use crate::util::future::TimedResource; -use crate::util::new_guid; +use crate::util::{FromStrParser, new_guid}; #[derive( Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize, TS, diff --git a/core/startos/src/s9pk/rpc.rs b/core/startos/src/s9pk/rpc.rs index a6af628e7..ec7dd3696 100644 --- a/core/startos/src/s9pk/rpc.rs +++ b/core/startos/src/s9pk/rpc.rs @@ -2,11 +2,11 @@ use std::path::PathBuf; use std::sync::Arc; use clap::Parser; -use crate::ImageId; use rpc_toolkit::{Empty, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use ts_rs::TS; +use crate::ImageId; use crate::context::CliContext; use crate::prelude::*; use crate::s9pk::manifest::Manifest; diff --git a/core/startos/src/s9pk/v1/manifest.rs b/core/startos/src/s9pk/v1/manifest.rs index 0ce5e67a6..993231138 100644 --- a/core/startos/src/s9pk/v1/manifest.rs +++ b/core/startos/src/s9pk/v1/manifest.rs @@ -4,15 +4,15 @@ use std::path::{Path, PathBuf}; use exver::{Version, VersionRange}; use imbl_value::InternedString; use indexmap::IndexMap; -pub use crate::PackageId; -use crate::{ActionId, HealthCheckId, ImageId, VolumeId}; use serde::{Deserialize, Serialize}; use url::Url; +pub use crate::PackageId; use crate::prelude::*; use crate::s9pk::git_hash::GitHash; use crate::s9pk::manifest::{Alerts, Description}; use crate::util::serde::{Duration, IoFormat, Regex}; +use crate::{ActionId, HealthCheckId, ImageId, VolumeId}; #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] diff --git a/core/startos/src/s9pk/v1/reader.rs b/core/startos/src/s9pk/v1/reader.rs index 7becf0475..8ebe55da6 100644 --- a/core/startos/src/s9pk/v1/reader.rs +++ b/core/startos/src/s9pk/v1/reader.rs @@ -9,7 +9,6 @@ use std::task::{Context, Poll}; use color_eyre::eyre::eyre; use digest::Output; use ed25519_dalek::VerifyingKey; -use crate::{ImageId, PackageId}; use sha2::{Digest, Sha512}; use tokio::fs::File; use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, BufReader, ReadBuf}; @@ -21,6 +20,7 @@ use crate::prelude::*; use crate::s9pk::v1::docker::DockerReader; use crate::util::VersionString; use crate::util::io::open_file; +use crate::{ImageId, PackageId}; #[pin_project::pin_project] #[derive(Debug)] diff --git a/core/startos/src/s9pk/v2/manifest.rs b/core/startos/src/s9pk/v2/manifest.rs index 0e5d3badc..23e518422 100644 --- a/core/startos/src/s9pk/v2/manifest.rs +++ b/core/startos/src/s9pk/v2/manifest.rs @@ -4,22 +4,21 @@ use std::path::Path; use color_eyre::eyre::eyre; use exver::{Version, VersionRange}; use imbl_value::InternedString; -pub use crate::PackageId; -use crate::util::mime; -use crate::{ImageId, VolumeId}; use serde::{Deserialize, Serialize}; use ts_rs::TS; use url::Url; +pub use crate::PackageId; use crate::dependencies::Dependencies; use crate::prelude::*; use crate::s9pk::git_hash::GitHash; use crate::s9pk::merkle_archive::directory_contents::DirectoryContents; use crate::s9pk::merkle_archive::expected::{Expected, Filter}; use crate::s9pk::v2::pack::ImageConfig; -use crate::util::VersionString; use crate::util::serde::Regex; +use crate::util::{VersionString, mime}; use crate::version::{Current, VersionT}; +use crate::{ImageId, VolumeId}; fn current_version() -> Version { Current::default().semver() diff --git a/core/startos/src/s9pk/v2/mod.rs b/core/startos/src/s9pk/v2/mod.rs index 3453cc21d..fcaa70531 100644 --- a/core/startos/src/s9pk/v2/mod.rs +++ b/core/startos/src/s9pk/v2/mod.rs @@ -3,10 +3,9 @@ use std::path::Path; use std::sync::Arc; use imbl_value::InternedString; -use crate::util::{DataUrl, mime}; -use crate::PackageId; use tokio::fs::File; +use crate::PackageId; use crate::dependencies::DependencyMetadata; use crate::prelude::*; use crate::s9pk::manifest::Manifest; @@ -20,6 +19,7 @@ use crate::s9pk::v2::pack::{ImageSource, PackSource}; use crate::sign::commitment::merkle_archive::MerkleArchiveCommitment; use crate::util::io::{TmpDir, open_file}; use crate::util::serde::IoFormat; +use crate::util::{DataUrl, mime}; const MAGIC_AND_VERSION: &[u8] = &[0x3b, 0x3b, 0x02]; diff --git a/core/startos/src/service/action.rs b/core/startos/src/service/action.rs index 713229ec5..0e75e1c3c 100644 --- a/core/startos/src/service/action.rs +++ b/core/startos/src/service/action.rs @@ -2,8 +2,6 @@ use std::collections::BTreeMap; use std::time::Duration; use imbl_value::json; -use crate::service::ProcedureName; -use crate::{ActionId, PackageId, ReplayId}; use crate::action::{ActionInput, ActionResult}; use crate::db::model::package::{ @@ -11,10 +9,11 @@ use crate::db::model::package::{ }; use crate::prelude::*; use crate::rpc_continuations::Guid; -use crate::service::{Service, ServiceActor}; +use crate::service::{ProcedureName, Service, ServiceActor}; use crate::util::actor::background::BackgroundJobQueue; use crate::util::actor::{ConflictBuilder, Handler}; use crate::util::serde::is_partial_of; +use crate::{ActionId, PackageId, ReplayId}; pub(super) struct GetActionInput { id: ActionId, diff --git a/core/startos/src/service/effects/action.rs b/core/startos/src/service/effects/action.rs index 3e195a92a..ff98dfd13 100644 --- a/core/startos/src/service/effects/action.rs +++ b/core/startos/src/service/effects/action.rs @@ -1,6 +1,5 @@ use std::collections::BTreeSet; -use crate::{ActionId, PackageId, ReplayId}; use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use crate::action::{ActionInput, ActionResult, display_action_result}; @@ -11,6 +10,7 @@ use crate::rpc_continuations::Guid; use crate::service::cli::ContainerCliContext; use crate::service::effects::prelude::*; use crate::util::serde::HandlerExtSerde; +use crate::{ActionId, PackageId, ReplayId}; pub fn action_api() -> ParentHandler { ParentHandler::new() diff --git a/core/startos/src/service/effects/callbacks.rs b/core/startos/src/service/effects/callbacks.rs index 2a94b2627..59d61f39c 100644 --- a/core/startos/src/service/effects/callbacks.rs +++ b/core/startos/src/service/effects/callbacks.rs @@ -5,10 +5,8 @@ use std::time::{Duration, SystemTime}; use clap::Parser; use futures::future::join_all; -use crate::util::future::NonDetachingJoinHandle; use imbl::{Vector, vector}; use imbl_value::InternedString; -use crate::{HostId, PackageId, ServiceInterfaceId}; use serde::{Deserialize, Serialize}; use tracing::warn; use ts_rs::TS; @@ -20,6 +18,8 @@ use crate::service::effects::net::ssl::Algorithm; use crate::service::rpc::{CallbackHandle, CallbackId}; use crate::service::{Service, ServiceActorSeed}; use crate::util::collections::EqMap; +use crate::util::future::NonDetachingJoinHandle; +use crate::{HostId, PackageId, ServiceInterfaceId}; #[derive(Default)] pub struct ServiceCallbacks(Mutex); diff --git a/core/startos/src/service/effects/control.rs b/core/startos/src/service/effects/control.rs index 5dd0e794a..292a0bb9f 100644 --- a/core/startos/src/service/effects/control.rs +++ b/core/startos/src/service/effects/control.rs @@ -2,13 +2,13 @@ use std::str::FromStr; use chrono::Utc; use clap::builder::ValueParserFactory; -use crate::util::FromStrParser; -use crate::PackageId; +use crate::PackageId; use crate::service::RebuildParams; use crate::service::effects::prelude::*; use crate::service::rpc::CallbackId; use crate::status::{DesiredStatus, StatusInfo}; +use crate::util::FromStrParser; pub async fn rebuild(context: EffectContext) -> Result<(), Error> { let seed = context.deref()?.seed.clone(); diff --git a/core/startos/src/service/effects/dependency.rs b/core/startos/src/service/effects/dependency.rs index 876e8dc47..419e4f2be 100644 --- a/core/startos/src/service/effects/dependency.rs +++ b/core/startos/src/service/effects/dependency.rs @@ -5,10 +5,7 @@ use std::str::FromStr; use clap::builder::ValueParserFactory; use exver::VersionRange; use imbl_value::InternedString; -use crate::util::{FromStrParser, VersionString}; -use crate::{HealthCheckId, PackageId, ReplayId, VolumeId}; -use crate::DATA_DIR; use crate::db::model::package::{ CurrentDependencies, CurrentDependencyInfo, CurrentDependencyKind, ManifestPreference, TaskEntry, @@ -19,7 +16,9 @@ use crate::disk::mount::filesystem::{FileSystem, MountType}; use crate::disk::mount::util::{is_mountpoint, unmount}; use crate::service::effects::prelude::*; use crate::status::health_check::NamedHealthCheckResult; +use crate::util::{FromStrParser, VersionString}; use crate::volume::data_dir; +use crate::{DATA_DIR, HealthCheckId, PackageId, ReplayId, VolumeId}; #[derive(Debug, Clone, Serialize, Deserialize, TS)] #[ts(export)] diff --git a/core/startos/src/service/effects/health.rs b/core/startos/src/service/effects/health.rs index 548c02dbd..aa1d8a3d3 100644 --- a/core/startos/src/service/effects/health.rs +++ b/core/startos/src/service/effects/health.rs @@ -1,5 +1,4 @@ use crate::HealthCheckId; - use crate::service::effects::prelude::*; use crate::status::health_check::NamedHealthCheckResult; diff --git a/core/startos/src/service/effects/net/bind.rs b/core/startos/src/service/effects/net/bind.rs index 252423d94..f25b22bd4 100644 --- a/core/startos/src/service/effects/net/bind.rs +++ b/core/startos/src/service/effects/net/bind.rs @@ -1,7 +1,6 @@ -use crate::{HostId, PackageId}; - use crate::net::host::binding::{BindId, BindOptions, NetInfo}; use crate::service::effects::prelude::*; +use crate::{HostId, PackageId}; #[derive(Debug, Clone, Serialize, Deserialize, TS)] #[serde(rename_all = "camelCase")] diff --git a/core/startos/src/service/effects/net/host.rs b/core/startos/src/service/effects/net/host.rs index e042b58bd..ebd1b80c8 100644 --- a/core/startos/src/service/effects/net/host.rs +++ b/core/startos/src/service/effects/net/host.rs @@ -1,9 +1,8 @@ -use crate::{HostId, PackageId}; - use crate::net::host::Host; use crate::service::effects::callbacks::CallbackHandler; use crate::service::effects::prelude::*; use crate::service::rpc::CallbackId; +use crate::{HostId, PackageId}; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)] #[serde(rename_all = "camelCase")] diff --git a/core/startos/src/service/effects/net/info.rs b/core/startos/src/service/effects/net/info.rs index 74ed7c8da..f14ee72dc 100644 --- a/core/startos/src/service/effects/net/info.rs +++ b/core/startos/src/service/effects/net/info.rs @@ -1,7 +1,6 @@ use std::net::Ipv4Addr; use crate::PackageId; - use crate::service::effects::callbacks::CallbackHandler; use crate::service::effects::prelude::*; use crate::service::rpc::CallbackId; diff --git a/core/startos/src/service/effects/net/interface.rs b/core/startos/src/service/effects/net/interface.rs index 94b416846..ff0452976 100644 --- a/core/startos/src/service/effects/net/interface.rs +++ b/core/startos/src/service/effects/net/interface.rs @@ -1,12 +1,12 @@ use std::collections::BTreeMap; use imbl::vector; -use crate::{PackageId, ServiceInterfaceId}; use crate::net::service_interface::{AddressInfo, ServiceInterface, ServiceInterfaceType}; use crate::service::effects::callbacks::CallbackHandler; use crate::service::effects::prelude::*; use crate::service::rpc::CallbackId; +use crate::{PackageId, ServiceInterfaceId}; #[derive(Debug, Clone, Serialize, Deserialize, TS)] #[ts(export)] diff --git a/core/startos/src/service/mod.rs b/core/startos/src/service/mod.rs index fe34c820e..95e53f83c 100644 --- a/core/startos/src/service/mod.rs +++ b/core/startos/src/service/mod.rs @@ -13,10 +13,8 @@ use clap::Parser; use futures::future::BoxFuture; use futures::stream::FusedStream; use futures::{FutureExt, SinkExt, StreamExt, TryStreamExt}; -use crate::util::future::NonDetachingJoinHandle; use imbl_value::{InternedString, json}; use itertools::Itertools; -use crate::{ActionId, HostId, ImageId, PackageId}; use nix::sys::signal::Signal; use persistent_container::{PersistentContainer, Subcontainer}; use rpc_toolkit::HandlerArgs; @@ -47,12 +45,13 @@ use crate::service::service_map::InstallProgressHandles; use crate::service::uninstall::cleanup; use crate::util::Never; use crate::util::actor::concurrent::ConcurrentActor; +use crate::util::future::NonDetachingJoinHandle; use crate::util::io::{AsyncReadStream, AtomicFile, TermSize, delete_file}; use crate::util::net::WebSocketExt; use crate::util::serde::Pem; use crate::util::sync::SyncMutex; use crate::volume::data_dir; -use crate::{CAP_1_KiB, DATA_DIR}; +use crate::{ActionId, CAP_1_KiB, DATA_DIR, HostId, ImageId, PackageId}; pub mod action; pub mod cli; diff --git a/core/startos/src/service/persistent_container.rs b/core/startos/src/service/persistent_container.rs index 5a1194945..e2faf0a8c 100644 --- a/core/startos/src/service/persistent_container.rs +++ b/core/startos/src/service/persistent_container.rs @@ -5,11 +5,8 @@ use std::time::Duration; use futures::Future; use futures::future::ready; -use crate::util::future::NonDetachingJoinHandle; use imbl::{Vector, vector}; use imbl_value::InternedString; -use crate::service::ProcedureName; -use crate::{ImageId, VolumeId}; use rpc_toolkit::{Empty, Server, ShutdownHandle}; use serde::de::DeserializeOwned; use tokio::process::Command; @@ -34,12 +31,13 @@ use crate::service::effects::handler; use crate::service::rpc::{ CallbackHandle, CallbackId, CallbackParams, ExitParams, InitKind, InitParams, }; -use crate::service::{Service, rpc}; +use crate::service::{ProcedureName, Service, rpc}; use crate::util::Invoke; +use crate::util::future::NonDetachingJoinHandle; use crate::util::io::create_file; use crate::util::rpc_client::UnixRpcClient; use crate::volume::data_dir; -use crate::{ARCH, DATA_DIR, PACKAGE_DATA}; +use crate::{ARCH, DATA_DIR, ImageId, PACKAGE_DATA, VolumeId}; const RPC_CONNECT_TIMEOUT: Duration = Duration::from_secs(30); diff --git a/core/startos/src/service/rpc.rs b/core/startos/src/service/rpc.rs index 777213443..b5c8ed01c 100644 --- a/core/startos/src/service/rpc.rs +++ b/core/startos/src/service/rpc.rs @@ -7,16 +7,15 @@ use clap::builder::ValueParserFactory; use exver::{ExtendedVersion, VersionRange}; use imbl::Vector; use imbl_value::{InternedString, Value}; -use crate::service::ProcedureName; -use crate::util::FromStrParser; use rpc_toolkit::Empty; use rpc_toolkit::yajrc::RpcMethod; use ts_rs::TS; use crate::prelude::*; use crate::rpc_continuations::Guid; +use crate::service::ProcedureName; use crate::service::persistent_container::PersistentContainer; -use crate::util::Never; +use crate::util::{FromStrParser, Never}; #[derive(Clone, serde::Deserialize, serde::Serialize, TS)] #[serde(rename_all = "kebab-case")] diff --git a/core/startos/src/service/service_actor.rs b/core/startos/src/service/service_actor.rs index 755f3ea42..724be7f16 100644 --- a/core/startos/src/service/service_actor.rs +++ b/core/startos/src/service/service_actor.rs @@ -132,9 +132,7 @@ async fn service_actor_loop<'a>( .filter(|task| task.kind == TransitionKind::BackingUp); *transition = task.or_else(|| Some(seed.backup())); } - _ => { - *transition = None; - } + _ => (), }; Ok(()) } diff --git a/core/startos/src/service/service_map.rs b/core/startos/src/service/service_map.rs index 53ff58748..fe8192d26 100644 --- a/core/startos/src/service/service_map.rs +++ b/core/startos/src/service/service_map.rs @@ -8,9 +8,7 @@ use exver::VersionRange; use futures::future::{BoxFuture, Fuse}; use futures::stream::FuturesUnordered; use futures::{Future, FutureExt, StreamExt, TryFutureExt}; -use crate::util::future::NonDetachingJoinHandle; use imbl::OrdMap; -use crate::error::ErrorData; use tokio::sync::{OwnedRwLockReadGuard, OwnedRwLockWriteGuard, RwLock, oneshot}; use tracing::instrument; use url::Url; @@ -21,6 +19,7 @@ use crate::db::model::package::{ InstallingInfo, InstallingState, PackageDataEntry, PackageState, UpdatingState, }; use crate::disk::mount::guard::GenericMountGuard; +use crate::error::ErrorData; use crate::install::PKG_ARCHIVE_DIR; use crate::notifications::{NotificationLevel, notify}; use crate::prelude::*; @@ -32,6 +31,7 @@ use crate::service::rpc::{ExitParams, InitKind}; use crate::service::{LoadDisposition, Service, ServiceRef}; use crate::sign::commitment::merkle_archive::MerkleArchiveCommitment; use crate::status::{DesiredStatus, StatusInfo}; +use crate::util::future::NonDetachingJoinHandle; use crate::util::serde::{Base32, Pem}; use crate::util::sync::SyncMutex; @@ -115,7 +115,18 @@ impl ServiceMap { shutdown_err = service.shutdown(None).await; } match Service::load(ctx, id, disposition).await { - Ok(s) => *service = s.into(), + Ok(s) => { + ctx.db + .mutate(|db| { + if let Some(pde) = db.as_public_mut().as_package_data_mut().as_idx_mut(id) { + pde.as_status_info_mut().as_error_mut().ser(&None)?; + } + Ok(()) + }) + .await + .result?; + *service = s.into(); + } Err(e) => { tracing::error!("Error loading service: {e}"); tracing::debug!("{e:?}"); diff --git a/core/startos/src/service/transition/backup.rs b/core/startos/src/service/transition/backup.rs index 1ed404c30..30787311e 100644 --- a/core/startos/src/service/transition/backup.rs +++ b/core/startos/src/service/transition/backup.rs @@ -2,7 +2,6 @@ use std::path::PathBuf; use futures::future::BoxFuture; use futures::{FutureExt, TryFutureExt}; -use crate::service::ProcedureName; use rpc_toolkit::yajrc::RpcError; use crate::disk::mount::filesystem::ReadWrite; @@ -11,7 +10,7 @@ use crate::rpc_continuations::Guid; use crate::service::action::GetActionInput; use crate::service::start_stop::StartStop; use crate::service::transition::{Transition, TransitionKind}; -use crate::service::{ServiceActor, ServiceActorSeed}; +use crate::service::{ProcedureName, ServiceActor, ServiceActorSeed}; use crate::status::DesiredStatus; use crate::util::actor::background::BackgroundJobQueue; use crate::util::actor::{ConflictBuilder, Handler}; diff --git a/core/startos/src/service/uninstall.rs b/core/startos/src/service/uninstall.rs index 4a93dff19..c245d0687 100644 --- a/core/startos/src/service/uninstall.rs +++ b/core/startos/src/service/uninstall.rs @@ -1,12 +1,10 @@ use std::path::Path; -use crate::PackageId; - use crate::context::RpcContext; use crate::db::model::package::{InstalledState, InstallingInfo, InstallingState, PackageState}; use crate::prelude::*; use crate::volume::PKG_VOLUME_DIR; -use crate::{DATA_DIR, PACKAGE_DATA}; +use crate::{DATA_DIR, PACKAGE_DATA, PackageId}; pub async fn cleanup(ctx: &RpcContext, id: &PackageId, soft: bool) -> Result<(), Error> { Ok( diff --git a/core/startos/src/sign/mod.rs b/core/startos/src/sign/mod.rs index a685a0e62..f0ed1e786 100644 --- a/core/startos/src/sign/mod.rs +++ b/core/startos/src/sign/mod.rs @@ -4,7 +4,6 @@ use std::str::FromStr; use ::ed25519::pkcs8::BitStringRef; use clap::builder::ValueParserFactory; use der::referenced::OwnedToRef; -use crate::util::FromStrParser; use pkcs8::der::AnyRef; use pkcs8::{PrivateKeyInfo, SubjectPublicKeyInfo}; use serde::{Deserialize, Serialize}; @@ -14,6 +13,7 @@ use ts_rs::TS; use crate::prelude::*; use crate::sign::commitment::Digestable; use crate::sign::ed25519::Ed25519; +use crate::util::FromStrParser; use crate::util::serde::{deserialize_from_str, serialize_display}; pub mod commitment; diff --git a/core/startos/src/ssh.rs b/core/startos/src/ssh.rs index c1bef01b7..cec4b0daf 100644 --- a/core/startos/src/ssh.rs +++ b/core/startos/src/ssh.rs @@ -4,7 +4,6 @@ use std::path::Path; use clap::Parser; use clap::builder::ValueParserFactory; use imbl_value::InternedString; -use crate::util::FromStrParser; use rpc_toolkit::{Context, Empty, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use tokio::fs::OpenOptions; @@ -15,9 +14,9 @@ use ts_rs::TS; use crate::context::{CliContext, RpcContext}; use crate::hostname::Hostname; use crate::prelude::*; -use crate::util::Invoke; use crate::util::io::create_file; use crate::util::serde::{HandlerExtSerde, Pem, WithIoFormat, display_serializable}; +use crate::util::{FromStrParser, Invoke}; pub const SSH_DIR: &str = "/home/start9/.ssh"; diff --git a/core/startos/src/status/health_check.rs b/core/startos/src/status/health_check.rs index 8807d7a6c..d028987dd 100644 --- a/core/startos/src/status/health_check.rs +++ b/core/startos/src/status/health_check.rs @@ -1,11 +1,12 @@ use std::str::FromStr; use clap::builder::ValueParserFactory; -use crate::util::FromStrParser; -pub use crate::HealthCheckId; use serde::{Deserialize, Serialize}; use ts_rs::TS; +pub use crate::HealthCheckId; +use crate::util::FromStrParser; + #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, TS)] #[serde(rename_all = "camelCase")] pub struct NamedHealthCheckResult { diff --git a/core/startos/src/status/mod.rs b/core/startos/src/status/mod.rs index 9bdb987d0..05efab83f 100644 --- a/core/startos/src/status/mod.rs +++ b/core/startos/src/status/mod.rs @@ -1,11 +1,11 @@ use std::collections::BTreeMap; use chrono::{DateTime, Utc}; -use crate::error::ErrorData; -use crate::HealthCheckId; use serde::{Deserialize, Serialize}; use ts_rs::TS; +use crate::HealthCheckId; +use crate::error::ErrorData; use crate::prelude::*; use crate::service::start_stop::StartStop; use crate::status::health_check::NamedHealthCheckResult; diff --git a/core/startos/src/tunnel/api.rs b/core/startos/src/tunnel/api.rs index 0e32f5452..ac6e1cdf3 100644 --- a/core/startos/src/tunnel/api.rs +++ b/core/startos/src/tunnel/api.rs @@ -7,9 +7,11 @@ use rpc_toolkit::{Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_f use serde::{Deserialize, Serialize}; use crate::context::CliContext; +use crate::db::model::public::NetworkInterfaceType; +use crate::net::forward::add_iptables_rule; use crate::prelude::*; use crate::tunnel::context::TunnelContext; -use crate::tunnel::wg::{WgConfig, WgSubnetClients, WgSubnetConfig}; +use crate::tunnel::wg::{WIREGUARD_INTERFACE_NAME, WgConfig, WgSubnetClients, WgSubnetConfig}; use crate::util::serde::{HandlerExtSerde, display_serializable}; pub fn tunnel_api() -> ParentHandler { @@ -167,7 +169,37 @@ pub async fn add_subnet( }) .await .result?; - server.sync().await + server.sync().await?; + + for iface in ctx.net_iface.peek(|i| { + i.iter() + .filter(|(_, info)| { + info.ip_info.as_ref().map_or(false, |i| { + i.device_type != Some(NetworkInterfaceType::Loopback) + }) + }) + .map(|(name, _)| name) + .filter(|id| id.as_str() != WIREGUARD_INTERFACE_NAME) + .cloned() + .collect::>() + }) { + add_iptables_rule( + true, + false, + &[ + "POSTROUTING", + "-s", + &subnet.trunc().to_string(), + "-o", + iface.as_str(), + "-j", + "MASQUERADE", + ], + ) + .await?; + } + + Ok(()) } pub async fn remove_subnet( @@ -184,7 +216,37 @@ pub async fn remove_subnet( .await .result?; server.sync().await?; - ctx.gc_forwards(&keep).await + ctx.gc_forwards(&keep).await?; + + for iface in ctx.net_iface.peek(|i| { + i.iter() + .filter(|(_, info)| { + info.ip_info.as_ref().map_or(false, |i| { + i.device_type != Some(NetworkInterfaceType::Loopback) + }) + }) + .map(|(name, _)| name) + .filter(|id| id.as_str() != WIREGUARD_INTERFACE_NAME) + .cloned() + .collect::>() + }) { + add_iptables_rule( + true, + true, + &[ + "POSTROUTING", + "-s", + &subnet.trunc().to_string(), + "-o", + iface.as_str(), + "-j", + "MASQUERADE", + ], + ) + .await?; + } + + Ok(()) } #[derive(Deserialize, Serialize, Parser)] diff --git a/core/startos/src/tunnel/context.rs b/core/startos/src/tunnel/context.rs index 0e426f481..5b4332f10 100644 --- a/core/startos/src/tunnel/context.rs +++ b/core/startos/src/tunnel/context.rs @@ -11,23 +11,22 @@ use imbl::OrdMap; use imbl_value::InternedString; use include_dir::Dir; use ipnet::Ipv4Net; -use crate::GatewayId; use patch_db::PatchDb; use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::{CallRemote, Context, Empty, ParentHandler}; use serde::{Deserialize, Serialize}; -use tokio::process::Command; use tokio::sync::broadcast::Sender; use tracing::instrument; use url::Url; +use crate::GatewayId; use crate::auth::Sessions; use crate::context::config::ContextConfig; use crate::context::{CliContext, RpcContext}; use crate::db::model::public::{NetworkInterfaceInfo, NetworkInterfaceType}; use crate::middleware::auth::{Auth, AuthContext}; use crate::middleware::cors::Cors; -use crate::net::forward::PortForwardController; +use crate::net::forward::{PortForwardController, add_iptables_rule}; use crate::net::static_server::{EMPTY_DIR, UiContext}; use crate::prelude::*; use crate::rpc_continuations::{OpenAuthedContinuations, RpcContinuations}; @@ -35,7 +34,6 @@ use crate::tunnel::TUNNEL_DEFAULT_LISTEN; use crate::tunnel::api::tunnel_api; use crate::tunnel::db::TunnelDatabase; use crate::tunnel::wg::{WIREGUARD_INTERFACE_NAME, WgSubnetConfig}; -use crate::util::Invoke; use crate::util::collections::OrdMapIterMut; use crate::util::io::read_file_to_string; use crate::util::sync::{SyncMutex, Watch}; @@ -134,12 +132,25 @@ impl TunnelContext { .result?; let net_iface = Watch::new(net_iface); let forward = PortForwardController::new(); + add_iptables_rule( + false, + false, + &[ + "FORWARD", + "-i", + WIREGUARD_INTERFACE_NAME, + "-m", + "state", + "--state", + "NEW", + "-j", + "ACCEPT", + ], + ) + .await?; - Command::new("sysctl") - .arg("-w") - .arg("net.ipv4.ip_forward=1") - .invoke(ErrorKind::Network) - .await?; + let peek = db.peek().await; + peek.as_wg().de()?.sync().await?; for iface in net_iface.peek(|i| { i.iter() @@ -153,37 +164,24 @@ impl TunnelContext { .cloned() .collect::>() }) { - if Command::new("iptables") - .arg("-t") - .arg("nat") - .arg("-C") - .arg("POSTROUTING") - .arg("-o") - .arg(iface.as_str()) - .arg("-j") - .arg("MASQUERADE") - .invoke(ErrorKind::Network) - .await - .is_err() - { - tracing::info!("Adding masquerade rule for interface {}", iface); - Command::new("iptables") - .arg("-t") - .arg("nat") - .arg("-A") - .arg("POSTROUTING") - .arg("-o") - .arg(iface.as_str()) - .arg("-j") - .arg("MASQUERADE") - .invoke(ErrorKind::Network) - .await - .log_err(); + for subnet in peek.as_wg().as_subnets().keys()? { + add_iptables_rule( + true, + false, + &[ + "POSTROUTING", + "-s", + &subnet.trunc().to_string(), + "-o", + iface.as_str(), + "-j", + "MASQUERADE", + ], + ) + .await?; } } - let peek = db.peek().await; - peek.as_wg().de()?.sync().await?; let mut active_forwards = BTreeMap::new(); for (from, to) in peek.as_port_forwards().de()?.0 { active_forwards.insert(from, forward.add_forward(from, to).await?); diff --git a/core/startos/src/tunnel/db.rs b/core/startos/src/tunnel/db.rs index 97353230b..863943543 100644 --- a/core/startos/src/tunnel/db.rs +++ b/core/startos/src/tunnel/db.rs @@ -8,7 +8,6 @@ use clap::Parser; use imbl::{HashMap, OrdMap}; use imbl_value::InternedString; use itertools::Itertools; -use crate::GatewayId; use patch_db::Dump; use patch_db::json_ptr::{JsonPointer, ROOT}; use rpc_toolkit::yajrc::RpcError; @@ -17,6 +16,7 @@ use serde::{Deserialize, Serialize}; use tracing::instrument; use ts_rs::TS; +use crate::GatewayId; use crate::auth::Sessions; use crate::context::CliContext; use crate::db::model::public::NetworkInterfaceInfo; diff --git a/core/startos/src/tunnel/wg.rs b/core/startos/src/tunnel/wg.rs index d9c9704ae..8696ba293 100644 --- a/core/startos/src/tunnel/wg.rs +++ b/core/startos/src/tunnel/wg.rs @@ -228,10 +228,7 @@ impl std::fmt::Display for ClientConfig { name = self.client_config.name, privkey = self.client_config.key.to_padded_string(), psk = self.client_config.psk.to_padded_string(), - addr = Ipv4Net::new_assert( - self.client_addr, - self.subnet.prefix_len() - ), + addr = Ipv4Net::new_assert(self.client_addr, self.subnet.prefix_len()), subnet = self.subnet.trunc(), server_pubkey = self.server_pubkey.to_padded_string(), server_addr = self.server_addr, diff --git a/core/startos/src/update/mod.rs b/core/startos/src/update/mod.rs index 0f0923036..44d67e3c9 100644 --- a/core/startos/src/update/mod.rs +++ b/core/startos/src/update/mod.rs @@ -6,7 +6,6 @@ use clap::{ArgAction, Parser}; use color_eyre::eyre::{Result, eyre}; use exver::{Version, VersionRange}; use futures::TryStreamExt; -use crate::util::future::NonDetachingJoinHandle; use imbl_value::json; use itertools::Itertools; use patch_db::json_ptr::JsonPointer; @@ -36,6 +35,7 @@ use crate::sound::{ CIRCLE_OF_5THS_SHORT, UPDATE_FAILED_1, UPDATE_FAILED_2, UPDATE_FAILED_3, UPDATE_FAILED_4, }; use crate::util::Invoke; +use crate::util::future::NonDetachingJoinHandle; use crate::util::io::AtomicFile; use crate::util::net::WebSocketExt; diff --git a/core/startos/src/util/actor/concurrent.rs b/core/startos/src/util/actor/concurrent.rs index 111106726..cce7b691b 100644 --- a/core/startos/src/util/actor/concurrent.rs +++ b/core/startos/src/util/actor/concurrent.rs @@ -4,13 +4,13 @@ use std::time::Duration; use futures::future::{BoxFuture, ready}; use futures::{Future, FutureExt, TryFutureExt}; -use crate::util::future::NonDetachingJoinHandle; use tokio::sync::{mpsc, oneshot}; use crate::prelude::*; use crate::rpc_continuations::Guid; use crate::util::actor::background::{BackgroundJobQueue, BackgroundJobRunner}; use crate::util::actor::{Actor, ConflictFn, Handler, PendingMessageStrategy, Request}; +use crate::util::future::NonDetachingJoinHandle; #[pin_project::pin_project] struct ConcurrentRunner { diff --git a/core/startos/src/util/actor/simple.rs b/core/startos/src/util/actor/simple.rs index e92e8e149..663a1a3bd 100644 --- a/core/startos/src/util/actor/simple.rs +++ b/core/startos/src/util/actor/simple.rs @@ -2,7 +2,6 @@ use std::time::Duration; use futures::future::ready; use futures::{Future, FutureExt, TryFutureExt}; -use crate::util::future::NonDetachingJoinHandle; use tokio::sync::oneshot::error::TryRecvError; use tokio::sync::{mpsc, oneshot}; @@ -10,6 +9,7 @@ use crate::prelude::*; use crate::rpc_continuations::Guid; use crate::util::actor::background::BackgroundJobQueue; use crate::util::actor::{Actor, Handler, PendingMessageStrategy, Request}; +use crate::util::future::NonDetachingJoinHandle; pub struct SimpleActor { shutdown: oneshot::Sender<()>, diff --git a/core/startos/src/util/data_url.rs b/core/startos/src/util/data_url.rs index 008ae5025..20a0060aa 100644 --- a/core/startos/src/util/data_url.rs +++ b/core/startos/src/util/data_url.rs @@ -4,11 +4,11 @@ use std::str::FromStr; use base64::Engine; use color_eyre::eyre::eyre; +use imbl_value::InternedString; use reqwest::header::CONTENT_TYPE; use serde::{Deserialize, Serialize}; use tokio::io::{AsyncRead, AsyncReadExt}; use ts_rs::TS; -use imbl_value::InternedString; use crate::util::mime::{mime, unmime}; use crate::{Error, ErrorKind, ResultExt}; diff --git a/core/startos/src/util/io.rs b/core/startos/src/util/io.rs index 10ffd4476..fa6ea9414 100644 --- a/core/startos/src/util/io.rs +++ b/core/startos/src/util/io.rs @@ -16,7 +16,6 @@ use clap::builder::ValueParserFactory; use futures::future::{BoxFuture, Fuse}; use futures::{FutureExt, Stream, TryStreamExt}; use inotify::{EventMask, EventStream, Inotify, WatchMask}; -use crate::util::FromStrParser; use nix::unistd::{Gid, Uid}; use serde::{Deserialize, Serialize}; use tokio::fs::{File, OpenOptions}; @@ -30,6 +29,7 @@ use tokio::time::{Instant, Sleep}; use ts_rs::TS; use crate::prelude::*; +use crate::util::FromStrParser; use crate::util::future::NonDetachingJoinHandle; use crate::util::sync::SyncMutex; diff --git a/core/startos/src/util/lshw.rs b/core/startos/src/util/lshw.rs index 425619a11..98c1a09ab 100644 --- a/core/startos/src/util/lshw.rs +++ b/core/startos/src/util/lshw.rs @@ -1,9 +1,9 @@ -use crate::{Error, ResultExt}; use serde::{Deserialize, Serialize}; use tokio::process::Command; use ts_rs::TS; use crate::util::Invoke; +use crate::{Error, ResultExt}; const KNOWN_CLASSES: &[&str] = &["processor", "display"]; diff --git a/core/startos/src/util/mod.rs b/core/startos/src/util/mod.rs index df8cefb63..3a351bd87 100644 --- a/core/startos/src/util/mod.rs +++ b/core/startos/src/util/mod.rs @@ -35,16 +35,16 @@ use crate::{Error, ErrorKind, ResultExt as _}; pub mod actor; pub mod clap; pub mod collections; -pub mod data_url; -pub mod mime; pub mod cpupower; pub mod crypto; +pub mod data_url; pub mod future; pub mod http_reader; pub mod io; pub mod iter; pub mod logger; pub mod lshw; +pub mod mime; pub mod net; pub mod rpc; pub mod rpc_client; diff --git a/core/startos/src/util/rpc_client.rs b/core/startos/src/util/rpc_client.rs index e80681bde..3dd6e6b21 100644 --- a/core/startos/src/util/rpc_client.rs +++ b/core/startos/src/util/rpc_client.rs @@ -6,7 +6,6 @@ use std::sync::{Arc, Weak}; use futures::future::BoxFuture; use futures::{FutureExt, TryFutureExt}; use lazy_async_pool::Pool; -use crate::{Error, ErrorKind, ResultExt}; use rpc_toolkit::yajrc::{self, Id, RpcError, RpcMethod, RpcRequest, RpcResponse}; use serde::{Deserialize, Serialize}; use serde_json::{Value, json}; @@ -17,6 +16,7 @@ use tokio::sync::{Mutex, OnceCell, oneshot}; use crate::util::future::NonDetachingJoinHandle; use crate::util::io::TmpDir; +use crate::{Error, ErrorKind, ResultExt}; type DynWrite = Box; type ResponseMap = BTreeMap>>; diff --git a/core/startos/src/util/rsync.rs b/core/startos/src/util/rsync.rs index fcaf11b04..1e91f77dc 100644 --- a/core/startos/src/util/rsync.rs +++ b/core/startos/src/util/rsync.rs @@ -2,7 +2,6 @@ use std::path::Path; use color_eyre::eyre::eyre; use futures::StreamExt; -use crate::{Error, ErrorKind}; use tokio::io::{AsyncBufReadExt, AsyncReadExt, BufReader}; use tokio::process::{Child, Command}; use tokio::sync::watch; @@ -11,6 +10,7 @@ use tokio_stream::wrappers::WatchStream; use crate::util::future::NonDetachingJoinHandle; use crate::util::io::ByteReplacementReader; use crate::util::serde::const_true; +use crate::{Error, ErrorKind}; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[serde(rename_all = "camelCase")] diff --git a/core/startos/src/util/serde.rs b/core/startos/src/util/serde.rs index 82229d95b..286041822 100644 --- a/core/startos/src/util/serde.rs +++ b/core/startos/src/util/serde.rs @@ -8,7 +8,6 @@ use clap::builder::ValueParserFactory; use clap::{ArgMatches, CommandFactory, FromArgMatches}; use color_eyre::eyre::eyre; use imbl_value::imbl::OrdMap; -use crate::util::FromStrParser; use openssl::pkey::{PKey, Private}; use openssl::x509::X509; use rpc_toolkit::{ @@ -21,7 +20,7 @@ use ts_rs::TS; use super::IntoDoubleEndedIterator; use crate::prelude::*; -use crate::util::Apply; +use crate::util::{Apply, FromStrParser}; pub fn const_true() -> bool { true diff --git a/core/startos/src/util/sync.rs b/core/startos/src/util/sync.rs index 3f97e913f..0f63e735a 100644 --- a/core/startos/src/util/sync.rs +++ b/core/startos/src/util/sync.rs @@ -51,7 +51,7 @@ where }) { panic!("lock {id} is already locked on this thread"); } - let tracer: helpers::NonDetachingJoinHandle<()> = { + let tracer: crate::util::future::NonDetachingJoinHandle<()> = { let bt = std::backtrace::Backtrace::force_capture(); tokio::spawn(async move { use std::time::Duration; diff --git a/core/startos/src/version/v0_3_6_alpha_0.rs b/core/startos/src/version/v0_3_6_alpha_0.rs index 9ddf7c067..3840721bb 100644 --- a/core/startos/src/version/v0_3_6_alpha_0.rs +++ b/core/startos/src/version/v0_3_6_alpha_0.rs @@ -7,7 +7,6 @@ use const_format::formatcp; use ed25519_dalek::SigningKey; use exver::{PreReleaseSegment, VersionRange}; use imbl_value::{InternedString, json}; -use crate::{HostId, Id, PackageId, ReplayId}; use openssl::pkey::PKey; use openssl::x509::X509; use sqlx::postgres::PgConnectOptions; @@ -34,7 +33,7 @@ use crate::ssh::{SshKeys, SshPubKey}; use crate::util::Invoke; use crate::util::crypto::ed25519_expand_key; use crate::util::serde::Pem; -use crate::{DATA_DIR, PACKAGE_DATA}; +use crate::{DATA_DIR, HostId, Id, PACKAGE_DATA, PackageId, ReplayId}; lazy_static::lazy_static! { static ref V0_3_6_alpha_0: exver::Version = exver::Version::new( diff --git a/core/startos/src/version/v0_3_6_alpha_10.rs b/core/startos/src/version/v0_3_6_alpha_10.rs index a2a2fbf28..08543d9e1 100644 --- a/core/startos/src/version/v0_3_6_alpha_10.rs +++ b/core/startos/src/version/v0_3_6_alpha_10.rs @@ -2,11 +2,11 @@ use std::collections::{BTreeMap, BTreeSet}; use exver::{PreReleaseSegment, VersionRange}; use imbl_value::InternedString; -use crate::GatewayId; use serde::{Deserialize, Serialize}; use super::v0_3_5::V0_3_0_COMPAT; use super::{VersionT, v0_3_6_alpha_9}; +use crate::GatewayId; use crate::net::host::address::PublicDomainConfig; use crate::net::tor::OnionAddress; use crate::prelude::*; diff --git a/core/startos/src/version/v0_4_0_alpha_12.rs b/core/startos/src/version/v0_4_0_alpha_12.rs index 5ff6cd4d2..fa7e5a189 100644 --- a/core/startos/src/version/v0_4_0_alpha_12.rs +++ b/core/startos/src/version/v0_4_0_alpha_12.rs @@ -4,7 +4,7 @@ use exver::{PreReleaseSegment, VersionRange}; use imbl_value::InternedString; use super::v0_3_5::V0_3_0_COMPAT; -use super::{v0_4_0_alpha_11, VersionT}; +use super::{VersionT, v0_4_0_alpha_11}; use crate::net::tor::TorSecretKey; use crate::prelude::*; diff --git a/core/startos/src/version/v0_4_0_alpha_9.rs b/core/startos/src/version/v0_4_0_alpha_9.rs index 4f047bd74..ce7bf399c 100644 --- a/core/startos/src/version/v0_4_0_alpha_9.rs +++ b/core/startos/src/version/v0_4_0_alpha_9.rs @@ -4,16 +4,15 @@ use std::sync::Arc; use exver::{PreReleaseSegment, VersionRange}; use imbl_value::{InOMap, InternedString}; -use crate::PackageId; use super::v0_3_5::V0_3_0_COMPAT; use super::{VersionT, v0_4_0_alpha_8}; -use crate::DATA_DIR; use crate::context::RpcContext; use crate::install::PKG_ARCHIVE_DIR; use crate::prelude::*; use crate::util::io::write_file_atomic; use crate::volume::PKG_VOLUME_DIR; +use crate::{DATA_DIR, PackageId}; lazy_static::lazy_static! { static ref V0_4_0_alpha_9: exver::Version = exver::Version::new( diff --git a/core/startos/src/volume.rs b/core/startos/src/volume.rs index be171fd65..2755fd809 100644 --- a/core/startos/src/volume.rs +++ b/core/startos/src/volume.rs @@ -2,7 +2,6 @@ use std::path::{Path, PathBuf}; use crate::PackageId; pub use crate::VolumeId; - use crate::prelude::*; use crate::util::VersionString; diff --git a/core/startos/start-registryd.service b/core/startos/start-registryd.service index 4103808ac..e8e6390ba 100644 --- a/core/startos/start-registryd.service +++ b/core/startos/start-registryd.service @@ -3,7 +3,7 @@ Description=StartOS Registry [Service] Type=simple -Environment=RUST_LOG=startos=debug,patch_db=warn,models=debug +Environment=RUST_LOG=startos=debug,patch_db=warn ExecStart=/usr/bin/start-registryd Restart=always RestartSec=3 diff --git a/core/startos/start-tunneld.service b/core/startos/start-tunneld.service index 7ed3ed17a..b0d0a2043 100644 --- a/core/startos/start-tunneld.service +++ b/core/startos/start-tunneld.service @@ -3,7 +3,7 @@ Description=StartTunnel [Service] Type=simple -Environment=RUST_LOG=startos=debug,patch_db=warn,models=debug +Environment=RUST_LOG=startos=debug,patch_db=warn ExecStart=/usr/bin/start-tunneld Restart=always RestartSec=3 diff --git a/core/startos/startd.service b/core/startos/startd.service index 4a8f81810..6ce17697e 100644 --- a/core/startos/startd.service +++ b/core/startos/startd.service @@ -3,7 +3,7 @@ Description=StartOS Daemon [Service] Type=simple -Environment=RUST_LOG=startos=debug,patch_db=warn,models=debug +Environment=RUST_LOG=startos=debug,patch_db=warn ExecStart=/usr/bin/startd Restart=always RestartSec=3