Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Federation allow list #673

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions conduwuit-example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,8 @@
# Vector list of servers that conduwuit will refuse to download remote
# media from.
#
# This is in addition to `forbidden_remote_server_names`.
#
#prevent_media_downloads_from = []

# List of forbidden server names that we will block incoming AND outgoing
Expand All @@ -1169,14 +1171,24 @@
# sender user's server name, inbound federation X-Matrix origin, and
# outbound federation handler.
#
# Additionally, it will hide messages from these servers for all users
# on this server.
#
# Basically "global" ACLs.
#
#forbidden_remote_server_names = []

# The inverse of `forbidden_remote_server_names`. By default, allows all
# servers. `forbidden_remote_server_names` takes precedence.
#
#allowed_remote_server_names = []

# List of forbidden server names that we will block all outgoing federated
# room directory requests for. Useful for preventing our users from
# wandering into bad servers or spaces.
#
# This is in addition to `forbidden_remote_server_names`.
#
#forbidden_remote_room_directory_server_names = []

# Vector list of IPv4 and IPv6 CIDR ranges / subnets *in quotes* that you
Expand Down
2 changes: 2 additions & 0 deletions src/api/client/directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub(crate) async fn get_public_rooms_filtered_route(
.config
.forbidden_remote_room_directory_server_names
.contains(server)
|| services.moderation.is_remote_server_forbidden(server)
{
return Err!(Request(Forbidden("Server is banned on this homeserver.")));
}
Expand Down Expand Up @@ -87,6 +88,7 @@ pub(crate) async fn get_public_rooms_route(
.config
.forbidden_remote_room_directory_server_names
.contains(server)
|| services.moderation.is_remote_server_forbidden(server)
{
return Err!(Request(Forbidden("Server is banned on this homeserver.")));
}
Expand Down
13 changes: 3 additions & 10 deletions src/api/client/membership.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,8 @@ async fn banned_room_check(
if let Some(room_id) = room_id {
if services.rooms.metadata.is_banned(room_id).await
|| services
.server
.config
.forbidden_remote_server_names
.contains(&room_id.server_name().unwrap().to_owned())
.moderation
.is_remote_server_forbidden(room_id.server_name().unwrap())
{
warn!(
"User {user_id} who is not an admin attempted to send an invite for or \
Expand Down Expand Up @@ -111,12 +109,7 @@ async fn banned_room_check(
return Err!(Request(Forbidden("This room is banned on this homeserver.")));
}
} else if let Some(server_name) = server_name {
if services
.server
.config
.forbidden_remote_server_names
.contains(&server_name.to_owned())
{
if services.moderation.is_remote_server_forbidden(server_name) {
warn!(
"User {user_id} who is not an admin tried joining a room which has the server \
name {server_name} that is globally forbidden. Rejecting.",
Expand Down
9 changes: 3 additions & 6 deletions src/api/client/message.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use axum::extract::State;
use conduwuit::{
at, is_equal_to,
at,
utils::{
result::{FlatOk, LogErr},
stream::{BroadbandExt, TryIgnore, WidebandExt},
Expand Down Expand Up @@ -241,11 +241,8 @@ pub(crate) async fn ignored_filter(
if IGNORED_MESSAGE_TYPES.binary_search(&pdu.kind).is_ok()
&& (services.users.user_is_ignored(&pdu.sender, user_id).await
|| services
.server
.config
.forbidden_remote_server_names
.iter()
.any(is_equal_to!(pdu.sender().server_name())))
.moderation
.is_remote_server_forbidden(pdu.sender().server_name()))
{
return None;
}
Expand Down
7 changes: 1 addition & 6 deletions src/api/router/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,12 +317,7 @@ fn auth_server_checks(services: &Services, x_matrix: &XMatrix) -> Result<()> {
}

let origin = &x_matrix.origin;
if services
.server
.config
.forbidden_remote_server_names
.contains(origin)
{
if services.moderation.is_remote_server_forbidden(origin) {
return Err!(Request(Forbidden(debug_warn!(
"Federation requests from {origin} denied."
))));
Expand Down
13 changes: 3 additions & 10 deletions src/api/server/invite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,14 @@ pub(crate) async fn create_invite_route(
}

if let Some(server) = body.room_id.server_name() {
if services
.server
.config
.forbidden_remote_server_names
.contains(&server.to_owned())
{
if services.moderation.is_remote_server_forbidden(server) {
return Err!(Request(Forbidden("Server is banned on this homeserver.")));
}
}

if services
.server
.config
.forbidden_remote_server_names
.contains(body.origin())
.moderation
.is_remote_server_forbidden(body.origin())
{
warn!(
"Received federated/remote invite from banned server {} for room ID {}. Rejecting.",
Expand Down
13 changes: 3 additions & 10 deletions src/api/server/make_join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@ pub(crate) async fn create_join_event_template_route(
.await?;

if services
.server
.config
.forbidden_remote_server_names
.contains(body.origin())
.moderation
.is_remote_server_forbidden(body.origin())
{
warn!(
"Server {} for remote user {} tried joining room ID {} which has a server name that \
Expand All @@ -58,12 +56,7 @@ pub(crate) async fn create_join_event_template_route(
}

if let Some(server) = body.room_id.server_name() {
if services
.server
.config
.forbidden_remote_server_names
.contains(&server.to_owned())
{
if services.moderation.is_remote_server_forbidden(server) {
return Err!(Request(Forbidden(warn!(
"Room ID server name {server} is banned on this homeserver."
))));
Expand Down
13 changes: 3 additions & 10 deletions src/api/server/make_knock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,8 @@ pub(crate) async fn create_knock_event_template_route(
.await?;

if services
.server
.config
.forbidden_remote_server_names
.contains(body.origin())
.moderation
.is_remote_server_forbidden(body.origin())
{
warn!(
"Server {} for remote user {} tried knocking room ID {} which has a server name \
Expand All @@ -50,12 +48,7 @@ pub(crate) async fn create_knock_event_template_route(
}

if let Some(server) = body.room_id.server_name() {
if services
.server
.config
.forbidden_remote_server_names
.contains(&server.to_owned())
{
if services.moderation.is_remote_server_forbidden(server) {
return Err!(Request(Forbidden("Server is banned on this homeserver.")));
}
}
Expand Down
26 changes: 6 additions & 20 deletions src/api/server/send_join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,8 @@ pub(crate) async fn create_join_event_v1_route(
body: Ruma<create_join_event::v1::Request>,
) -> Result<create_join_event::v1::Response> {
if services
.server
.config
.forbidden_remote_server_names
.contains(body.origin())
.moderation
.is_remote_server_forbidden(body.origin())
{
warn!(
"Server {} tried joining room ID {} through us who has a server name that is \
Expand All @@ -285,12 +283,7 @@ pub(crate) async fn create_join_event_v1_route(
}

if let Some(server) = body.room_id.server_name() {
if services
.server
.config
.forbidden_remote_server_names
.contains(&server.to_owned())
{
if services.moderation.is_remote_server_forbidden(server) {
warn!(
"Server {} tried joining room ID {} through us which has a server name that is \
globally forbidden. Rejecting.",
Expand Down Expand Up @@ -318,21 +311,14 @@ pub(crate) async fn create_join_event_v2_route(
body: Ruma<create_join_event::v2::Request>,
) -> Result<create_join_event::v2::Response> {
if services
.server
.config
.forbidden_remote_server_names
.contains(body.origin())
.moderation
.is_remote_server_forbidden(body.origin())
{
return Err!(Request(Forbidden("Server is banned on this homeserver.")));
}

if let Some(server) = body.room_id.server_name() {
if services
.server
.config
.forbidden_remote_server_names
.contains(&server.to_owned())
{
if services.moderation.is_remote_server_forbidden(server) {
warn!(
"Server {} tried joining room ID {} through us which has a server name that is \
globally forbidden. Rejecting.",
Expand Down
13 changes: 3 additions & 10 deletions src/api/server/send_knock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ pub(crate) async fn create_knock_event_v1_route(
body: Ruma<send_knock::v1::Request>,
) -> Result<send_knock::v1::Response> {
if services
.server
.config
.forbidden_remote_server_names
.contains(body.origin())
.moderation
.is_remote_server_forbidden(body.origin())
{
warn!(
"Server {} tried knocking room ID {} who has a server name that is globally \
Expand All @@ -37,12 +35,7 @@ pub(crate) async fn create_knock_event_v1_route(
}

if let Some(server) = body.room_id.server_name() {
if services
.server
.config
.forbidden_remote_server_names
.contains(&server.to_owned())
{
if services.moderation.is_remote_server_forbidden(server) {
warn!(
"Server {} tried knocking room ID {} which has a server name that is globally \
forbidden. Rejecting.",
Expand Down
16 changes: 15 additions & 1 deletion src/core/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1324,6 +1324,8 @@ pub struct Config {
/// Vector list of servers that conduwuit will refuse to download remote
/// media from.
///
/// This is in addition to `forbidden_remote_server_names`.
///
/// default: []
#[serde(default)]
pub prevent_media_downloads_from: HashSet<OwnedServerName>,
Expand All @@ -1335,16 +1337,28 @@ pub struct Config {
/// sender user's server name, inbound federation X-Matrix origin, and
/// outbound federation handler.
///
/// Additionally, it will hide messages from these servers for all users
/// on this server.
///
/// Basically "global" ACLs.
///
/// default: []
#[serde(default)]
pub forbidden_remote_server_names: HashSet<OwnedServerName>,

/// The inverse of `forbidden_remote_server_names`. By default, allows all
/// servers. `forbidden_remote_server_names` takes precedence.
///
/// default: []
#[serde(default)]
pub allowed_remote_server_names: HashSet<OwnedServerName>,

/// List of forbidden server names that we will block all outgoing federated
/// room directory requests for. Useful for preventing our users from
/// wandering into bad servers or spaces.
///
/// This is in addition to `forbidden_remote_server_names`.
///
/// default: []
#[serde(default = "HashSet::new")]
pub forbidden_remote_room_directory_server_names: HashSet<OwnedServerName>,
Expand Down Expand Up @@ -1871,7 +1885,7 @@ impl Config {
let mut addrs = Vec::with_capacity(
self.get_bind_hosts()
.len()
.saturating_add(self.get_bind_ports().len()),
.saturating_mul(self.get_bind_ports().len()),
);
for host in &self.get_bind_hosts() {
for port in &self.get_bind_ports() {
Expand Down
8 changes: 1 addition & 7 deletions src/service/federation/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,7 @@ where
return Err!(Config("allow_federation", "Federation is disabled."));
}

if self
.services
.server
.config
.forbidden_remote_server_names
.contains(dest)
{
if self.services.moderation.is_remote_server_forbidden(dest) {
return Err!(Request(Forbidden(debug_warn!("Federation with {dest} is not allowed."))));
}

Expand Down
4 changes: 3 additions & 1 deletion src/service/federation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::sync::Arc;

use conduwuit::{Result, Server};

use crate::{client, resolver, server_keys, Dep};
use crate::{client, moderation, resolver, server_keys, Dep};

pub struct Service {
services: Services,
Expand All @@ -15,6 +15,7 @@ struct Services {
client: Dep<client::Service>,
resolver: Dep<resolver::Service>,
server_keys: Dep<server_keys::Service>,
moderation: Dep<moderation::Service>,
}

impl crate::Service for Service {
Expand All @@ -25,6 +26,7 @@ impl crate::Service for Service {
client: args.depend::<client::Service>("client"),
resolver: args.depend::<resolver::Service>("resolver"),
server_keys: args.depend::<server_keys::Service>("server_keys"),
moderation: args.depend::<moderation::Service>("moderation"),
},
}))
}
Expand Down
4 changes: 3 additions & 1 deletion src/service/media/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use tokio::{

use self::data::{Data, Metadata};
pub use self::thumbnail::Dim;
use crate::{client, globals, sending, Dep};
use crate::{client, globals, moderation, sending, Dep};

#[derive(Debug)]
pub struct FileMeta {
Expand All @@ -42,6 +42,7 @@ struct Services {
client: Dep<client::Service>,
globals: Dep<globals::Service>,
sending: Dep<sending::Service>,
moderation: Dep<moderation::Service>,
}

/// generated MXC ID (`media-id`) length
Expand All @@ -64,6 +65,7 @@ impl crate::Service for Service {
client: args.depend::<client::Service>("client"),
globals: args.depend::<globals::Service>("globals"),
sending: args.depend::<sending::Service>("sending"),
moderation: args.depend::<moderation::Service>("moderation"),
},
}))
}
Expand Down
4 changes: 4 additions & 0 deletions src/service/media/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,10 @@ fn check_fetch_authorized(&self, mxc: &Mxc<'_>) -> Result<()> {
.config
.prevent_media_downloads_from
.contains(mxc.server_name)
|| self
.services
.moderation
.is_remote_server_forbidden(mxc.server_name)
{
// we'll lie to the client and say the blocked server's media was not found and
// log. the client has no way of telling anyways so this is a security bonus.
Expand Down
Loading