mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
ST port labels and move logout to settings (#3134)
* chore: update packages (#3132) * chore: update packages * start tunnel messaging * chore: standalone * pbpaste instead --------- Co-authored-by: Matt Hill <mattnine@protonmail.com> * port labels and move logout to settings * enable-disable forwards * Fix docs URLs in start-tunnel installer output (#3135) --------- Co-authored-by: Alex Inkin <alexander@inkin.ru> Co-authored-by: gStart9 <106188942+gStart9@users.noreply.github.com>
This commit is contained in:
@@ -11,6 +11,7 @@ use crate::db::model::public::NetworkInterfaceType;
|
||||
use crate::net::forward::add_iptables_rule;
|
||||
use crate::prelude::*;
|
||||
use crate::tunnel::context::TunnelContext;
|
||||
use crate::tunnel::db::PortForwardEntry;
|
||||
use crate::tunnel::wg::{WIREGUARD_INTERFACE_NAME, WgConfig, WgSubnetClients, WgSubnetConfig};
|
||||
use crate::util::serde::{HandlerExtSerde, display_serializable};
|
||||
|
||||
@@ -51,6 +52,22 @@ pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
|
||||
.no_display()
|
||||
.with_about("about.remove-port-forward")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"update-label",
|
||||
from_fn_async(update_forward_label)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("about.update-port-forward-label")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"set-enabled",
|
||||
from_fn_async(set_forward_enabled)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("about.enable-or-disable-port-forward")
|
||||
.with_call_remote::<CliContext>(),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -453,11 +470,17 @@ pub async fn show_config(
|
||||
pub struct AddPortForwardParams {
|
||||
source: SocketAddrV4,
|
||||
target: SocketAddrV4,
|
||||
#[arg(long)]
|
||||
label: String,
|
||||
}
|
||||
|
||||
pub async fn add_forward(
|
||||
ctx: TunnelContext,
|
||||
AddPortForwardParams { source, target }: AddPortForwardParams,
|
||||
AddPortForwardParams {
|
||||
source,
|
||||
target,
|
||||
label,
|
||||
}: AddPortForwardParams,
|
||||
) -> Result<(), Error> {
|
||||
let prefix = ctx
|
||||
.net_iface
|
||||
@@ -482,10 +505,12 @@ pub async fn add_forward(
|
||||
m.insert(source, rc);
|
||||
});
|
||||
|
||||
let entry = PortForwardEntry { target, label, enabled: true };
|
||||
|
||||
ctx.db
|
||||
.mutate(|db| {
|
||||
db.as_port_forwards_mut()
|
||||
.insert(&source, &target)
|
||||
.insert(&source, &entry)
|
||||
.and_then(|replaced| {
|
||||
if replaced.is_some() {
|
||||
Err(Error::new(
|
||||
@@ -523,3 +548,92 @@ pub async fn remove_forward(
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Parser)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UpdatePortForwardLabelParams {
|
||||
source: SocketAddrV4,
|
||||
label: String,
|
||||
}
|
||||
|
||||
pub async fn update_forward_label(
|
||||
ctx: TunnelContext,
|
||||
UpdatePortForwardLabelParams { source, label }: UpdatePortForwardLabelParams,
|
||||
) -> Result<(), Error> {
|
||||
ctx.db
|
||||
.mutate(|db| {
|
||||
db.as_port_forwards_mut().mutate(|pf| {
|
||||
let entry = pf.0.get_mut(&source).ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("Port forward from {source} not found"),
|
||||
ErrorKind::NotFound,
|
||||
)
|
||||
})?;
|
||||
entry.label = label.clone();
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
.await
|
||||
.result
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Parser)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SetPortForwardEnabledParams {
|
||||
source: SocketAddrV4,
|
||||
enabled: bool,
|
||||
}
|
||||
|
||||
pub async fn set_forward_enabled(
|
||||
ctx: TunnelContext,
|
||||
SetPortForwardEnabledParams { source, enabled }: SetPortForwardEnabledParams,
|
||||
) -> Result<(), Error> {
|
||||
let target = ctx
|
||||
.db
|
||||
.mutate(|db| {
|
||||
db.as_port_forwards_mut().mutate(|pf| {
|
||||
let entry = pf.0.get_mut(&source).ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("Port forward from {source} not found"),
|
||||
ErrorKind::NotFound,
|
||||
)
|
||||
})?;
|
||||
entry.enabled = enabled;
|
||||
Ok(entry.target)
|
||||
})
|
||||
})
|
||||
.await
|
||||
.result?;
|
||||
|
||||
if enabled {
|
||||
let prefix = ctx
|
||||
.net_iface
|
||||
.peek(|i| {
|
||||
i.iter()
|
||||
.find_map(|(_, i)| {
|
||||
i.ip_info.as_ref().and_then(|i| {
|
||||
i.subnets
|
||||
.iter()
|
||||
.find(|s| s.contains(&IpAddr::from(*target.ip())))
|
||||
})
|
||||
})
|
||||
.cloned()
|
||||
})
|
||||
.map(|s| s.prefix_len())
|
||||
.unwrap_or(32);
|
||||
let rc = ctx
|
||||
.forward
|
||||
.add_forward(source, target, prefix, None)
|
||||
.await?;
|
||||
ctx.active_forwards.mutate(|m| {
|
||||
m.insert(source, rc);
|
||||
});
|
||||
} else {
|
||||
if let Some(rc) = ctx.active_forwards.mutate(|m| m.remove(&source)) {
|
||||
drop(rc);
|
||||
ctx.forward.gc().await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -184,7 +184,11 @@ impl TunnelContext {
|
||||
}
|
||||
|
||||
let mut active_forwards = BTreeMap::new();
|
||||
for (from, to) in peek.as_port_forwards().de()?.0 {
|
||||
for (from, entry) in peek.as_port_forwards().de()?.0 {
|
||||
if !entry.enabled {
|
||||
continue;
|
||||
}
|
||||
let to = entry.target;
|
||||
let prefix = net_iface
|
||||
.peek(|i| {
|
||||
i.iter()
|
||||
|
||||
@@ -53,7 +53,7 @@ impl Model<TunnelDatabase> {
|
||||
}
|
||||
self.as_port_forwards_mut().mutate(|pf| {
|
||||
Ok(pf.0.retain(|k, v| {
|
||||
if keep_targets.contains(v.ip()) {
|
||||
if keep_targets.contains(v.target.ip()) {
|
||||
keep_sources.insert(*k);
|
||||
true
|
||||
} else {
|
||||
@@ -70,11 +70,25 @@ fn export_bindings_tunnel_db() {
|
||||
TunnelDatabase::export_all_to("bindings/tunnel").unwrap();
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PortForwardEntry {
|
||||
pub target: SocketAddrV4,
|
||||
#[serde(default)]
|
||||
pub label: String,
|
||||
#[serde(default = "default_true")]
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
fn default_true() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
|
||||
pub struct PortForwards(pub BTreeMap<SocketAddrV4, SocketAddrV4>);
|
||||
pub struct PortForwards(pub BTreeMap<SocketAddrV4, PortForwardEntry>);
|
||||
impl Map for PortForwards {
|
||||
type Key = SocketAddrV4;
|
||||
type Value = SocketAddrV4;
|
||||
type Value = PortForwardEntry;
|
||||
fn key_str(key: &Self::Key) -> Result<impl AsRef<str>, Error> {
|
||||
Self::key_string(key)
|
||||
}
|
||||
|
||||
@@ -524,26 +524,26 @@ pub async fn init_web(ctx: CliContext) -> Result<(), Error> {
|
||||
"To access your Web URL securely, trust your Root CA (displayed above) on your client device(s):\n",
|
||||
" - MacOS\n",
|
||||
" 1. Open the Terminal app\n",
|
||||
" 2. Paste the following command (**DO NOT** click Return): pbcopy < ~/Desktop/ca.crt\n",
|
||||
" 2. Type or copy/paste the following command (**DO NOT** click Enter/Return yet): pbpaste > ~/Desktop/tunnel-ca.crt\n",
|
||||
" 3. Copy your Root CA (including -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----)\n",
|
||||
" 4. Back in Terminal, click Return. ca.crt is saved to your Desktop\n",
|
||||
" 5. Complete by trusting your Root CA: https://docs.start9.com/device-guides/mac/ca.html\n",
|
||||
" 4. Back in Terminal, click Enter/Return. tunnel-ca.crt is saved to your Desktop\n",
|
||||
" 5. Complete by trusting your Root CA: https://docs.start9.com/start-os/0.4.0.x/user-manual/trust-ca.html?platform=Mac\n",
|
||||
" - Linux\n",
|
||||
" 1. Open gedit, nano, or any editor\n",
|
||||
" 2. Copy/paste your Root CA (including -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----)\n",
|
||||
" 3. Name the file ca.crt and save as plaintext\n",
|
||||
" 4. Complete by trusting your Root CA: https://docs.start9.com/device-guides/linux/ca.html\n",
|
||||
" 3. Name the file tunnel-ca.crt and save as plaintext\n",
|
||||
" 4. Complete by trusting your Root CA: https://docs.start9.com/start-os/0.4.0.x/user-manual/trust-ca.html?platform=Debian+%252F+Ubuntu\n",
|
||||
" - Windows\n",
|
||||
" 1. Open the Notepad app\n",
|
||||
" 2. Copy/paste your Root CA (including -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----)\n",
|
||||
" 3. Name the file ca.crt and save as plaintext\n",
|
||||
" 4. Complete by trusting your Root CA: https://docs.start9.com/device-guides/windows/ca.html\n",
|
||||
" 3. Name the file tunnel-ca.crt and save as plaintext\n",
|
||||
" 4. Complete by trusting your Root CA: https://docs.start9.com/start-os/0.4.0.x/user-manual/trust-ca.html?platform=Windows\n",
|
||||
" - Android/Graphene\n",
|
||||
" 1. Send the ca.crt file (created above) to yourself\n",
|
||||
" 2. Complete by trusting your Root CA: https://docs.start9.com/device-guides/android/ca.html\n",
|
||||
" 1. Send the tunnel-ca.crt file (created above) to yourself\n",
|
||||
" 2. Complete by trusting your Root CA: https://docs.start9.com/start-os/0.4.0.x/user-manual/trust-ca.html?platform=Android+%252F+Graphene\n",
|
||||
" - iOS\n",
|
||||
" 1. Send the ca.crt file (created above) to yourself\n",
|
||||
" 2. Complete by trusting your Root CA: https://docs.start9.com/device-guides/ios/ca.html\n",
|
||||
" 1. Send the tunnel-ca.crt file (created above) to yourself\n",
|
||||
" 2. Complete by trusting your Root CA: https://docs.start9.com/start-os/0.4.0.x/user-manual/trust-ca.html?platform=iOS\n",
|
||||
));
|
||||
|
||||
return Ok(());
|
||||
|
||||
Reference in New Issue
Block a user