mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-27 02:41:53 +00:00
feat: cascade address enable/disable to related bindings on same gateway
This commit is contained in:
@@ -14,6 +14,7 @@ use crate::hostname::ServerHostname;
|
||||
use crate::net::acme::AcmeProvider;
|
||||
use crate::net::gateway::{CheckDnsParams, CheckPortParams, CheckPortRes, check_dns, check_port};
|
||||
use crate::net::host::{HostApiKind, all_hosts};
|
||||
use crate::net::service_interface::HostnameMetadata;
|
||||
use crate::prelude::*;
|
||||
use crate::util::serde::{HandlerExtSerde, display_serializable};
|
||||
|
||||
@@ -246,8 +247,50 @@ pub async fn add_public_domain<Kind: HostApiKind>(
|
||||
.and_then(|a| a.port)
|
||||
.ok_or_else(|| Error::new(eyre!("no public address found for {fqdn} on port {internal_port}"), ErrorKind::NotFound))?;
|
||||
|
||||
// Disable the domain on all other bindings
|
||||
// On the target binding, enable the WAN IPv4 and all
|
||||
// public domains on the same gateway+port (no SNI without SSL).
|
||||
host.as_bindings_mut().mutate(|b| {
|
||||
if let Some(bind) = b.get_mut(&internal_port) {
|
||||
let non_ssl_port = bind.addresses.available.iter().find_map(|a| {
|
||||
if a.ssl || !a.public || a.hostname != fqdn {
|
||||
return None;
|
||||
}
|
||||
if let HostnameMetadata::PublicDomain { gateway: gw } = &a.metadata {
|
||||
if *gw == gateway {
|
||||
return a.port;
|
||||
}
|
||||
}
|
||||
None
|
||||
});
|
||||
if let Some(dp) = non_ssl_port {
|
||||
for a in &bind.addresses.available {
|
||||
if a.ssl || !a.public {
|
||||
continue;
|
||||
}
|
||||
if let HostnameMetadata::Ipv4 { gateway: gw } = &a.metadata {
|
||||
if *gw == gateway {
|
||||
if let Some(sa) = a.to_socket_addr() {
|
||||
if sa.port() == dp {
|
||||
bind.addresses.enabled.insert(sa);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for a in &bind.addresses.available {
|
||||
if a.ssl {
|
||||
continue;
|
||||
}
|
||||
if let HostnameMetadata::PublicDomain { gateway: gw } = &a.metadata {
|
||||
if *gw == gateway && a.port == Some(dp) {
|
||||
bind.addresses.disabled.remove(&(a.hostname.clone(), dp));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disable the domain on all other bindings
|
||||
for (&port, bind) in b.iter_mut() {
|
||||
if port == internal_port {
|
||||
continue;
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::context::{CliContext, RpcContext};
|
||||
use crate::db::prelude::Map;
|
||||
use crate::net::forward::AvailablePorts;
|
||||
use crate::net::host::HostApiKind;
|
||||
use crate::net::service_interface::HostnameInfo;
|
||||
use crate::net::service_interface::{HostnameInfo, HostnameMetadata};
|
||||
use crate::net::vhost::AlpnInfo;
|
||||
use crate::prelude::*;
|
||||
use crate::util::FromStrParser;
|
||||
@@ -344,6 +344,41 @@ pub async fn set_address_enabled<Kind: HostApiKind>(
|
||||
} else {
|
||||
bind.addresses.enabled.remove(&sa);
|
||||
}
|
||||
// Non-SSL Ipv4: cascade to PublicDomains on same gateway
|
||||
if !address.ssl {
|
||||
if let HostnameMetadata::Ipv4 { gateway } =
|
||||
&address.metadata
|
||||
{
|
||||
let port = sa.port();
|
||||
for a in &bind.addresses.available {
|
||||
if a.ssl {
|
||||
continue;
|
||||
}
|
||||
if let HostnameMetadata::PublicDomain {
|
||||
gateway: gw,
|
||||
} = &a.metadata
|
||||
{
|
||||
if gw == gateway
|
||||
&& a.port.unwrap_or(80) == port
|
||||
{
|
||||
let k = (
|
||||
a.hostname.clone(),
|
||||
a.port.unwrap_or(80),
|
||||
);
|
||||
if enabled {
|
||||
bind.addresses
|
||||
.disabled
|
||||
.remove(&k);
|
||||
} else {
|
||||
bind.addresses
|
||||
.disabled
|
||||
.insert(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Domains and private IPs: toggle via (host, port) in `disabled` set
|
||||
let port = address.port.unwrap_or(if address.ssl { 443 } else { 80 });
|
||||
@@ -353,6 +388,61 @@ pub async fn set_address_enabled<Kind: HostApiKind>(
|
||||
} else {
|
||||
bind.addresses.disabled.insert(key);
|
||||
}
|
||||
// Non-SSL PublicDomain: cascade to Ipv4 + other PublicDomains on same gateway
|
||||
if !address.ssl {
|
||||
if let HostnameMetadata::PublicDomain { gateway } =
|
||||
&address.metadata
|
||||
{
|
||||
for a in &bind.addresses.available {
|
||||
if a.ssl {
|
||||
continue;
|
||||
}
|
||||
match &a.metadata {
|
||||
HostnameMetadata::Ipv4 { gateway: gw }
|
||||
if a.public
|
||||
&& gw == gateway =>
|
||||
{
|
||||
if let Some(sa) =
|
||||
a.to_socket_addr()
|
||||
{
|
||||
if sa.port() == port {
|
||||
if enabled {
|
||||
bind.addresses
|
||||
.enabled
|
||||
.insert(sa);
|
||||
} else {
|
||||
bind.addresses
|
||||
.enabled
|
||||
.remove(&sa);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HostnameMetadata::PublicDomain {
|
||||
gateway: gw,
|
||||
} if gw == gateway => {
|
||||
let dp = a.port.unwrap_or(80);
|
||||
if dp == port {
|
||||
let k = (
|
||||
a.hostname.clone(),
|
||||
dp,
|
||||
);
|
||||
if enabled {
|
||||
bind.addresses
|
||||
.disabled
|
||||
.remove(&k);
|
||||
} else {
|
||||
bind.addresses
|
||||
.disabled
|
||||
.insert(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user