Implement instance blocklist
This commit is contained in:
parent
4981eb38fb
commit
0308035090
3 changed files with 47 additions and 25 deletions
4
server/config/defaults.hjson
vendored
4
server/config/defaults.hjson
vendored
|
@ -62,8 +62,10 @@
|
||||||
enabled: false
|
enabled: false
|
||||||
# whether tls is required for activitypub. only disable this for debugging, never for producion.
|
# whether tls is required for activitypub. only disable this for debugging, never for producion.
|
||||||
tls_enabled: true
|
tls_enabled: true
|
||||||
# comma seperated list of instances with which federation is allowed
|
# comma separated list of instances with which federation is allowed
|
||||||
allowed_instances: ""
|
allowed_instances: ""
|
||||||
|
# comma separated list of instances which are blocked from federating
|
||||||
|
blocked_instances: ""
|
||||||
}
|
}
|
||||||
captcha: {
|
captcha: {
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
|
@ -8,7 +8,7 @@ static CONFIG_FILE: &str = "config/config.hjson";
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub setup: Option<Setup>,
|
pub setup: Option<Setup>,
|
||||||
pub database: Database,
|
pub database: DatabaseConfig,
|
||||||
pub hostname: String,
|
pub hostname: String,
|
||||||
pub bind: IpAddr,
|
pub bind: IpAddr,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
|
@ -17,7 +17,7 @@ pub struct Settings {
|
||||||
pub pictrs_url: String,
|
pub pictrs_url: String,
|
||||||
pub rate_limit: RateLimitConfig,
|
pub rate_limit: RateLimitConfig,
|
||||||
pub email: Option<EmailConfig>,
|
pub email: Option<EmailConfig>,
|
||||||
pub federation: Federation,
|
pub federation: FederationConfig,
|
||||||
pub captcha: CaptchaConfig,
|
pub captcha: CaptchaConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ pub struct CaptchaConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct Database {
|
pub struct DatabaseConfig {
|
||||||
pub user: String,
|
pub user: String,
|
||||||
pub password: String,
|
pub password: String,
|
||||||
pub host: String,
|
pub host: String,
|
||||||
|
@ -67,10 +67,11 @@ pub struct Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct Federation {
|
pub struct FederationConfig {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub tls_enabled: bool,
|
pub tls_enabled: bool,
|
||||||
pub allowed_instances: String,
|
pub allowed_instances: String,
|
||||||
|
pub blocked_instances: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
@ -143,6 +144,20 @@ impl Settings {
|
||||||
allowed_instances
|
allowed_instances
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_blocked_instances(&self) -> Vec<String> {
|
||||||
|
let mut blocked_instances: Vec<String> = self
|
||||||
|
.federation
|
||||||
|
.blocked_instances
|
||||||
|
.split(',')
|
||||||
|
.map(|d| d.to_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// The defaults.hjson config always returns a [""]
|
||||||
|
blocked_instances.retain(|d| !d.eq(""));
|
||||||
|
|
||||||
|
blocked_instances
|
||||||
|
}
|
||||||
|
|
||||||
pub fn save_config_file(data: &str) -> Result<String, Error> {
|
pub fn save_config_file(data: &str) -> Result<String, Error> {
|
||||||
fs::write(CONFIG_FILE, data)?;
|
fs::write(CONFIG_FILE, data)?;
|
||||||
|
|
||||||
|
|
|
@ -76,30 +76,35 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
|
||||||
return Err(anyhow!("invalid apub id scheme: {:?}", apub_id.scheme()).into());
|
return Err(anyhow!("invalid apub id scheme: {:?}", apub_id.scheme()).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut allowed_instances: Vec<String> = Settings::get().get_allowed_instances();
|
let mut allowed_instances = Settings::get().get_allowed_instances();
|
||||||
|
let blocked_instances = Settings::get().get_blocked_instances();
|
||||||
|
|
||||||
// need to allow this explicitly because apub activities might contain objects from our local
|
let domain = apub_id.domain().context(location_info!())?.to_string();
|
||||||
// instance. replace is needed to remove the port in our federation test setup.
|
if !allowed_instances.is_empty() {
|
||||||
let settings = Settings::get();
|
// need to allow this explicitly because apub activities might contain objects from our local
|
||||||
let local_instance = settings.hostname.split(':').collect::<Vec<&str>>();
|
// instance. split is needed to remove the port in our federation test setup.
|
||||||
allowed_instances.push(
|
let settings = Settings::get();
|
||||||
local_instance
|
let local_instance = settings.hostname.split(':').collect::<Vec<&str>>();
|
||||||
.first()
|
allowed_instances.push(
|
||||||
.context(location_info!())?
|
local_instance
|
||||||
.to_string(),
|
.first()
|
||||||
);
|
.context(location_info!())?
|
||||||
|
.to_string(),
|
||||||
match apub_id.domain() {
|
);
|
||||||
Some(d) => {
|
|
||||||
let contains = allowed_instances.contains(&d.to_owned());
|
|
||||||
|
|
||||||
if !contains {
|
|
||||||
return Err(anyhow!("{} not in federation allowlist", d).into());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if allowed_instances.contains(&domain) {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("{} not in federation allowlist", domain).into())
|
||||||
|
}
|
||||||
|
} else if !blocked_instances.is_empty() {
|
||||||
|
if blocked_instances.contains(&domain) {
|
||||||
|
Err(anyhow!("{} is in federation blocklist", domain).into())
|
||||||
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
None => Err(anyhow!("federation allowlist is empty").into()),
|
} else {
|
||||||
|
panic!("Invalid config, both allowed_instances and blocked_instances are specified");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue