Skip to content

Commit 522b511

Browse files
authored
Add SOCKS5 proxy support for peer and Esplora (#24)
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 5baa1f8 commit 522b511

5 files changed

Lines changed: 67 additions & 26 deletions

File tree

Cargo.toml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,17 @@ default = []
4242
# lightning-macros = { version = "0.2.0" }
4343

4444
# 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 = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace", features = ["std"] }
46-
lightning-types = { git = "https://github.com/moneydevkit/rust-lightning", rev = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace" }
47-
lightning-invoice = { git = "https://github.com/moneydevkit/rust-lightning", rev = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace", features = ["std"] }
48-
lightning-net-tokio = { git = "https://github.com/moneydevkit/rust-lightning", rev = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace" }
49-
lightning-persister = { git = "https://github.com/moneydevkit/rust-lightning", rev = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace", features = ["tokio"] }
50-
lightning-background-processor = { git = "https://github.com/moneydevkit/rust-lightning", rev = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace" }
51-
lightning-rapid-gossip-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace" }
52-
lightning-block-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace", features = ["rest-client", "rpc-client", "tokio"] }
53-
lightning-transaction-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace", features = ["esplora-async-https", "time", "electrum-rustls-ring"] }
54-
lightning-liquidity = { git = "https://github.com/moneydevkit/rust-lightning", rev = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace", features = ["std"] }
55-
lightning-macros = { git = "https://github.com/moneydevkit/rust-lightning", rev = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace" }
45+
lightning = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72", features = ["std"] }
46+
lightning-types = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72" }
47+
lightning-invoice = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72", features = ["std"] }
48+
lightning-net-tokio = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72", features = ["socks"] }
49+
lightning-persister = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72", features = ["tokio"] }
50+
lightning-background-processor = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72" }
51+
lightning-rapid-gossip-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72" }
52+
lightning-block-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72", features = ["rest-client", "rpc-client", "tokio"] }
53+
lightning-transaction-sync = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72", features = ["esplora-async-https", "time", "electrum-rustls-ring"] }
54+
lightning-liquidity = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72", features = ["std"] }
55+
lightning-macros = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72" }
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 = "dbc5bf8eb96d72456939d0ba539b7f00618e8ace", features = ["std", "_test_utils"] }
103+
# Branch: https://github.com/moneydevkit/rust-lightning/commits/lsp-0.2.0_accept-underpaying-htlcs_with_timing_logs
104+
lightning = { git = "https://github.com/moneydevkit/rust-lightning", rev = "f56f47fe6c874771cd079faaacf96c42b32fbe72", 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
@@ -606,6 +606,12 @@ impl NodeBuilder {
606606
Ok(self)
607607
}
608608

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

1144+
/// Sets the SOCKS5 proxy address for all outbound connections.
1145+
pub fn set_socks5_proxy(&self, addr: std::net::SocketAddr) {
1146+
self.inner.write().unwrap().set_socks5_proxy(addr);
1147+
}
1148+
11381149
/// Sets the role of the node in an asynchronous payments context.
11391150
pub fn set_async_payments_role(
11401151
&self, role: Option<AsyncPaymentsRole>,
@@ -1940,7 +1951,7 @@ fn build_with_store_internal(
19401951
);
19411952

19421953
let connection_manager =
1943-
Arc::new(ConnectionManager::new(Arc::clone(&peer_manager), Arc::clone(&logger)));
1954+
Arc::new(ConnectionManager::new(Arc::clone(&peer_manager), config.socks5_proxy_addr, Arc::clone(&logger)));
19441955

19451956
// read_output_sweeper (peer_info was already read in the spawned group above)
19461957
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;
@@ -188,6 +189,11 @@ pub struct Config {
188189
/// The parameters used to configure the [`lightning::routing::scoring::ProbabilisticScorer`]
189190
/// used by the node.
190191
pub scoring_parameters: ProbabilisticScoringParameters,
192+
/// Optional SOCKS5 proxy address for all outbound connections (peer, Esplora, Electrum).
193+
///
194+
/// When set, Lightning peer connections and chain-source HTTP requests will be routed
195+
/// through the given SOCKS5 proxy.
196+
pub socks5_proxy_addr: Option<SocketAddr>,
191197
}
192198

193199
impl Default for Config {
@@ -203,6 +209,7 @@ impl Default for Config {
203209
route_parameters: None,
204210
node_alias: None,
205211
scoring_parameters: ProbabilisticScoringParameters::default(),
212+
socks5_proxy_addr: None,
206213
}
207214
}
208215
}

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)