Implement instance blocklist (#85)

Implement instance blocklist

Co-authored-by: Felix Ableitner <me@nutomic.com>
Reviewed-on: https://yerbamate.dev/LemmyNet/lemmy/pulls/85
pull/1088/head
nutomic 2020-08-13 20:26:49 +00:00 committed by dessalines
parent 9a343cfe8b
commit 164a9c29fe
3 changed files with 47 additions and 25 deletions

View File

@ -62,8 +62,10 @@
enabled: false
# whether tls is required for activitypub. only disable this for debugging, never for producion.
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: ""
# comma separated list of instances which are blocked from federating
blocked_instances: ""
}
captcha: {
enabled: true

View File

@ -8,7 +8,7 @@ static CONFIG_FILE: &str = "config/config.hjson";
#[derive(Debug, Deserialize, Clone)]
pub struct Settings {
pub setup: Option<Setup>,
pub database: Database,
pub database: DatabaseConfig,
pub hostname: String,
pub bind: IpAddr,
pub port: u16,
@ -17,7 +17,7 @@ pub struct Settings {
pub pictrs_url: String,
pub rate_limit: RateLimitConfig,
pub email: Option<EmailConfig>,
pub federation: Federation,
pub federation: FederationConfig,
pub captcha: CaptchaConfig,
}
@ -57,7 +57,7 @@ pub struct CaptchaConfig {
}
#[derive(Debug, Deserialize, Clone)]
pub struct Database {
pub struct DatabaseConfig {
pub user: String,
pub password: String,
pub host: String,
@ -67,10 +67,11 @@ pub struct Database {
}
#[derive(Debug, Deserialize, Clone)]
pub struct Federation {
pub struct FederationConfig {
pub enabled: bool,
pub tls_enabled: bool,
pub allowed_instances: String,
pub blocked_instances: String,
}
lazy_static! {
@ -143,6 +144,20 @@ impl Settings {
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> {
fs::write(CONFIG_FILE, data)?;

View File

@ -76,10 +76,13 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
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();
let domain = apub_id.domain().context(location_info!())?.to_string();
if !allowed_instances.is_empty() {
// need to allow this explicitly because apub activities might contain objects from our local
// instance. replace is needed to remove the port in our federation test setup.
// instance. split is needed to remove the port in our federation test setup.
let settings = Settings::get();
let local_instance = settings.hostname.split(':').collect::<Vec<&str>>();
allowed_instances.push(
@ -89,17 +92,19 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
.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(())
}
None => Err(anyhow!("federation allowlist is empty").into()),
} else {
panic!("Invalid config, both allowed_instances and blocked_instances are specified");
}
}