mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 22:57:59 -05:00
net: add i2p transport
This commit is contained in:
@@ -363,6 +363,8 @@ async fn spawn_net(name: String, info: &NetInfo, ex: Arc<Executor<'static>>) ->
|
||||
"tor+tls".to_string(),
|
||||
"nym".to_string(),
|
||||
"nym+tls".to_string(),
|
||||
"i2p".to_string(),
|
||||
"i2p+tls".to_string(),
|
||||
],
|
||||
ban_policy: BanPolicy::Relaxed,
|
||||
..Default::default()
|
||||
|
||||
@@ -67,6 +67,7 @@ impl Connector {
|
||||
let transport_mixing = settings.transport_mixing;
|
||||
let datastore = settings.p2p_datastore.clone();
|
||||
let outbound_connect_timeout = settings.outbound_connect_timeout;
|
||||
let i2p_socks5_proxy = settings.i2p_socks5_proxy.clone();
|
||||
let socks5_proxy = settings.socks5_proxy.clone();
|
||||
drop(settings);
|
||||
|
||||
@@ -111,7 +112,7 @@ impl Connector {
|
||||
}
|
||||
}
|
||||
|
||||
let dialer = Dialer::new(endpoint.clone(), datastore).await?;
|
||||
let dialer = Dialer::new(endpoint.clone(), datastore, Some(i2p_socks5_proxy)).await?;
|
||||
let timeout = Duration::from_secs(outbound_connect_timeout);
|
||||
|
||||
let stop_fut = async {
|
||||
|
||||
@@ -40,6 +40,7 @@ use super::{
|
||||
use crate::{
|
||||
system::{Publisher, PublisherPtr, Subscription},
|
||||
util::{
|
||||
encoding::base32,
|
||||
file::{load_file, save_file},
|
||||
most_frequent_or_any,
|
||||
path::expand_path,
|
||||
@@ -1357,6 +1358,16 @@ impl Hosts {
|
||||
);
|
||||
}
|
||||
|
||||
"i2p" | "i2p+tls" => {
|
||||
if !Self::is_i2p_host(host_str) {
|
||||
continue
|
||||
}
|
||||
trace!(
|
||||
target: "net::hosts::filter_addresses",
|
||||
"[I2p] Valid: {}", host_str,
|
||||
);
|
||||
}
|
||||
|
||||
_ => continue,
|
||||
}
|
||||
|
||||
@@ -1501,7 +1512,7 @@ impl Hosts {
|
||||
// with stuff that has host_str().
|
||||
if addr.host_str().is_some() {
|
||||
// Localhost connections should never enter the blacklist
|
||||
// This however allows any Tor and Nym connections.
|
||||
// This however allows any Tor, Nym and I2p connections.
|
||||
if self.is_local_host(addr) {
|
||||
return Ok(());
|
||||
}
|
||||
@@ -1590,6 +1601,26 @@ impl Hosts {
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn is_i2p_host(host: &str) -> bool {
|
||||
if !host.ends_with(".i2p") {
|
||||
return false
|
||||
}
|
||||
|
||||
// Two kinds of address
|
||||
// 1. wvbtv6i6njxdtxwsgsr3d4xejdtsy6n7s3d2paqgigjkv3fv5imq.b32.i2p
|
||||
// 2. node.darkfi.i2p
|
||||
let name = host.trim_end_matches(".i2p");
|
||||
|
||||
if name.ends_with(".b32") {
|
||||
let b32 = name.trim_end_matches(".b32");
|
||||
let decoded = base32::decode(b32);
|
||||
// decoded should be a SHA256 hash
|
||||
return decoded.is_some() && decoded.unwrap().len() == 32
|
||||
}
|
||||
|
||||
name.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '.')
|
||||
}
|
||||
}
|
||||
|
||||
/// We need a convenience method from Rust's unstable feature "ip".
|
||||
@@ -1866,4 +1897,12 @@ mod tests {
|
||||
println!("last entry: {} {}", entry.0, entry.1);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_p2p_host() {
|
||||
assert!(Hosts::is_i2p_host("tm7bz5qfh73id33yjpshxmesrqedoz2ckghd3levktqywcrramwq.b32.i2p"));
|
||||
assert!(!Hosts::is_i2p_host("randomstring.b32.i2p"));
|
||||
assert!(Hosts::is_i2p_host("node.dark.fi.i2p"));
|
||||
assert!(!Hosts::is_i2p_host("node.dark.fi"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ const PROTO_NAME: &str = "ProtocolAddress";
|
||||
/// combinations. Should be updated if and when new transports are
|
||||
/// added. Creates a upper bound on the number of transports a given peer
|
||||
/// can request.
|
||||
const TRANSPORT_COMBOS: [&str; 7] = ["tor", "tls", "tcp", "nym", "tor+tls", "nym+tls", "tcp+tls"];
|
||||
const TRANSPORT_COMBOS: [&str; 9] =
|
||||
["tor", "tls", "tcp", "nym", "i2p", "tor+tls", "nym+tls", "tcp+tls", "i2p+tls"];
|
||||
|
||||
impl ProtocolAddress {
|
||||
/// Creates a new address protocol. Makes an address, an external address
|
||||
|
||||
@@ -67,6 +67,8 @@ pub struct Settings {
|
||||
/// Socks5 proxy to connect to when socks5 or socks5+tls are added to allowed transports
|
||||
/// and transport mixing is enabled
|
||||
pub socks5_proxy: Url,
|
||||
/// I2p Socks5 proxy to connect to i2p eepsite (hidden services)
|
||||
pub i2p_socks5_proxy: Url,
|
||||
/// Outbound connection slots number, this many connections will be
|
||||
/// attempted. (This does not include manual connections)
|
||||
pub outbound_connections: usize,
|
||||
@@ -128,6 +130,7 @@ impl Default for Settings {
|
||||
allowed_transports: vec!["tcp+tls".to_string()],
|
||||
transport_mixing: true,
|
||||
socks5_proxy: Url::parse("socks5://127.0.0.1:9050").unwrap(),
|
||||
i2p_socks5_proxy: Url::parse("socks5://127.0.0.1:4447").unwrap(),
|
||||
outbound_connections: 8,
|
||||
inbound_connections: 8,
|
||||
outbound_connect_timeout: 15,
|
||||
@@ -234,6 +237,10 @@ pub struct SettingsOpt {
|
||||
#[structopt(long)]
|
||||
pub socks5_proxy: Option<Url>,
|
||||
|
||||
/// I2p Socks5 proxy to connect to i2p eepsite (hidden services)
|
||||
#[structopt(long)]
|
||||
pub i2p_socks5_proxy: Option<Url>,
|
||||
|
||||
/// If this is true, strictly follow the gold_connect_count and
|
||||
/// white_connect_percent settings. Otherwise, connect to greylist
|
||||
/// entries if we have no white or gold connections.
|
||||
@@ -311,6 +318,7 @@ impl From<SettingsOpt> for Settings {
|
||||
allowed_transports: opt.allowed_transports.unwrap_or(def.allowed_transports),
|
||||
transport_mixing: opt.transport_mixing.unwrap_or(def.transport_mixing),
|
||||
socks5_proxy: opt.socks5_proxy.unwrap_or(def.socks5_proxy),
|
||||
i2p_socks5_proxy: opt.i2p_socks5_proxy.unwrap_or(def.i2p_socks5_proxy),
|
||||
outbound_connections: opt.outbound_connections.unwrap_or(def.outbound_connections),
|
||||
inbound_connections: opt.inbound_connections.unwrap_or(def.inbound_connections),
|
||||
outbound_connect_timeout: opt
|
||||
|
||||
@@ -132,7 +132,11 @@ macro_rules! enforce_abspath {
|
||||
|
||||
impl Dialer {
|
||||
/// Instantiate a new [`Dialer`] with the given [`Url`] and datastore path.
|
||||
pub async fn new(endpoint: Url, datastore: Option<String>) -> io::Result<Self> {
|
||||
pub async fn new(
|
||||
endpoint: Url,
|
||||
datastore: Option<String>,
|
||||
i2p_socks5_proxy: Option<Url>,
|
||||
) -> io::Result<Self> {
|
||||
match endpoint.scheme().to_lowercase().as_str() {
|
||||
"tcp" => {
|
||||
// Build a TCP dialer
|
||||
@@ -211,6 +215,27 @@ impl Dialer {
|
||||
Ok(Self { endpoint, variant })
|
||||
}
|
||||
|
||||
"i2p" => {
|
||||
// Build a Socks5 Dialer for I2p
|
||||
enforce_hostport!(endpoint);
|
||||
let mut url = i2p_socks5_proxy.unwrap();
|
||||
url.set_path(&format!("{}:{}", endpoint.host().unwrap(), endpoint.port().unwrap()));
|
||||
let variant = socks5::Socks5Dialer::new(&url).await?;
|
||||
let variant = DialerVariant::Socks5(variant);
|
||||
Ok(Self { endpoint, variant })
|
||||
}
|
||||
|
||||
"i2p+tls" => {
|
||||
// Build a SOCKS5 dialer with TLS encapsulation for I2p
|
||||
enforce_hostport!(endpoint);
|
||||
let mut url = i2p_socks5_proxy.unwrap();
|
||||
url.set_path(&format!("{}:{}", endpoint.host().unwrap(), endpoint.port().unwrap()));
|
||||
url.set_scheme("socks5+tls").unwrap();
|
||||
let variant = socks5::Socks5Dialer::new(&url).await?;
|
||||
let variant = DialerVariant::Socks5Tls(variant);
|
||||
Ok(Self { endpoint, variant })
|
||||
}
|
||||
|
||||
x => {
|
||||
error!("[P2P] Requested unsupported transport: {}", x);
|
||||
Err(io::Error::from_raw_os_error(libc::ENETUNREACH))
|
||||
|
||||
@@ -70,7 +70,7 @@ impl RpcClient {
|
||||
|
||||
// Instantiate Dialer and dial the server
|
||||
// TODO: Could add a timeout here
|
||||
let dialer = Dialer::new(dialer_url, None).await?;
|
||||
let dialer = Dialer::new(dialer_url, None, None).await?;
|
||||
let stream = dialer.dial(None).await?;
|
||||
|
||||
// Create the StoppableTask running the request-reply loop.
|
||||
@@ -322,7 +322,7 @@ impl RpcChadClient {
|
||||
|
||||
// Instantiate Dialer and dial the server
|
||||
// TODO: Could add a timeout here
|
||||
let dialer = Dialer::new(dialer_url, None).await?;
|
||||
let dialer = Dialer::new(dialer_url, None, None).await?;
|
||||
let stream = dialer.dial(None).await?;
|
||||
|
||||
// Create the StoppableTask running the request-reply loop.
|
||||
|
||||
@@ -39,7 +39,7 @@ fn tcp_transport() {
|
||||
|
||||
let payload = "ohai tcp";
|
||||
|
||||
let dialer = Dialer::new(url, None).await.unwrap();
|
||||
let dialer = Dialer::new(url, None, None).await.unwrap();
|
||||
let mut client = dialer.dial(None).await.unwrap();
|
||||
payload.encode_async(&mut client).await.unwrap();
|
||||
|
||||
@@ -70,7 +70,7 @@ fn tcp_tls_transport() {
|
||||
|
||||
let payload = "ohai tls";
|
||||
|
||||
let dialer = Dialer::new(url, None).await.unwrap();
|
||||
let dialer = Dialer::new(url, None, None).await.unwrap();
|
||||
let mut client = dialer.dial(None).await.unwrap();
|
||||
payload.encode_async(&mut client).await.unwrap();
|
||||
|
||||
@@ -103,7 +103,7 @@ fn unix_transport() {
|
||||
|
||||
let payload = "ohai unix";
|
||||
|
||||
let dialer = Dialer::new(url, None).await.unwrap();
|
||||
let dialer = Dialer::new(url, None, None).await.unwrap();
|
||||
let mut client = dialer.dial(None).await.unwrap();
|
||||
payload.encode_async(&mut client).await.unwrap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user