Skip to content

Commit

Permalink
add support for binding to a specific interface for url previews
Browse files Browse the repository at this point in the history
This is helpful to, for example, bind to an interface that can
only access the public internet. The resulting setup is less
maintenance-heavy / error-prone than manually maintaining a deny/
allowlist to protect internal resources.

Signed-off-by: Jade Ellis <[email protected]>
  • Loading branch information
JadedBlueEyes committed Dec 7, 2024
1 parent fe1ce52 commit 6c6ae6e
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 4 deletions.
10 changes: 10 additions & 0 deletions conduwuit-example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,16 @@
#
#ip_range_denylist = ["127.0.0.0/8", "10.0.0.0/8", "172.16.0.0/12",

# Optional interface to bind to with SO_BINDTODEVICE for URL previews.
# If not set, it will not bind to a specific interface.
# This uses [`reqwest::ClientBuilder::interface`] under the hood.
#
# To list the interfaces on your system, use the command `ip link show`
#
# Example: `"eth0"`
#
#url_preview_bound_interface =

# Vector list of domains allowed to send requests to for URL previews.
# Defaults to none. Note: this is a *contains* match, not an explicit
# match. Putting "google.com" will match "https://google.com" and
Expand Down
19 changes: 19 additions & 0 deletions src/core/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,16 @@ pub struct Config {
#[serde(default = "default_ip_range_denylist")]
pub ip_range_denylist: Vec<String>,

/// Optional interface to bind to with SO_BINDTODEVICE for URL previews.
/// If not set, it will not bind to a specific interface.
/// This uses [`reqwest::ClientBuilder::interface`] under the hood.
///
/// To list the interfaces on your system, use the command `ip link show`
///
/// Example: `"eth0"`
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
pub url_preview_bound_interface: Option<String>,

/// Vector list of domains allowed to send requests to for URL previews.
/// Defaults to none. Note: this is a *contains* match, not an explicit
/// match. Putting "google.com" will match "https://google.com" and
Expand Down Expand Up @@ -1960,6 +1970,15 @@ impl fmt::Display for Config {
line("Forbidden room aliases", {
&self.forbidden_alias_names.patterns().iter().join(", ")
});
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
line(
"URL preview bound interface",
if let Some(interface) = &self.url_preview_bound_interface {
interface
} else {
"not set"
},
);
line(
"URL preview domain contains allowlist",
&self.url_preview_domain_contains_allowlist.join(", "),
Expand Down
16 changes: 12 additions & 4 deletions src/service/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,23 @@ impl crate::Service for Service {
let config = &args.server.config;
let resolver = args.require::<resolver::Service>("resolver");

let url_preview_builder = base(config)?
.dns_resolver(resolver.resolver.clone())
.redirect(redirect::Policy::limited(3));

#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
let url_preview_builder = if let Some(interface) = &config.url_preview_bound_interface {
url_preview_builder.interface(&interface)
} else {
url_preview_builder
};

Ok(Arc::new(Self {
default: base(config)?
.dns_resolver(resolver.resolver.clone())
.build()?,

url_preview: base(config)?
.dns_resolver(resolver.resolver.clone())
.redirect(redirect::Policy::limited(3))
.build()?,
url_preview: url_preview_builder.build()?,

extern_media: base(config)?
.dns_resolver(resolver.resolver.clone())
Expand Down

0 comments on commit 6c6ae6e

Please sign in to comment.