1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2025-04-22 14:10:16 +03:00

Do spamhaus check

This commit is contained in:
Steven Vergenz 2024-10-31 11:21:16 -07:00
parent b76357c80e
commit 7dd9bda17b
2 changed files with 26 additions and 4 deletions
src
api/client_server
config

View file

@ -7,6 +7,7 @@ use crate::{
service::media::{FileMeta, UrlPreviewData},
config::UrlPreviewPermission,
services, utils, Error, Result, Ruma};
use hickory_resolver::error::ResolveErrorKind;
use http::header::{CONTENT_DISPOSITION, CONTENT_TYPE};
use ruma::{
api::{
@ -126,7 +127,7 @@ async fn download_html(
Ok(data)
}
fn url_request_allowed(addr: &IpAddr) -> bool {
fn is_ip_external(addr: &IpAddr) -> bool {
// could be implemented with reqwest when it supports IP filtering:
// https://github.com/seanmonstar/reqwest/issues/1515
@ -179,18 +180,38 @@ fn url_request_allowed(addr: &IpAddr) -> bool {
/// Generate URL preview data from the given URL
async fn request_url_preview(url: &Url) -> Result<UrlPreviewData> {
// resolve host to IP to ensure it's not a local IP (host guaranteed to not be None)
// host guaranteed to not be None by get_media_preview_route
let host = url.host_str().unwrap();
// resolve host to IP to ensure it's not an internal IP
let dns_resolver = services().globals.dns_resolver();
match dns_resolver.lookup_ip(url.host_str().unwrap()).await {
match dns_resolver.lookup_ip(host).await {
Err(_) => {
return Err(Error::BadServerResponse("Failed to resolve media preview host"));
},
Ok(lookup) if lookup.iter().any(|ip| !url_request_allowed(&ip)) => {
Ok(lookup) if lookup.iter().any(|ip| !is_ip_external(&ip)) => {
return Err(Error::BadRequest(ErrorKind::Unknown, "Requesting from this address forbidden"));
},
Ok(_) => { },
}
// Spamhaus API is over DNS. Query the API domain, no result = no block
// https://docs.spamhaus.com/datasets/docs/source/70-access-methods/data-query-service/040-dqs-queries.html
if services().globals.url_previews().use_spamhaus_denylist {
let resolver = services().globals.dns_resolver();
match resolver.lookup_ip(format!("{host}.dbl.spamhaus.org")).await {
Err(e) => {
if let ResolveErrorKind::NoRecordsFound { .. } = e.kind() { }
else {
tracing::log::warn!("Failed to check Spamhaus denylist: {}", e);
}
},
Ok(_) => {
return Err(Error::BadRequest(ErrorKind::Unknown, "Domain fails reputation check"));
},
}
}
let client = services().globals.default_client();
let response = client.head(url.as_str()).send().await?;

View file

@ -110,6 +110,7 @@ pub struct WellKnownConfig {
pub struct UrlPreviewConfig {
pub default: UrlPreviewPermission,
pub exceptions: Vec<WildCardedDomain>,
pub use_spamhaus_denylist: bool,
}
#[derive(Clone, Debug, Deserialize, Default)]