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:
Matt Hill
2026-03-12 12:02:38 -06:00
committed by GitHub
parent 3024db2654
commit d1444b1175
79 changed files with 2313 additions and 1868 deletions

View File

@@ -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(())
}