Skip to content

Commit 169bed4

Browse files
authored
Merge pull request #422 from nervosnetwork/support-proxy-protocol
feat: support proxy protocol
2 parents 24f53ca + ea67814 commit 169bed4

File tree

12 files changed

+2002
-28
lines changed

12 files changed

+2002
-28
lines changed

rust-toolchain

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.85.0
1+
1.92.0

secio/src/dh_compat/openssl_impl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ struct Algorithm {
1919

2020
static ECDH_P256: Algorithm = Algorithm {
2121
_private_len: 256 / 8,
22-
pubkey_len: 1 + (2 * ((256 + 7) / 8)),
22+
pubkey_len: 1 + (2 * 256_usize.div_ceil(8)),
2323
pairs_generate: p256_generate,
2424
from_pubkey: p256_from_pubkey,
2525
};
2626

2727
static ECDH_P384: Algorithm = Algorithm {
2828
_private_len: 384 / 8,
29-
pubkey_len: 1 + (2 * ((384 + 7) / 8)),
29+
pubkey_len: 1 + (2 * 384_usize.div_ceil(8)),
3030
pairs_generate: p384_generate,
3131
from_pubkey: p384_from_pubkey,
3232
};

tentacle/src/builder.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,34 @@ where
147147
self
148148
}
149149

150+
/// Set trusted proxy addresses for HAProxy PROXY protocol and X-Forwarded-For header parsing.
151+
///
152+
/// When a connection comes from one of these addresses, tentacle will extract the real client IP from:
153+
/// - PROXY protocol v1/v2 headers (for TCP connections)
154+
/// - X-Forwarded-For headers (for WebSocket connections)
155+
///
156+
/// By default, loopback addresses (127.0.0.1 and ::1) are trusted. This method will **replace**
157+
/// the default list with the provided addresses.
158+
///
159+
/// # Example
160+
///
161+
/// ```ignore
162+
/// use std::net::IpAddr;
163+
/// use tentacle::builder::ServiceBuilder;
164+
///
165+
/// // Replace default loopback with custom proxy addresses
166+
/// let builder = ServiceBuilder::new()
167+
/// .trusted_proxies(vec![
168+
/// "192.168.1.100".parse().unwrap(),
169+
/// "10.0.0.1".parse().unwrap(),
170+
/// ]);
171+
/// ```
172+
#[cfg(not(target_family = "wasm"))]
173+
pub fn trusted_proxies(mut self, proxies: Vec<std::net::IpAddr>) -> Self {
174+
self.config.trusted_proxies = proxies;
175+
self
176+
}
177+
150178
/// Whether to allow tentative registration upnp, default is disable(false)
151179
///
152180
/// upnp: https://en.wikipedia.org/wiki/Universal_Plug_and_Play

tentacle/src/channel/bound.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,7 @@ impl<T> Stream for Receiver<T> {
696696
}
697697

698698
impl<T> Drop for Receiver<T> {
699+
#[allow(clippy::unnecessary_unwrap)]
699700
fn drop(&mut self) {
700701
// Drain the channel of all pending messages
701702
self.close();

tentacle/src/channel/unbound.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ impl<T> Stream for UnboundedReceiver<T> {
500500
}
501501

502502
impl<T> Drop for UnboundedReceiver<T> {
503+
#[allow(clippy::unnecessary_unwrap)]
503504
fn drop(&mut self) {
504505
// Drain the channel of all pending messages
505506
self.close();

tentacle/src/service.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,11 @@ where
173173
let transport = MultiTransport::new(config.timeout.timeout);
174174
#[allow(clippy::let_and_return)]
175175
#[cfg(not(target_family = "wasm"))]
176-
let transport = MultiTransport::new(config.timeout, config.tcp_config.clone());
176+
let transport = MultiTransport::new(
177+
config.timeout,
178+
config.tcp_config.clone(),
179+
config.trusted_proxies.clone(),
180+
);
177181
#[cfg(feature = "tls")]
178182
let transport = transport.tls_config(config.tls_config.clone());
179183
transport
@@ -256,7 +260,7 @@ where
256260
|| extract_peer_id(&address)
257261
.map(|peer_id| {
258262
inner.dial_protocols.keys().any(|addr| {
259-
if let Some(addr_peer_id) = extract_peer_id(&addr) {
263+
if let Some(addr_peer_id) = extract_peer_id(addr) {
260264
addr_peer_id == peer_id
261265
} else {
262266
false
@@ -1161,7 +1165,7 @@ where
11611165
|| extract_peer_id(&address)
11621166
.map(|peer_id| {
11631167
self.dial_protocols.keys().any(|addr| {
1164-
if let Some(addr_peer_id) = extract_peer_id(&addr) {
1168+
if let Some(addr_peer_id) = extract_peer_id(addr) {
11651169
addr_peer_id == peer_id
11661170
} else {
11671171
false

tentacle/src/service/config.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ use std::os::{
1313
fd::AsFd,
1414
unix::io::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd},
1515
};
16-
use std::{net::SocketAddr, sync::Arc, time::Duration};
16+
use std::{
17+
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
18+
sync::Arc,
19+
time::Duration,
20+
};
1721
#[cfg(feature = "tls")]
1822
use tokio_rustls::rustls::{ClientConfig, ServerConfig};
1923

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

5160
impl Default for ServiceConfig {
@@ -61,6 +70,11 @@ impl Default for ServiceConfig {
6170
tcp_config: Default::default(),
6271
#[cfg(feature = "tls")]
6372
tls_config: None,
73+
// Default: trust loopback addresses
74+
trusted_proxies: vec![
75+
IpAddr::V4(Ipv4Addr::LOCALHOST),
76+
IpAddr::V6(Ipv6Addr::LOCALHOST),
77+
],
6478
}
6579
}
6680
}

tentacle/src/transports/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ mod memory;
1818
#[cfg(not(target_family = "wasm"))]
1919
mod onion;
2020
#[cfg(not(target_family = "wasm"))]
21+
pub(crate) mod proxy_protocol;
22+
#[cfg(not(target_family = "wasm"))]
2123
mod tcp;
2224
#[cfg(not(target_family = "wasm"))]
2325
pub(crate) mod tcp_base_listen;
@@ -141,16 +143,23 @@ mod os {
141143
pub(crate) listens_upgrade_modes: Arc<crate::lock::Mutex<HashMap<SocketAddr, UpgradeMode>>>,
142144
#[cfg(feature = "tls")]
143145
pub(crate) tls_config: Option<TlsConfig>,
146+
/// Trusted proxy addresses for HAProxy PROXY protocol and X-Forwarded-For header parsing.
147+
pub(crate) trusted_proxies: Arc<Vec<std::net::IpAddr>>,
144148
}
145149

146150
impl MultiTransport {
147-
pub fn new(timeout: ServiceTimeout, tcp_config: TcpConfig) -> Self {
151+
pub fn new(
152+
timeout: ServiceTimeout,
153+
tcp_config: TcpConfig,
154+
trusted_proxies: Vec<std::net::IpAddr>,
155+
) -> Self {
148156
MultiTransport {
149157
timeout,
150158
tcp_config,
151159
listens_upgrade_modes: Arc::new(crate::lock::Mutex::new(Default::default())),
152160
#[cfg(feature = "tls")]
153161
tls_config: None,
162+
trusted_proxies: Arc::new(trusted_proxies),
154163
}
155164
}
156165

0 commit comments

Comments
 (0)