tor: add service key result check

This commit is contained in:
ardocrat 2024-05-18 14:55:01 +03:00
parent eec434ecaa
commit c4fa0f7ec6

View file

@ -97,19 +97,18 @@ impl Tor {
/// Create Tor client configuration. /// Create Tor client configuration.
fn build_config() -> TorClientConfig { fn build_config() -> TorClientConfig {
// Create Tor client config. // Create Tor client config.
let mut builder = let mut builder = TorClientConfigBuilder::from_directories(
TorClientConfigBuilder::from_directories(TorConfig::state_path(), TorConfig::state_path(),
TorConfig::cache_path()); TorConfig::cache_path(),
);
// Setup bridges. // Setup bridges.
let bridge = TorConfig::get_bridge(); let bridge = TorConfig::get_bridge();
if let Some(b) = bridge { if let Some(b) = bridge {
match b { match b {
super::TorBridge::Snowflake(path, conn) => { super::TorBridge::Snowflake(path, conn) => {
Self::build_snowflake(&mut builder, path, conn) Self::build_snowflake(&mut builder, path, conn)
}, }
super::TorBridge::Obfs4(path, conn) => { super::TorBridge::Obfs4(path, conn) => Self::build_obfs4(&mut builder, path, conn),
Self::build_obfs4(&mut builder, path, conn)
},
} }
} }
// Setup address filter. // Setup address filter.
@ -123,7 +122,10 @@ impl Tor {
pub fn rebuild_client() { pub fn rebuild_client() {
let config = Self::build_config(); let config = Self::build_config();
let r_client = TOR_SERVER_STATE.client_config.read(); let r_client = TOR_SERVER_STATE.client_config.read();
r_client.0.reconfigure(&config, tor_config::Reconfigure::AllOrNothing).unwrap(); r_client
.0
.reconfigure(&config, tor_config::Reconfigure::AllOrNothing)
.unwrap();
} }
/// Send post request using Tor. /// Send post request using Tor.
@ -144,15 +146,11 @@ impl Tor {
// Send request. // Send request.
let mut resp = None; let mut resp = None;
match http.request(req).await { match http.request(req).await {
Ok(r) => { Ok(r) => match hyper::body::to_bytes(r).await {
match hyper::body::to_bytes(r).await { Ok(raw) => resp = Some(String::from_utf8_lossy(&raw).to_string()),
Ok(raw) => { Err(_) => {}
resp = Some(String::from_utf8_lossy(&raw).to_string())
}, },
Err(_) => {}, Err(_) => {}
}
},
Err(_) => {},
} }
resp resp
} }
@ -218,12 +216,28 @@ impl Tor {
let service_id = id.clone(); let service_id = id.clone();
thread::spawn(move || { thread::spawn(move || {
let on_error = |service_id: String| {
// Remove service from starting.
let mut w_services = TOR_SERVER_STATE.starting_services.write();
w_services.remove(&service_id);
// Save failed service.
let mut w_services = TOR_SERVER_STATE.failed_services.write();
w_services.insert(service_id);
};
let (client, config) = Self::client_config(); let (client, config) = Self::client_config();
let client_thread = client.clone(); let client_thread = client.clone();
client.runtime().spawn(async move { client
.runtime()
.spawn(async move {
// Add service key to keystore. // Add service key to keystore.
let hs_nickname = HsNickname::new(service_id.clone()).unwrap(); let hs_nickname = HsNickname::new(service_id.clone()).unwrap();
Self::add_service_key(config.fs_mistrust(), &key, &hs_nickname); if let Err(_) = Self::add_service_key(config.fs_mistrust(),
&key,
&hs_nickname) {
on_error(service_id);
return;
}
// Bootstrap client. // Bootstrap client.
client_thread.bootstrap().await.unwrap(); client_thread.bootstrap().await.unwrap();
// Launch Onion service. // Launch Onion service.
@ -231,23 +245,30 @@ impl Tor {
.nickname(hs_nickname.clone()) .nickname(hs_nickname.clone())
.build() .build()
.unwrap(); .unwrap();
if let Ok((service, request)) = client_thread.launch_onion_service(service_config) { if let Ok((service, request)) =
client_thread.launch_onion_service(service_config)
{
// Launch service proxy. // Launch service proxy.
let addr = SocketAddr::new(IpAddr::from(Ipv4Addr::LOCALHOST), port); let addr = SocketAddr::new(IpAddr::from(Ipv4Addr::LOCALHOST), port);
tokio::spawn( tokio::spawn(Self::run_service_proxy(
Self::run_service_proxy(addr, addr,
client_thread.clone(), client_thread.clone(),
service.clone(), service.clone(),
request, request,
hs_nickname.clone()) hs_nickname.clone(),
).await.unwrap(); ))
.await
.unwrap();
// Check service availability if not checking. // Check service availability if not checking.
if Self::is_service_checking(&service_id) { if Self::is_service_checking(&service_id) {
return; return;
} }
let client_check = client_thread.clone(); let client_check = client_thread.clone();
let url = format!("http://{}/v2/foreign", service.onion_name().unwrap().to_string()); let url = format!(
"http://{}/v2/foreign",
service.onion_name().unwrap().to_string()
);
thread::spawn(move || { thread::spawn(move || {
// Wait 1 second to start. // Wait 1 second to start.
thread::sleep(Duration::from_millis(1000)); thread::sleep(Duration::from_millis(1000));
@ -264,7 +285,8 @@ impl Tor {
loop { loop {
if !Self::is_service_running(&service_id) { if !Self::is_service_running(&service_id) {
// Remove service from checking. // Remove service from checking.
let mut w_services = TOR_SERVER_STATE.checking_services.write(); let mut w_services =
TOR_SERVER_STATE.checking_services.write();
w_services.remove(&service_id); w_services.remove(&service_id);
break; break;
} }
@ -273,13 +295,19 @@ impl Tor {
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "check_version", "method": "check_version",
"params": [] "params": []
}).to_string(); })
.to_string();
// Bootstrap client. // Bootstrap client.
client_check.bootstrap().await.unwrap(); client_check.bootstrap().await.unwrap();
// Create http tor-powered client to post data. // Create http tor-powered client to post data.
let tls_connector = TlsConnector::builder().unwrap().build().unwrap(); let tls_connector =
let tor_connector = ArtiHttpConnector::new(client_check.clone(), tls_connector); TlsConnector::builder().unwrap().build().unwrap();
let http = hyper::Client::builder().build::<_, Body>(tor_connector); let tor_connector = ArtiHttpConnector::new(
client_check.clone(),
tls_connector,
);
let http = hyper::Client::builder()
.build::<_, Body>(tor_connector);
// Create request. // Create request.
let req = hyper::Request::builder() let req = hyper::Request::builder()
.method(hyper::Method::POST) .method(hyper::Method::POST)
@ -290,11 +318,12 @@ impl Tor {
let duration = match http.request(req).await { let duration = match http.request(req).await {
Ok(_) => { Ok(_) => {
// Remove service from starting. // Remove service from starting.
let mut w_services = TOR_SERVER_STATE.starting_services.write(); let mut w_services =
TOR_SERVER_STATE.starting_services.write();
w_services.remove(&service_id); w_services.remove(&service_id);
// Check again after 15 seconds. // Check again after 15 seconds.
Duration::from_millis(15000) Duration::from_millis(15000)
}, }
Err(_) => { Err(_) => {
// Restart service on 3rd error. // Restart service on 3rd error.
errors_count += 1; errors_count += 1;
@ -303,26 +332,27 @@ impl Tor {
let key = key.clone(); let key = key.clone();
let service_id = service_id.clone(); let service_id = service_id.clone();
thread::spawn(move || { thread::spawn(move || {
Self::restart_service(port, key, &service_id); Self::restart_service(
port,
key,
&service_id,
);
}); });
} }
Duration::from_millis(5000) Duration::from_millis(5000)
}, }
}; };
// Wait to check service again.
sleep(duration).await; sleep(duration).await;
} }
}).unwrap(); })
.unwrap();
}); });
} else { return;
// Remove service from starting.
let mut w_services = TOR_SERVER_STATE.starting_services.write();
w_services.remove(&service_id);
// Save failed service.
let mut w_services = TOR_SERVER_STATE.failed_services.write();
w_services.insert(service_id);
} }
on_error(service_id);
}).unwrap(); })
.unwrap();
}); });
} }
@ -332,9 +362,8 @@ impl Tor {
client: TorClient<R>, client: TorClient<R>,
service: Arc<RunningOnionService>, service: Arc<RunningOnionService>,
request: S, request: S,
nickname: HsNickname nickname: HsNickname,
) ) where
where
R: Runtime, R: Runtime,
S: futures::Stream<Item = tor_hsservice::RendRequest> + Unpin + Send + 'static, S: futures::Stream<Item = tor_hsservice::RendRequest> + Unpin + Send + 'static,
{ {
@ -360,65 +389,60 @@ impl Tor {
.spawn(async move { .spawn(async move {
match proxy match proxy
.handle_requests(runtime, nickname.clone(), request) .handle_requests(runtime, nickname.clone(), request)
.await { .await
{
Ok(()) => { Ok(()) => {
// Remove service from running. // Remove service from running.
let mut w_services = let mut w_services = TOR_SERVER_STATE.running_services.write();
TOR_SERVER_STATE.running_services.write();
w_services.remove(&id); w_services.remove(&id);
} }
Err(_) => { Err(_) => {
// Remove service from running. // Remove service from running.
let mut w_services = let mut w_services = TOR_SERVER_STATE.running_services.write();
TOR_SERVER_STATE.running_services.write();
w_services.remove(&id); w_services.remove(&id);
// Save failed service. // Save failed service.
let mut w_services = let mut w_services = TOR_SERVER_STATE.failed_services.write();
TOR_SERVER_STATE.failed_services.write();
w_services.insert(id); w_services.insert(id);
} }
} }
}).unwrap(); })
.unwrap();
} }
/// Save Onion service key to keystore. /// Save Onion service key to keystore.
fn add_service_key(mistrust: &Mistrust, key: &SecretKey, hs_nickname: &HsNickname) { fn add_service_key(
mistrust: &Mistrust,
key: &SecretKey,
hs_nickname: &HsNickname,
) -> tor_keymgr::Result<()> {
let arti_store = let arti_store =
ArtiNativeKeystore::from_path_and_mistrust(TorConfig::keystore_path(), &mistrust) ArtiNativeKeystore::from_path_and_mistrust(TorConfig::keystore_path(), &mistrust)?;
.unwrap();
let key_manager = KeyMgrBuilder::default() let key_manager = KeyMgrBuilder::default()
.default_store(Box::new(arti_store)) .default_store(Box::new(arti_store))
.build() .build()
.unwrap(); .unwrap();
let expanded_sk = ExpandedSecretKey::from_bytes( let expanded_sk =
Sha512::default() ExpandedSecretKey::from_bytes(Sha512::default().chain_update(key).finalize().as_ref());
.chain_update(key)
.finalize()
.as_ref(),
);
let mut sk_bytes = [0_u8; 64]; let mut sk_bytes = [0_u8; 64];
sk_bytes[0..32].copy_from_slice(&expanded_sk.scalar.to_bytes()); sk_bytes[0..32].copy_from_slice(&expanded_sk.scalar.to_bytes());
sk_bytes[32..64].copy_from_slice(&expanded_sk.hash_prefix); sk_bytes[32..64].copy_from_slice(&expanded_sk.hash_prefix);
let expanded_kp = ExpandedKeypair::from_secret_key_bytes(sk_bytes).unwrap(); let expanded_kp = ExpandedKeypair::from_secret_key_bytes(sk_bytes).unwrap();
key_manager key_manager.insert(
.insert(
HsIdKey::from(expanded_kp.public().clone()), HsIdKey::from(expanded_kp.public().clone()),
&HsIdPublicKeySpecifier::new(hs_nickname.clone()), &HsIdPublicKeySpecifier::new(hs_nickname.clone()),
KeystoreSelector::Default, KeystoreSelector::Default,
) )?;
.unwrap();
key_manager key_manager.insert(
.insert(
HsIdKeypair::from(expanded_kp), HsIdKeypair::from(expanded_kp),
&HsIdKeypairSpecifier::new(hs_nickname.clone()), &HsIdKeypairSpecifier::new(hs_nickname.clone()),
KeystoreSelector::Default, KeystoreSelector::Default,
) )?;
.unwrap(); Ok(())
} }
fn build_snowflake(builder: &mut TorClientConfigBuilder, bin_path: String, conn_line: String) { fn build_snowflake(builder: &mut TorClientConfigBuilder, bin_path: String, conn_line: String) {