de-global services for services

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-07-18 06:37:47 +00:00
parent 992c0a1e58
commit 010e4ee35a
85 changed files with 2480 additions and 1887 deletions

View file

@ -9,12 +9,9 @@ use hickory_resolver::{error::ResolveError, lookup::SrvLookup};
use ipaddress::IPAddress;
use ruma::ServerName;
use crate::{
resolver::{
cache::{CachedDest, CachedOverride},
fed::{add_port_to_hostname, get_ip_with_port, FedDest},
},
services,
use crate::resolver::{
cache::{CachedDest, CachedOverride},
fed::{add_port_to_hostname, get_ip_with_port, FedDest},
};
#[derive(Clone, Debug)]
@ -40,7 +37,7 @@ impl super::Service {
result
} else {
cached = false;
validate_dest(server_name)?;
self.validate_dest(server_name)?;
self.resolve_actual_dest(server_name, true).await?
};
@ -188,7 +185,8 @@ impl super::Service {
self.query_and_cache_override(dest, dest, 8448).await?;
}
let response = services()
let response = self
.services
.client
.well_known
.get(&format!("https://{dest}/.well-known/matrix/server"))
@ -245,19 +243,14 @@ impl super::Service {
#[tracing::instrument(skip_all, name = "ip")]
async fn query_and_cache_override(&self, overname: &'_ str, hostname: &'_ str, port: u16) -> Result<()> {
match services()
.resolver
.raw()
.lookup_ip(hostname.to_owned())
.await
{
Err(e) => handle_resolve_error(&e),
match self.raw().lookup_ip(hostname.to_owned()).await {
Err(e) => Self::handle_resolve_error(&e),
Ok(override_ip) => {
if hostname != overname {
debug_info!("{overname:?} overriden by {hostname:?}");
}
services().resolver.set_cached_override(
self.set_cached_override(
overname.to_owned(),
CachedOverride {
ips: override_ip.iter().collect(),
@ -295,62 +288,62 @@ impl super::Service {
for hostname in hostnames {
match lookup_srv(self.raw(), &hostname).await {
Ok(result) => return Ok(handle_successful_srv(&result)),
Err(e) => handle_resolve_error(&e)?,
Err(e) => Self::handle_resolve_error(&e)?,
}
}
Ok(None)
}
}
#[allow(clippy::single_match_else)]
fn handle_resolve_error(e: &ResolveError) -> Result<()> {
use hickory_resolver::error::ResolveErrorKind;
#[allow(clippy::single_match_else)]
fn handle_resolve_error(e: &ResolveError) -> Result<()> {
use hickory_resolver::error::ResolveErrorKind;
match *e.kind() {
ResolveErrorKind::NoRecordsFound {
..
} => {
// Raise to debug_warn if we can find out the result wasn't from cache
debug!("{e}");
Ok(())
},
_ => Err!(error!("DNS {e}")),
}
}
fn validate_dest(dest: &ServerName) -> Result<()> {
if dest == services().globals.server_name() {
return Err!("Won't send federation request to ourselves");
match *e.kind() {
ResolveErrorKind::NoRecordsFound {
..
} => {
// Raise to debug_warn if we can find out the result wasn't from cache
debug!("{e}");
Ok(())
},
_ => Err!(error!("DNS {e}")),
}
}
if dest.is_ip_literal() || IPAddress::is_valid(dest.host()) {
validate_dest_ip_literal(dest)?;
fn validate_dest(&self, dest: &ServerName) -> Result<()> {
if dest == self.services.server.config.server_name {
return Err!("Won't send federation request to ourselves");
}
if dest.is_ip_literal() || IPAddress::is_valid(dest.host()) {
self.validate_dest_ip_literal(dest)?;
}
Ok(())
}
Ok(())
}
fn validate_dest_ip_literal(&self, dest: &ServerName) -> Result<()> {
trace!("Destination is an IP literal, checking against IP range denylist.",);
debug_assert!(
dest.is_ip_literal() || !IPAddress::is_valid(dest.host()),
"Destination is not an IP literal."
);
let ip = IPAddress::parse(dest.host()).map_err(|e| {
debug_error!("Failed to parse IP literal from string: {}", e);
Error::BadServerResponse("Invalid IP address")
})?;
fn validate_dest_ip_literal(dest: &ServerName) -> Result<()> {
trace!("Destination is an IP literal, checking against IP range denylist.",);
debug_assert!(
dest.is_ip_literal() || !IPAddress::is_valid(dest.host()),
"Destination is not an IP literal."
);
let ip = IPAddress::parse(dest.host()).map_err(|e| {
debug_error!("Failed to parse IP literal from string: {}", e);
Error::BadServerResponse("Invalid IP address")
})?;
self.validate_ip(&ip)?;
validate_ip(&ip)?;
Ok(())
}
pub(crate) fn validate_ip(ip: &IPAddress) -> Result<()> {
if !services().globals.valid_cidr_range(ip) {
return Err(Error::BadServerResponse("Not allowed to send requests to this IP"));
Ok(())
}
Ok(())
pub(crate) fn validate_ip(&self, ip: &IPAddress) -> Result<()> {
if !self.services.globals.valid_cidr_range(ip) {
return Err(Error::BadServerResponse("Not allowed to send requests to this IP"));
}
Ok(())
}
}

View file

@ -5,11 +5,10 @@ use std::{
time::SystemTime,
};
use conduit::trace;
use conduit::{trace, utils::rand};
use ruma::{OwnedServerName, ServerName};
use super::fed::FedDest;
use crate::utils::rand;
pub struct Cache {
pub destinations: RwLock<WellKnownMap>, // actual_destination, host

View file

@ -6,14 +6,22 @@ mod tests;
use std::{fmt::Write, sync::Arc};
use conduit::Result;
use conduit::{Result, Server};
use hickory_resolver::TokioAsyncResolver;
use self::{cache::Cache, dns::Resolver};
use crate::{client, globals, Dep};
pub struct Service {
pub cache: Arc<Cache>,
pub resolver: Arc<Resolver>,
services: Services,
}
struct Services {
server: Arc<Server>,
client: Dep<client::Service>,
globals: Dep<globals::Service>,
}
impl crate::Service for Service {
@ -23,6 +31,11 @@ impl crate::Service for Service {
Ok(Arc::new(Self {
cache: cache.clone(),
resolver: Resolver::build(args.server, cache)?,
services: Services {
server: args.server.clone(),
client: args.depend::<client::Service>("client"),
globals: args.depend::<globals::Service>("globals"),
},
}))
}