Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.85.0
1.92.0
4 changes: 2 additions & 2 deletions secio/src/dh_compat/openssl_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ struct Algorithm {

static ECDH_P256: Algorithm = Algorithm {
_private_len: 256 / 8,
pubkey_len: 1 + (2 * ((256 + 7) / 8)),
pubkey_len: 1 + (2 * 256_usize.div_ceil(8)),
pairs_generate: p256_generate,
from_pubkey: p256_from_pubkey,
};

static ECDH_P384: Algorithm = Algorithm {
_private_len: 384 / 8,
pubkey_len: 1 + (2 * ((384 + 7) / 8)),
pubkey_len: 1 + (2 * 384_usize.div_ceil(8)),
pairs_generate: p384_generate,
from_pubkey: p384_from_pubkey,
};
Expand Down
28 changes: 28 additions & 0 deletions tentacle/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,34 @@ where
self
}

/// Set trusted proxy addresses for HAProxy PROXY protocol and X-Forwarded-For header parsing.
///
/// When a connection comes from one of these addresses, tentacle will extract the real client IP from:
/// - PROXY protocol v1/v2 headers (for TCP connections)
/// - X-Forwarded-For headers (for WebSocket connections)
///
/// By default, loopback addresses (127.0.0.1 and ::1) are trusted. This method will **replace**
/// the default list with the provided addresses.
///
/// # Example
///
/// ```ignore
/// use std::net::IpAddr;
/// use tentacle::builder::ServiceBuilder;
///
/// // Replace default loopback with custom proxy addresses
/// let builder = ServiceBuilder::new()
/// .trusted_proxies(vec![
/// "192.168.1.100".parse().unwrap(),
/// "10.0.0.1".parse().unwrap(),
/// ]);
/// ```
#[cfg(not(target_family = "wasm"))]
pub fn trusted_proxies(mut self, proxies: Vec<std::net::IpAddr>) -> Self {
self.config.trusted_proxies = proxies;
self
}

/// Whether to allow tentative registration upnp, default is disable(false)
///
/// upnp: https://en.wikipedia.org/wiki/Universal_Plug_and_Play
Expand Down
1 change: 1 addition & 0 deletions tentacle/src/channel/bound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,7 @@ impl<T> Stream for Receiver<T> {
}

impl<T> Drop for Receiver<T> {
#[allow(clippy::unnecessary_unwrap)]
fn drop(&mut self) {
// Drain the channel of all pending messages
self.close();
Expand Down
1 change: 1 addition & 0 deletions tentacle/src/channel/unbound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ impl<T> Stream for UnboundedReceiver<T> {
}

impl<T> Drop for UnboundedReceiver<T> {
#[allow(clippy::unnecessary_unwrap)]
fn drop(&mut self) {
// Drain the channel of all pending messages
self.close();
Expand Down
10 changes: 7 additions & 3 deletions tentacle/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,11 @@ where
let transport = MultiTransport::new(config.timeout.timeout);
#[allow(clippy::let_and_return)]
#[cfg(not(target_family = "wasm"))]
let transport = MultiTransport::new(config.timeout, config.tcp_config.clone());
let transport = MultiTransport::new(
config.timeout,
config.tcp_config.clone(),
config.trusted_proxies.clone(),
);
#[cfg(feature = "tls")]
let transport = transport.tls_config(config.tls_config.clone());
transport
Expand Down Expand Up @@ -256,7 +260,7 @@ where
|| extract_peer_id(&address)
.map(|peer_id| {
inner.dial_protocols.keys().any(|addr| {
if let Some(addr_peer_id) = extract_peer_id(&addr) {
if let Some(addr_peer_id) = extract_peer_id(addr) {
addr_peer_id == peer_id
} else {
false
Expand Down Expand Up @@ -1161,7 +1165,7 @@ where
|| extract_peer_id(&address)
.map(|peer_id| {
self.dial_protocols.keys().any(|addr| {
if let Some(addr_peer_id) = extract_peer_id(&addr) {
if let Some(addr_peer_id) = extract_peer_id(addr) {
addr_peer_id == peer_id
} else {
false
Expand Down
16 changes: 15 additions & 1 deletion tentacle/src/service/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ use std::os::{
fd::AsFd,
unix::io::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd},
};
use std::{net::SocketAddr, sync::Arc, time::Duration};
use std::{
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
sync::Arc,
time::Duration,
};
#[cfg(feature = "tls")]
use tokio_rustls::rustls::{ClientConfig, ServerConfig};

Expand Down Expand Up @@ -46,6 +50,11 @@ pub(crate) struct ServiceConfig {
pub tcp_config: TcpConfig,
#[cfg(feature = "tls")]
pub tls_config: Option<TlsConfig>,
/// Trusted proxy addresses for HAProxy PROXY protocol and X-Forwarded-For header parsing.
/// When a connection comes from one of these addresses, the real client IP will be extracted
/// from PROXY protocol headers (for TCP) or X-Forwarded-For headers (for WebSocket).
/// By default, loopback addresses (127.0.0.1 and ::1) are included in this list.
pub trusted_proxies: Vec<IpAddr>,
}

impl Default for ServiceConfig {
Expand All @@ -61,6 +70,11 @@ impl Default for ServiceConfig {
tcp_config: Default::default(),
#[cfg(feature = "tls")]
tls_config: None,
// Default: trust loopback addresses
trusted_proxies: vec![
IpAddr::V4(Ipv4Addr::LOCALHOST),
IpAddr::V6(Ipv6Addr::LOCALHOST),
],
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion tentacle/src/transports/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ mod memory;
#[cfg(not(target_family = "wasm"))]
mod onion;
#[cfg(not(target_family = "wasm"))]
pub(crate) mod proxy_protocol;
#[cfg(not(target_family = "wasm"))]
mod tcp;
#[cfg(not(target_family = "wasm"))]
pub(crate) mod tcp_base_listen;
Expand Down Expand Up @@ -141,16 +143,23 @@ mod os {
pub(crate) listens_upgrade_modes: Arc<crate::lock::Mutex<HashMap<SocketAddr, UpgradeMode>>>,
#[cfg(feature = "tls")]
pub(crate) tls_config: Option<TlsConfig>,
/// Trusted proxy addresses for HAProxy PROXY protocol and X-Forwarded-For header parsing.
pub(crate) trusted_proxies: Arc<Vec<std::net::IpAddr>>,
}

impl MultiTransport {
pub fn new(timeout: ServiceTimeout, tcp_config: TcpConfig) -> Self {
pub fn new(
timeout: ServiceTimeout,
tcp_config: TcpConfig,
trusted_proxies: Vec<std::net::IpAddr>,
) -> Self {
MultiTransport {
timeout,
tcp_config,
listens_upgrade_modes: Arc::new(crate::lock::Mutex::new(Default::default())),
#[cfg(feature = "tls")]
tls_config: None,
trusted_proxies: Arc::new(trusted_proxies),
}
}

Expand Down
Loading