feat: simple federation policies
basically can now fediblock instances, yayy, but more interestingly just refuse to mirror media from problematic instances or refuse deliveries for places we want to read but who shouldn't read us
This commit is contained in:
parent
5800f39c67
commit
95d1ab948f
4 changed files with 38 additions and 1 deletions
|
@ -18,6 +18,9 @@ pub struct Config {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub files: FileStorageConfig,
|
pub files: FileStorageConfig,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub reject: RejectConfig,
|
||||||
|
|
||||||
// TODO should i move app keys here?
|
// TODO should i move app keys here?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,6 +125,19 @@ pub struct FileStorageConfig {
|
||||||
pub path: String,
|
pub path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[serde_inline_default::serde_inline_default]
|
||||||
|
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, serde_default::DefaultFromSerde)]
|
||||||
|
pub struct RejectConfig {
|
||||||
|
#[serde(default)]
|
||||||
|
pub everything: Vec<String>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub media: Vec<String>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub delivery: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn load(path: Option<&std::path::PathBuf>) -> Self {
|
pub fn load(path: Option<&std::path::PathBuf>) -> Self {
|
||||||
let Some(cfg_path) = path else { return Config::default() };
|
let Some(cfg_path) = path else { return Config::default() };
|
||||||
|
|
|
@ -120,6 +120,11 @@ pub async fn cloak_proxy(
|
||||||
let uri = ctx.uncloak(&hmac, &uri)
|
let uri = ctx.uncloak(&hmac, &uri)
|
||||||
.ok_or_else(ApiError::unauthorized)?;
|
.ok_or_else(ApiError::unauthorized)?;
|
||||||
|
|
||||||
|
let stripped = uri.replace("https://", "").replace("http://", "");
|
||||||
|
if ctx.cfg().reject.media.iter().any(|x| stripped.starts_with(x)) {
|
||||||
|
return Err(ApiError::Status(axum::http::StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS));
|
||||||
|
}
|
||||||
|
|
||||||
let resp = Context::client(ctx.domain())
|
let resp = Context::client(ctx.domain())
|
||||||
.get(uri)
|
.get(uri)
|
||||||
.send()
|
.send()
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub async fn post(
|
||||||
AuthIdentity(auth): AuthIdentity,
|
AuthIdentity(auth): AuthIdentity,
|
||||||
Json(activity): Json<serde_json::Value>
|
Json(activity): Json<serde_json::Value>
|
||||||
) -> crate::ApiResult<StatusCode> {
|
) -> crate::ApiResult<StatusCode> {
|
||||||
let Identity::Remote { domain: _server, user: uid, .. } = auth else {
|
let Identity::Remote { domain, user: uid, .. } = auth else {
|
||||||
if matches!(activity.activity_type(), Ok(ActivityType::Delete)) {
|
if matches!(activity.activity_type(), Ok(ActivityType::Delete)) {
|
||||||
// this is spammy af, ignore them!
|
// this is spammy af, ignore them!
|
||||||
// we basically received a delete for a user we can't fetch and verify, meaning remote
|
// we basically received a delete for a user we can't fetch and verify, meaning remote
|
||||||
|
@ -64,6 +64,10 @@ pub async fn post(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if ctx.cfg().reject.everything.contains(&domain) {
|
||||||
|
return Err(crate::ApiError::Status(StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS));
|
||||||
|
}
|
||||||
|
|
||||||
let aid = activity.id()?.to_string();
|
let aid = activity.id()?.to_string();
|
||||||
let server = upub::Context::server(&aid);
|
let server = upub::Context::server(&aid);
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,18 @@ pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<
|
||||||
targets.push(relay);
|
targets.push(relay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
targets
|
||||||
|
.retain(|target| {
|
||||||
|
let stripped = target.replace("https://", "").replace("http://", "");
|
||||||
|
if ctx.cfg().reject.delivery.iter().any(|x| stripped.starts_with(x)) {
|
||||||
|
tracing::warn!("rejecting delivery of {} to {target}", job.activity);
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ctx.deliver(targets, &job.activity, &job.actor, &tx).await?;
|
ctx.deliver(targets, &job.activity, &job.actor, &tx).await?;
|
||||||
|
|
||||||
tx.commit().await?;
|
tx.commit().await?;
|
||||||
|
|
Loading…
Reference in a new issue