diff --git a/CHANGELOG.md b/CHANGELOG.md index 9583d50..6fb2dd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Added support for content warnings. - Support integrity proofs with `DataIntegrityProof` type. +- Add `federation.i2p_proxy_url` configuration parameter. ### Changed diff --git a/mitra-config/src/config.rs b/mitra-config/src/config.rs index a3ea8c7..883a363 100644 --- a/mitra-config/src/config.rs +++ b/mitra-config/src/config.rs @@ -93,6 +93,7 @@ impl Config { actor_key: self.instance_rsa_key.clone().unwrap(), proxy_url: self.federation.proxy_url.clone(), onion_proxy_url: self.federation.onion_proxy_url.clone(), + i2p_proxy_url: self.federation.i2p_proxy_url.clone(), // Private instance doesn't send activities and sign requests is_private: !self.federation.enabled || @@ -119,6 +120,7 @@ pub struct Instance { // Proxy for outgoing requests pub proxy_url: Option, pub onion_proxy_url: Option, + pub i2p_proxy_url: Option, // Private instance won't send signed HTTP requests pub is_private: bool, pub fetcher_timeout: u64, @@ -152,6 +154,7 @@ impl Instance { actor_key: generate_weak_rsa_key().unwrap(), proxy_url: None, onion_proxy_url: None, + i2p_proxy_url: None, is_private: true, fetcher_timeout: 0, deliverer_timeout: 0, @@ -173,6 +176,7 @@ mod tests { actor_key: instance_rsa_key, proxy_url: None, onion_proxy_url: None, + i2p_proxy_url: None, is_private: true, fetcher_timeout: 0, deliverer_timeout: 0, @@ -195,6 +199,7 @@ mod tests { actor_key: instance_rsa_key, proxy_url: None, onion_proxy_url: None, + i2p_proxy_url: None, is_private: true, fetcher_timeout: 0, deliverer_timeout: 0, diff --git a/mitra-config/src/federation.rs b/mitra-config/src/federation.rs index 1bfe423..1c80e77 100644 --- a/mitra-config/src/federation.rs +++ b/mitra-config/src/federation.rs @@ -15,6 +15,7 @@ pub struct FederationConfig { pub(super) deliverer_timeout: u64, pub(super) proxy_url: Option, pub(super) onion_proxy_url: Option, + pub(super) i2p_proxy_url: Option, } impl Default for FederationConfig { @@ -25,6 +26,7 @@ impl Default for FederationConfig { deliverer_timeout: default_deliverer_timeout(), proxy_url: None, onion_proxy_url: None, + i2p_proxy_url: None, } } } diff --git a/src/activitypub/deliverer.rs b/src/activitypub/deliverer.rs index 9a0b357..1b0a92d 100644 --- a/src/activitypub/deliverer.rs +++ b/src/activitypub/deliverer.rs @@ -15,10 +15,7 @@ use mitra_models::{ profiles::types::DbActor, users::types::User, }; -use mitra_utils::{ - crypto_rsa::deserialize_private_key, - urls::get_hostname, -}; +use mitra_utils::crypto_rsa::deserialize_private_key; use crate::http_signatures::create::{ create_http_signature, @@ -32,7 +29,7 @@ use crate::json_signatures::create::{ use super::{ constants::AP_MEDIA_TYPE, - http_client::build_federation_client, + http_client::{build_federation_client, get_network_type}, identifiers::{local_actor_id, local_actor_key_id}, queues::OutgoingActivityJobData, }; @@ -63,13 +60,12 @@ pub enum DelivererError { fn build_client( instance: &Instance, - request_uri: &str, + request_url: &str, ) -> Result { - let hostname = get_hostname(request_uri)?; - let is_onion = hostname.ends_with(".onion"); + let network = get_network_type(request_url)?; let client = build_federation_client( instance, - is_onion, + network, instance.deliverer_timeout, )?; Ok(client) diff --git a/src/activitypub/fetcher/fetchers.rs b/src/activitypub/fetcher/fetchers.rs index d4858a6..1bcc99a 100644 --- a/src/activitypub/fetcher/fetchers.rs +++ b/src/activitypub/fetcher/fetchers.rs @@ -7,13 +7,13 @@ use serde_json::{Value as JsonValue}; use mitra_config::Instance; use mitra_utils::{ files::sniff_media_type, - urls::{get_hostname, guess_protocol}, + urls::guess_protocol, }; use crate::activitypub::{ actors::types::Actor, constants::{AP_CONTEXT, AP_MEDIA_TYPE}, - http_client::build_federation_client, + http_client::{build_federation_client, get_network_type}, identifiers::{local_actor_key_id, local_instance_actor_id}, types::Object, vocabulary::GROUP, @@ -56,11 +56,10 @@ fn build_client( instance: &Instance, request_url: &str, ) -> Result { - let hostname = get_hostname(request_url)?; - let is_onion = hostname.ends_with(".onion"); + let network = get_network_type(request_url)?; let client = build_federation_client( instance, - is_onion, + network, instance.fetcher_timeout, )?; Ok(client) diff --git a/src/activitypub/http_client.rs b/src/activitypub/http_client.rs index 74171ca..57d4b63 100644 --- a/src/activitypub/http_client.rs +++ b/src/activitypub/http_client.rs @@ -4,19 +4,47 @@ use std::time::Duration; use reqwest::{Client, Proxy}; use mitra_config::Instance; +use mitra_utils::urls::get_hostname; const CONNECTION_TIMEOUT: u64 = 30; +pub enum Network { + Default, + Tor, + I2p, +} + +pub fn get_network_type(request_url: &str) -> + Result +{ + let hostname = get_hostname(request_url)?; + let network = if hostname.ends_with(".onion") { + Network::Tor + } else if hostname.ends_with(".i2p") { + Network::I2p + } else { + Network::Default + }; + Ok(network) +} + pub fn build_federation_client( instance: &Instance, - is_onion: bool, + network: Network, timeout: u64, ) -> reqwest::Result { let mut client_builder = Client::builder(); let mut maybe_proxy_url = instance.proxy_url.as_ref(); - if is_onion { - maybe_proxy_url = instance.onion_proxy_url.as_ref() - .or(maybe_proxy_url); + match network { + Network::Default => (), + Network::Tor => { + maybe_proxy_url = instance.onion_proxy_url.as_ref() + .or(maybe_proxy_url); + }, + Network::I2p => { + maybe_proxy_url = instance.i2p_proxy_url.as_ref() + .or(maybe_proxy_url); + }, }; if let Some(proxy_url) = maybe_proxy_url { let proxy = Proxy::all(proxy_url)?;