Skip to content

Commit c3aba2a

Browse files
committed
Add SOCKS5 proxy support for peer and Esplora
Thread an optional socks5_proxy_addr through Config, Builder, ConnectionManager, and EsploraChainSource so all outbound connections can be routed through a SOCKS5 proxy (e.g. Tor). Peer connections branch between connect_outbound_via_socks5 and the existing connect_outbound. The two async fns return different opaque Future types, so we Box::pin in each branch to erase the type before the shared match block. Esplora passes socks5://<addr> to esplora_client::Builder::proxy, which uses reqwest's built-in SOCKS5 support under the hood. Bumps rust-lightning to lsp-0.2.0_socks-support (adf445e5) which adds the connect_outbound_via_socks5 function behind a "socks" feature flag on lightning-net-tokio. Electrum proxy support deferred to a follow-up.
1 parent 4309f47 commit c3aba2a

5 files changed

Lines changed: 68 additions & 27 deletions

File tree

Cargo.toml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,18 @@ default = []
4141
# lightning-liquidity = { version = "0.2.0", features = ["std"] }
4242
# lightning-macros = { version = "0.2.0" }
4343

44-
# Branch: https://github.com/moneydevkit/rust-lightning/tree/lsp-0.2.0_accept-underpaying-htlcs_with_timing_logs
45-
lightning = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611", features = ["std"] }
46-
lightning-types = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611" }
47-
lightning-invoice = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611", features = ["std"] }
48-
lightning-net-tokio = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611" }
49-
lightning-persister = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611", features = ["tokio"] }
50-
lightning-background-processor = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611" }
51-
lightning-rapid-gossip-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611" }
52-
lightning-block-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611", features = ["rest-client", "rpc-client", "tokio"] }
53-
lightning-transaction-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611", features = ["esplora-async-https", "time", "electrum-rustls-ring"] }
54-
lightning-liquidity = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611", features = ["std"] }
55-
lightning-macros = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611" }
44+
# Branch: https://github.com/moneydevkit/rust-lightning/tree/lsp-0.2.0_socks-support
45+
lightning = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f", features = ["std"] }
46+
lightning-types = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f" }
47+
lightning-invoice = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f", features = ["std"] }
48+
lightning-net-tokio = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f", features = ["socks"] }
49+
lightning-persister = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f", features = ["tokio"] }
50+
lightning-background-processor = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f" }
51+
lightning-rapid-gossip-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f" }
52+
lightning-block-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f", features = ["rest-client", "rpc-client", "tokio"] }
53+
lightning-transaction-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f", features = ["esplora-async-https", "time", "electrum-rustls-ring"] }
54+
lightning-liquidity = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f", features = ["std"] }
55+
lightning-macros = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f" }
5656

5757
#lightning = { path = "../rust-lightning/lightning", features = ["std"] }
5858
#lightning-types = { path = "../rust-lightning/lightning-types" }
@@ -100,8 +100,8 @@ winapi = { version = "0.3", features = ["winbase"] }
100100

101101
[dev-dependencies]
102102
# lightning = { version = "0.2.0", features = ["std", "_test_utils"] }
103-
# Branch: https://github.com/moneydevkit/rust-lightning/commits/lsp-0.2.0_accept-underpaying-htlcs
104-
lightning = { git = "https://github.com/moneydevkit/rust-lightning", rev = "070b31d93ca28a80a204e9ddf540eb7767b72611", features = ["std", "_test_utils"] }
103+
# Branch: https://github.com/moneydevkit/rust-lightning/commits/lsp-0.2.0_socks-support
104+
lightning = { git = "https://github.com/moneydevkit/rust-lightning", rev = "adf445e5d5e5c9f0f3c0e3925989404707e06e3f", features = ["std", "_test_utils"] }
105105
#lightning = { path = "../rust-lightning/lightning", features = ["std", "_test_utils"] }
106106
proptest = "1.0.0"
107107
regex = "1.5.6"

src/builder.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,12 @@ impl NodeBuilder {
605605
Ok(self)
606606
}
607607

608+
/// Sets the SOCKS5 proxy address for all outbound connections.
609+
pub fn set_socks5_proxy(&mut self, addr: std::net::SocketAddr) -> &mut Self {
610+
self.config.socks5_proxy_addr = Some(addr);
611+
self
612+
}
613+
608614
/// Sets the role of the node in an asynchronous payments context.
609615
///
610616
/// See <https://github.com/lightning/bolts/pull/1149> for more information about the async payments protocol.
@@ -1126,6 +1132,11 @@ impl ArcedNodeBuilder {
11261132
self.inner.write().unwrap().set_node_alias(node_alias).map(|_| ())
11271133
}
11281134

1135+
/// Sets the SOCKS5 proxy address for all outbound connections.
1136+
pub fn set_socks5_proxy(&self, addr: std::net::SocketAddr) {
1137+
self.inner.write().unwrap().set_socks5_proxy(addr);
1138+
}
1139+
11291140
/// Sets the role of the node in an asynchronous payments context.
11301141
pub fn set_async_payments_role(
11311142
&self, role: Option<AsyncPaymentsRole>,
@@ -1922,7 +1933,7 @@ fn build_with_store_internal(
19221933
);
19231934

19241935
let connection_manager =
1925-
Arc::new(ConnectionManager::new(Arc::clone(&peer_manager), Arc::clone(&logger)));
1936+
Arc::new(ConnectionManager::new(Arc::clone(&peer_manager), config.socks5_proxy_addr, Arc::clone(&logger)));
19261937

19271938
// read_output_sweeper (peer_info was already read in the spawned group above)
19281939
let step_start = Instant::now();

src/chain/esplora.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ impl EsploraChainSource {
5757
client_builder = client_builder.header(header_name, header_value);
5858
}
5959

60+
if let Some(proxy_addr) = config.socks5_proxy_addr {
61+
client_builder = client_builder.proxy(&format!("socks5://{}", proxy_addr));
62+
}
63+
6064
let esplora_client = client_builder.build_async().unwrap();
6165
let tx_sync =
6266
Arc::new(EsploraSyncClient::from_client(esplora_client.clone(), Arc::clone(&logger)));

src/config.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//! Objects for configuring the node.
99
1010
use std::fmt;
11+
use std::net::SocketAddr;
1112
use std::time::Duration;
1213

1314
use bitcoin::secp256k1::PublicKey;
@@ -184,6 +185,11 @@ pub struct Config {
184185
/// **Note:** If unset, default parameters will be used, and you will be able to override the
185186
/// parameters on a per-payment basis in the corresponding method calls.
186187
pub route_parameters: Option<RouteParametersConfig>,
188+
/// Optional SOCKS5 proxy address for all outbound connections (peer, Esplora, Electrum).
189+
///
190+
/// When set, Lightning peer connections and chain-source HTTP requests will be routed
191+
/// through the given SOCKS5 proxy.
192+
pub socks5_proxy_addr: Option<SocketAddr>,
187193
}
188194

189195
impl Default for Config {
@@ -198,6 +204,7 @@ impl Default for Config {
198204
anchor_channels_config: Some(AnchorChannelsConfig::default()),
199205
route_parameters: None,
200206
node_alias: None,
207+
socks5_proxy_addr: None,
201208
}
202209
}
203210
}

src/connection.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
// accordance with one or both of these licenses.
77

88
use std::collections::hash_map::{self, HashMap};
9-
use std::net::ToSocketAddrs;
9+
use std::future::Future;
10+
use std::net::{SocketAddr, ToSocketAddrs};
1011
use std::ops::Deref;
12+
use std::pin::Pin;
1113
use std::sync::{Arc, Mutex};
1214
use std::time::Duration;
1315

@@ -25,16 +27,19 @@ where
2527
pending_connections:
2628
Mutex<HashMap<PublicKey, Vec<tokio::sync::oneshot::Sender<Result<(), Error>>>>>,
2729
peer_manager: Arc<PeerManager>,
30+
socks5_proxy_addr: Option<SocketAddr>,
2831
logger: L,
2932
}
3033

3134
impl<L: Deref + Clone + Sync + Send> ConnectionManager<L>
3235
where
3336
L::Target: LdkLogger,
3437
{
35-
pub(crate) fn new(peer_manager: Arc<PeerManager>, logger: L) -> Self {
38+
pub(crate) fn new(
39+
peer_manager: Arc<PeerManager>, socks5_proxy_addr: Option<SocketAddr>, logger: L,
40+
) -> Self {
3641
let pending_connections = Mutex::new(HashMap::new());
37-
Self { pending_connections, peer_manager, logger }
42+
Self { pending_connections, peer_manager, socks5_proxy_addr, logger }
3843
}
3944

4045
pub(crate) async fn connect_peer_if_necessary(
@@ -78,15 +83,29 @@ where
7883
Error::InvalidSocketAddress
7984
})?;
8085

81-
let connection_future = lightning_net_tokio::connect_outbound(
82-
Arc::clone(&self.peer_manager),
83-
node_id,
84-
socket_addr,
85-
);
86-
87-
let res = match connection_future.await {
88-
Some(connection_closed_future) => {
89-
let mut connection_closed_future = Box::pin(connection_closed_future);
86+
let connection_future =
87+
if let Some(proxy_addr) = self.socks5_proxy_addr {
88+
log_info!(self.logger, "Connecting via SOCKS5 proxy {} to peer: {}@{}", proxy_addr, node_id, addr);
89+
lightning_net_tokio::connect_outbound_via_socks5(
90+
Arc::clone(&self.peer_manager),
91+
node_id,
92+
socket_addr,
93+
proxy_addr,
94+
)
95+
.await
96+
.map(|f| Box::pin(f) as Pin<Box<dyn Future<Output = ()> + Send>>)
97+
} else {
98+
lightning_net_tokio::connect_outbound(
99+
Arc::clone(&self.peer_manager),
100+
node_id,
101+
socket_addr,
102+
)
103+
.await
104+
.map(|f| Box::pin(f) as Pin<Box<dyn Future<Output = ()> + Send>>)
105+
};
106+
107+
let res = match connection_future {
108+
Some(mut connection_closed_future) => {
90109
loop {
91110
tokio::select! {
92111
_ = &mut connection_closed_future => {

0 commit comments

Comments
 (0)