Add federation.onion_proxy_url configuration parameter
This commit is contained in:
parent
94a5f3a3cd
commit
50f31e96fc
7 changed files with 55 additions and 14 deletions
|
@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Support audio attachments.
|
- Support audio attachments.
|
||||||
- Added CLI command for viewing unreachable actors.
|
- Added CLI command for viewing unreachable actors.
|
||||||
- Implemented NodeInfo 2.1.
|
- Implemented NodeInfo 2.1.
|
||||||
|
- Added `federation.onion_proxy_url` configuration parameter (enables proxy for requests to `.onion` domains).
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,8 @@ retention:
|
||||||
#federation:
|
#federation:
|
||||||
# # Proxy for outgoing requests
|
# # Proxy for outgoing requests
|
||||||
# #proxy_url: 'socks5h://127.0.0.1:9050'
|
# #proxy_url: 'socks5h://127.0.0.1:9050'
|
||||||
|
# # Proxy for outgoing requests to .onion targets
|
||||||
|
# #onion_proxy_url: 'socks5h://127.0.0.1:9050'
|
||||||
|
|
||||||
# List of blocked domains
|
# List of blocked domains
|
||||||
#blocked_instances: []
|
#blocked_instances: []
|
||||||
|
|
|
@ -99,6 +99,7 @@ impl Config {
|
||||||
_url: self.try_instance_url().unwrap(),
|
_url: self.try_instance_url().unwrap(),
|
||||||
actor_key: self.instance_rsa_key.clone().unwrap(),
|
actor_key: self.instance_rsa_key.clone().unwrap(),
|
||||||
proxy_url: self.federation.proxy_url.clone(),
|
proxy_url: self.federation.proxy_url.clone(),
|
||||||
|
onion_proxy_url: self.federation.onion_proxy_url.clone(),
|
||||||
is_private: matches!(self.environment, Environment::Development),
|
is_private: matches!(self.environment, Environment::Development),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,6 +132,7 @@ pub struct Instance {
|
||||||
pub actor_key: RsaPrivateKey,
|
pub actor_key: RsaPrivateKey,
|
||||||
// Proxy for outgoing requests
|
// Proxy for outgoing requests
|
||||||
pub proxy_url: Option<String>,
|
pub proxy_url: Option<String>,
|
||||||
|
pub onion_proxy_url: Option<String>,
|
||||||
// Private instance won't send signed HTTP requests
|
// Private instance won't send signed HTTP requests
|
||||||
pub is_private: bool,
|
pub is_private: bool,
|
||||||
}
|
}
|
||||||
|
@ -161,6 +163,7 @@ impl Instance {
|
||||||
_url: Url::parse(url).unwrap(),
|
_url: Url::parse(url).unwrap(),
|
||||||
actor_key: generate_weak_rsa_key().unwrap(),
|
actor_key: generate_weak_rsa_key().unwrap(),
|
||||||
proxy_url: None,
|
proxy_url: None,
|
||||||
|
onion_proxy_url: None,
|
||||||
is_private: true,
|
is_private: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,6 +182,7 @@ mod tests {
|
||||||
_url: instance_url,
|
_url: instance_url,
|
||||||
actor_key: instance_rsa_key,
|
actor_key: instance_rsa_key,
|
||||||
proxy_url: None,
|
proxy_url: None,
|
||||||
|
onion_proxy_url: None,
|
||||||
is_private: true,
|
is_private: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,6 +202,7 @@ mod tests {
|
||||||
_url: instance_url,
|
_url: instance_url,
|
||||||
actor_key: instance_rsa_key,
|
actor_key: instance_rsa_key,
|
||||||
proxy_url: None,
|
proxy_url: None,
|
||||||
|
onion_proxy_url: None,
|
||||||
is_private: true,
|
is_private: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,5 @@ use serde::Deserialize;
|
||||||
#[derive(Clone, Default, Deserialize)]
|
#[derive(Clone, Default, Deserialize)]
|
||||||
pub struct FederationConfig {
|
pub struct FederationConfig {
|
||||||
pub proxy_url: Option<String>,
|
pub proxy_url: Option<String>,
|
||||||
|
pub onion_proxy_url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,10 @@ use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use mitra_config::Instance;
|
use mitra_config::Instance;
|
||||||
use mitra_utils::crypto_rsa::deserialize_private_key;
|
use mitra_utils::{
|
||||||
|
crypto_rsa::deserialize_private_key,
|
||||||
|
urls::get_hostname,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::database::{
|
use crate::database::{
|
||||||
DatabaseClient,
|
DatabaseClient,
|
||||||
|
@ -47,18 +50,28 @@ pub enum DelivererError {
|
||||||
#[error("activity serialization error")]
|
#[error("activity serialization error")]
|
||||||
SerializationError(#[from] serde_json::Error),
|
SerializationError(#[from] serde_json::Error),
|
||||||
|
|
||||||
|
#[error("inavlid URL")]
|
||||||
|
UrlError(#[from] url::ParseError),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
RequestError(#[from] reqwest::Error),
|
RequestError(#[from] reqwest::Error),
|
||||||
|
|
||||||
#[error("http error {0:?}")]
|
#[error("http error {0:?}")]
|
||||||
HttpError(reqwest::StatusCode),
|
HttpError(reqwest::StatusCode),
|
||||||
|
|
||||||
#[error(transparent)]
|
|
||||||
DatabaseError(#[from] DatabaseError),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_client(instance: &Instance) -> reqwest::Result<Client> {
|
fn build_client(
|
||||||
build_federation_client(instance, DELIVERER_TIMEOUT)
|
instance: &Instance,
|
||||||
|
request_uri: &str,
|
||||||
|
) -> Result<Client, DelivererError> {
|
||||||
|
let hostname = get_hostname(request_uri)?;
|
||||||
|
let is_onion = hostname.ends_with(".onion");
|
||||||
|
let client = build_federation_client(
|
||||||
|
instance,
|
||||||
|
is_onion,
|
||||||
|
DELIVERER_TIMEOUT,
|
||||||
|
)?;
|
||||||
|
Ok(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_activity(
|
async fn send_activity(
|
||||||
|
@ -76,7 +89,7 @@ async fn send_activity(
|
||||||
actor_key_id,
|
actor_key_id,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let client = build_client(instance)?;
|
let client = build_client(instance, inbox_url)?;
|
||||||
let request = client.post(inbox_url)
|
let request = client.post(inbox_url)
|
||||||
.header("Host", headers.host)
|
.header("Host", headers.host)
|
||||||
.header("Date", headers.date)
|
.header("Date", headers.date)
|
||||||
|
|
|
@ -6,7 +6,7 @@ use serde_json::Value;
|
||||||
use mitra_config::Instance;
|
use mitra_config::Instance;
|
||||||
use mitra_utils::{
|
use mitra_utils::{
|
||||||
files::sniff_media_type,
|
files::sniff_media_type,
|
||||||
urls::guess_protocol,
|
urls::{get_hostname, guess_protocol},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::activitypub::{
|
use crate::activitypub::{
|
||||||
|
@ -31,6 +31,9 @@ pub enum FetchError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
SignatureError(#[from] HttpSignatureError),
|
SignatureError(#[from] HttpSignatureError),
|
||||||
|
|
||||||
|
#[error("inavlid URL")]
|
||||||
|
UrlError(#[from] url::ParseError),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
RequestError(#[from] reqwest::Error),
|
RequestError(#[from] reqwest::Error),
|
||||||
|
|
||||||
|
@ -50,8 +53,18 @@ pub enum FetchError {
|
||||||
OtherError(&'static str),
|
OtherError(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_client(instance: &Instance) -> reqwest::Result<Client> {
|
fn build_client(
|
||||||
build_federation_client(instance, FETCHER_TIMEOUT)
|
instance: &Instance,
|
||||||
|
request_uri: &str,
|
||||||
|
) -> Result<Client, FetchError> {
|
||||||
|
let hostname = get_hostname(request_uri)?;
|
||||||
|
let is_onion = hostname.ends_with(".onion");
|
||||||
|
let client = build_federation_client(
|
||||||
|
instance,
|
||||||
|
is_onion,
|
||||||
|
FETCHER_TIMEOUT,
|
||||||
|
)?;
|
||||||
|
Ok(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_request(
|
fn build_request(
|
||||||
|
@ -75,7 +88,7 @@ async fn send_request(
|
||||||
url: &str,
|
url: &str,
|
||||||
query_params: &[(&str, &str)],
|
query_params: &[(&str, &str)],
|
||||||
) -> Result<String, FetchError> {
|
) -> Result<String, FetchError> {
|
||||||
let client = build_client(instance)?;
|
let client = build_client(instance, url)?;
|
||||||
let mut request_builder = build_request(instance, client, Method::GET, url)
|
let mut request_builder = build_request(instance, client, Method::GET, url)
|
||||||
.header(reqwest::header::ACCEPT, AP_MEDIA_TYPE);
|
.header(reqwest::header::ACCEPT, AP_MEDIA_TYPE);
|
||||||
|
|
||||||
|
@ -113,7 +126,7 @@ pub async fn fetch_file(
|
||||||
file_max_size: usize,
|
file_max_size: usize,
|
||||||
output_dir: &Path,
|
output_dir: &Path,
|
||||||
) -> Result<(String, usize, Option<String>), FetchError> {
|
) -> Result<(String, usize, Option<String>), FetchError> {
|
||||||
let client = build_client(instance)?;
|
let client = build_client(instance, url)?;
|
||||||
let request_builder =
|
let request_builder =
|
||||||
build_request(instance, client, Method::GET, url);
|
build_request(instance, client, Method::GET, url);
|
||||||
let response = request_builder.send().await?.error_for_status()?;
|
let response = request_builder.send().await?.error_for_status()?;
|
||||||
|
@ -164,7 +177,7 @@ pub async fn perform_webfinger_query(
|
||||||
guess_protocol(&actor_address.hostname),
|
guess_protocol(&actor_address.hostname),
|
||||||
actor_address.hostname,
|
actor_address.hostname,
|
||||||
);
|
);
|
||||||
let client = build_client(instance)?;
|
let client = build_client(instance, &webfinger_url)?;
|
||||||
let request_builder =
|
let request_builder =
|
||||||
build_request(instance, client, Method::GET, &webfinger_url);
|
build_request(instance, client, Method::GET, &webfinger_url);
|
||||||
let webfinger_data = request_builder
|
let webfinger_data = request_builder
|
||||||
|
|
|
@ -9,10 +9,16 @@ const CONNECTION_TIMEOUT: u64 = 30;
|
||||||
|
|
||||||
pub fn build_federation_client(
|
pub fn build_federation_client(
|
||||||
instance: &Instance,
|
instance: &Instance,
|
||||||
|
is_onion: bool,
|
||||||
timeout: u64,
|
timeout: u64,
|
||||||
) -> reqwest::Result<Client> {
|
) -> reqwest::Result<Client> {
|
||||||
let mut client_builder = Client::builder();
|
let mut client_builder = Client::builder();
|
||||||
if let Some(ref proxy_url) = instance.proxy_url {
|
let mut maybe_proxy_url = instance.proxy_url.as_ref();
|
||||||
|
if is_onion {
|
||||||
|
maybe_proxy_url = maybe_proxy_url
|
||||||
|
.or(instance.onion_proxy_url.as_ref());
|
||||||
|
};
|
||||||
|
if let Some(proxy_url) = maybe_proxy_url {
|
||||||
let proxy = Proxy::all(proxy_url)?;
|
let proxy = Proxy::all(proxy_url)?;
|
||||||
client_builder = client_builder.proxy(proxy);
|
client_builder = client_builder.proxy(proxy);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue