Skip to content

Commit cbffa3a

Browse files
authored
Merge pull request #177 from Anyitechs/add-TorSupport
2 parents f7b895e + 9af1012 commit cbffa3a

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed

ldk-server/ldk-server-config.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,8 @@ poll_metrics_interval = 60 # The polling interval for metrics in seconds.
9696
# The auth details below are optional, but uncommenting the fields means enabling basic auth, so valid fields must be supplied.
9797
#username = "" # The username required to access the metrics endpoint (Basic Auth).
9898
#password = "" # The password required to access the metrics endpoint (Basic Auth).
99+
100+
# Tor Config
101+
[tor]
102+
# Only connections to OnionV3 peers will be made via this proxy; other connections (IPv4 peers, Electrum server) will not be routed over Tor.
103+
#proxy_address = "" # Tor daemon SOCKS proxy address.

ldk-server/src/main.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,14 @@ fn main() {
183183
);
184184
}
185185

186+
if let Some(tor_config) = config_file.tor_config {
187+
let tor_config = ldk_node::config::TorConfig { proxy_address: tor_config.proxy_address };
188+
if let Err(e) = builder.set_tor_config(tor_config) {
189+
error!("Failed to configure Tor proxy: {e}");
190+
std::process::exit(-1);
191+
}
192+
}
193+
186194
// LSPS2 support is highly experimental and for testing purposes only.
187195
#[cfg(feature = "experimental-lsps2-support")]
188196
builder.set_liquidity_provider_lsps2(

ldk-server/src/util/config.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ pub struct Config {
6464
pub poll_metrics_interval: Option<u64>,
6565
pub metrics_username: Option<String>,
6666
pub metrics_password: Option<String>,
67+
pub tor_config: Option<TorConfig>,
6768
}
6869

6970
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -87,6 +88,11 @@ pub enum ChainSource {
8788
Esplora { server_url: String },
8889
}
8990

91+
#[derive(Debug, PartialEq, Eq)]
92+
pub struct TorConfig {
93+
pub proxy_address: SocketAddress,
94+
}
95+
9096
/// A builder for `Config`.
9197
#[derive(Default)]
9298
struct ConfigBuilder {
@@ -113,6 +119,7 @@ struct ConfigBuilder {
113119
poll_metrics_interval: Option<u64>,
114120
metrics_username: Option<String>,
115121
metrics_password: Option<String>,
122+
tor_proxy_address: Option<String>,
116123
}
117124

118125
impl ConfigBuilder {
@@ -180,6 +187,10 @@ impl ConfigBuilder {
180187
self.metrics_username = metrics.username.or(self.metrics_username.clone());
181188
self.metrics_password = metrics.password.or(self.metrics_password.clone());
182189
}
190+
191+
if let Some(tor) = toml.tor {
192+
self.tor_proxy_address = Some(tor.proxy_address)
193+
}
183194
}
184195

185196
fn merge_args(&mut self, args: &ArgsConfig) {
@@ -238,6 +249,10 @@ impl ConfigBuilder {
238249
if let Some(metrics_password) = &args.metrics_password {
239250
self.metrics_password = Some(metrics_password.clone());
240251
}
252+
253+
if let Some(tor_proxy_address) = &args.tor_proxy_address {
254+
self.tor_proxy_address = Some(tor_proxy_address.clone());
255+
}
241256
}
242257

243258
fn build(self) -> io::Result<Config> {
@@ -410,6 +425,18 @@ impl ConfigBuilder {
410425
"Both `metrics.username` and `metrics.password` must be set if authentication is used for metrics."));
411426
}
412427

428+
let tor_proxy_address: Option<SocketAddress> = self
429+
.tor_proxy_address
430+
.map(|addrs| {
431+
SocketAddress::from_str(&addrs).map_err(|e| {
432+
io::Error::new(
433+
io::ErrorKind::InvalidInput,
434+
format!("Invalid proxy address configured: {}", e),
435+
)
436+
})
437+
})
438+
.transpose()?;
439+
413440
Ok(Config {
414441
network,
415442
listening_addrs,
@@ -431,6 +458,7 @@ impl ConfigBuilder {
431458
poll_metrics_interval,
432459
metrics_username,
433460
metrics_password,
461+
tor_config: tor_proxy_address.map(|proxy_address| TorConfig { proxy_address }),
434462
})
435463
}
436464
}
@@ -448,6 +476,7 @@ pub struct TomlConfig {
448476
log: Option<LogConfig>,
449477
tls: Option<TomlTlsConfig>,
450478
metrics: Option<MetricsTomlConfig>,
479+
tor: Option<TomlTorConfig>,
451480
}
452481

453482
#[derive(Deserialize, Serialize)]
@@ -515,6 +544,11 @@ struct MetricsTomlConfig {
515544
password: Option<String>,
516545
}
517546

547+
#[derive(Deserialize, Serialize)]
548+
struct TomlTorConfig {
549+
proxy_address: String,
550+
}
551+
518552
#[derive(Deserialize, Serialize)]
519553
struct LiquidityConfig {
520554
lsps2_client: Option<LSPSClientTomlConfig>,
@@ -702,6 +736,13 @@ pub struct ArgsConfig {
702736
help = "The password required to access the metrics endpoint (Basic Auth)."
703737
)]
704738
metrics_password: Option<String>,
739+
740+
#[arg(
741+
long,
742+
env = "LDK_SERVER_TOR_PROXY_ADDRESS",
743+
help = "Tor daemon SOCKS proxy address. Only connections to OnionV3 peers will be made via this proxy; other connections (IPv4 peers, Electrum server) will not be routed over Tor."
744+
)]
745+
tor_proxy_address: Option<String>,
705746
}
706747

707748
pub fn load_config(args: &ArgsConfig) -> io::Result<Config> {
@@ -820,6 +861,9 @@ mod tests {
820861
min_payment_size_msat = 10000000 # 10,000 satoshis
821862
max_payment_size_msat = 25000000000 # 0.25 BTC
822863
client_trusts_lsp = true
864+
865+
[tor]
866+
proxy_address = "127.0.0.1:9050"
823867
"#;
824868

825869
fn default_args_config() -> ArgsConfig {
@@ -839,6 +883,7 @@ mod tests {
839883
poll_metrics_interval: None,
840884
metrics_username: None,
841885
metrics_password: None,
886+
tor_proxy_address: None,
842887
}
843888
}
844889

@@ -859,6 +904,7 @@ mod tests {
859904
poll_metrics_interval: None,
860905
metrics_username: None,
861906
metrics_password: None,
907+
tor_proxy_address: None,
862908
}
863909
}
864910

@@ -939,6 +985,9 @@ mod tests {
939985
poll_metrics_interval: None,
940986
metrics_username: None,
941987
metrics_password: None,
988+
tor_config: Some(TorConfig {
989+
proxy_address: SocketAddress::from_str("127.0.0.1:9050").unwrap(),
990+
}),
942991
};
943992

944993
assert_eq!(config.listening_addrs, expected.listening_addrs);
@@ -958,6 +1007,7 @@ mod tests {
9581007
assert_eq!(config.log_file_path, expected.log_file_path);
9591008
assert_eq!(config.pathfinding_scores_source_url, expected.pathfinding_scores_source_url);
9601009
assert_eq!(config.metrics_enabled, expected.metrics_enabled);
1010+
assert_eq!(config.tor_config, expected.tor_config);
9611011

9621012
// Test case where only electrum is set
9631013

@@ -1267,6 +1317,7 @@ mod tests {
12671317
poll_metrics_interval: None,
12681318
metrics_username: None,
12691319
metrics_password: None,
1320+
tor_config: None,
12701321
};
12711322

12721323
assert_eq!(config.listening_addrs, expected.listening_addrs);
@@ -1281,6 +1332,7 @@ mod tests {
12811332
assert!(config.lsps2_service_config.is_none());
12821333
assert_eq!(config.pathfinding_scores_source_url, expected.pathfinding_scores_source_url);
12831334
assert_eq!(config.metrics_enabled, expected.metrics_enabled);
1335+
assert_eq!(config.tor_config, expected.tor_config);
12841336
}
12851337

12861338
#[test]
@@ -1383,6 +1435,9 @@ mod tests {
13831435
poll_metrics_interval: None,
13841436
metrics_username: None,
13851437
metrics_password: None,
1438+
tor_config: Some(TorConfig {
1439+
proxy_address: SocketAddress::from_str("127.0.0.1:9050").unwrap(),
1440+
}),
13861441
};
13871442

13881443
assert_eq!(config.listening_addrs, expected.listening_addrs);
@@ -1399,6 +1454,7 @@ mod tests {
13991454
assert_eq!(config.lsps2_service_config.is_some(), expected.lsps2_service_config.is_some());
14001455
assert_eq!(config.pathfinding_scores_source_url, expected.pathfinding_scores_source_url);
14011456
assert_eq!(config.metrics_enabled, expected.metrics_enabled);
1457+
assert_eq!(config.tor_config, expected.tor_config);
14021458
}
14031459

14041460
#[test]

0 commit comments

Comments
 (0)