Skip to content

Commit

Permalink
feat: implement health check service
Browse files Browse the repository at this point in the history
  • Loading branch information
junkurihara committed Oct 30, 2023
1 parent 1b4af7d commit 72e98e5
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 12 deletions.
2 changes: 2 additions & 0 deletions dap-bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ keywords = [
"doh",
"oblivious-dns-over-https",
"odoh",
"mutualized-oblivious-dns",
"mutualized-odoh",
"modoh",
"proxy",
"authorization",
]
Expand Down
6 changes: 4 additions & 2 deletions dap-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ keywords = [
"doh",
"oblivious-dns-over-https",
"odoh",
"mutualized-oblivious-dns",
"mutualized-odoh",
"modoh",
"proxy",
"authorization",
]
Expand Down Expand Up @@ -50,11 +52,12 @@ serde = { version = "1.0.189", features = ["derive"] }
itertools = "0.11.0"
rustc-hash = "1.1.0"

# doh and odoh client
# doh and odoh client with cache and query plugins
odoh-rs = { git = "https://github.com/junkurihara/odoh-rs.git" }
bytes = "1.5.0"
hickory-proto = { version = "0.24.0", default-features = false }
data-encoding = "2.4.0"
hashlink = "0.8.4"

# network
socket2 = "0.5.5"
Expand All @@ -74,7 +77,6 @@ hickory-resolver = { version = "0.24.0", default-features = false, features = [

# authentication
auth-client = { git = "https://github.com/junkurihara/rust-token-server", package = "rust-token-server-client", branch = "develop" }
hashlink = "0.8.4"

[dev-dependencies]
hickory-client = "0.24.0"
Expand Down
11 changes: 8 additions & 3 deletions dap-lib/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@
// Constant Values for Config //
////////////////////////////////
// Cannot override by config.toml
pub const UDP_BUFFER_SIZE: usize = 2048; // TODO: バッファサイズめちゃ適当

/// UDP buffer size TODO: めちゃ適当
pub const UDP_BUFFER_SIZE: usize = 2048;
/// UDP channel Capacity TODO: めちゃ適当
pub const UDP_CHANNEL_CAPACITY: usize = 1024; // TODO: channelキャパシティめちゃ適当
/// UDP timeout in secs
pub const UDP_TIMEOUT_SEC: u64 = 10;
/// TCP listen backlog
pub const TCP_LISTEN_BACKLOG: u32 = 1024;

/// Max connections via UPD and TCP (total) TODO: めちゃ適当
pub const MAX_CONNECTIONS: usize = 128;
/// Time out secs for HTTP requests
pub const HTTP_TIMEOUT_SEC: u64 = 10;

pub const MIN_TTL: u32 = 10; // TTL for overridden records (plugin)
/// TTL for overridden records (plugin) in synthetic response
pub const MIN_TTL: u32 = 10;

////////////////////////////////
// Default Values for Config //
Expand Down
82 changes: 78 additions & 4 deletions dap-lib/src/doh_client/doh_client_healthcheck.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
use super::DoHClient;
use crate::{error::*, log::*};
use super::{dns_message, path_manage::DoHPath, DoHClient};
use crate::{
constants::{HEALTHCHECK_TARGET_ADDR, HEALTHCHECK_TARGET_FQDN},
error::*,
log::*,
};
use futures::future::join_all;
use hickory_proto::op::response_code::ResponseCode;
use std::sync::Arc;
use tokio::sync::Notify;

Expand Down Expand Up @@ -38,11 +44,79 @@ impl DoHClient {
debug!("Purged {} expired entries from cache", purged);
});

// TODO: health check for every path
// make_doh_query_innerを使う
// health check for every path
let futures = self
.path_manager
.paths
.iter()
.flatten()
.flatten()
.map(|path| async move {
if let Err(e) = self.healthcheck(path).await {
warn!("Healthcheck fails for {}: {e}", path.as_url()?)
}
Ok(()) as Result<()>
});
let _ = join_all(futures).await;

if !self
.path_manager
.paths
.iter()
.flatten()
.flatten()
.any(|v| v.is_healthy())
{
error!("All possible paths are unhealthy. Should check the Internet connection");
}
tokio::time::sleep(self.healthcheck_period_sec).await;
}
}

/// Check health for a given path, and update health status for the path.
async fn healthcheck(&self, path: &Arc<DoHPath>) -> Result<()> {
let q_msg = dns_message::build_query_a(HEALTHCHECK_TARGET_FQDN)?;
let packet_buf = dns_message::encode(&q_msg)?;

let Ok((_, res_msg)) = self.make_doh_query_inner(&packet_buf, path).await else {
path.make_unhealthy();
warn!(
"Failed to query or invalid response. Path {} is unhealthy",
path.as_url()?
);
return Ok(());
};

if res_msg.header().response_code() != ResponseCode::NoError {
path.make_unhealthy();
warn!("Response is not Ok. Path {} is unhealthy", path.as_url()?);
return Ok(());
}

let answers = res_msg.answers();
if answers.is_empty() {
path.make_unhealthy();
warn!("Response has no answer. Path {} is unhealthy", path.as_url()?);

return Ok(());
}

let target_addr_contains = answers
.iter()
.filter_map(|answer| answer.data())
.any(|v| v.to_string() == HEALTHCHECK_TARGET_ADDR);

if !target_addr_contains {
path.make_unhealthy();
warn!(
"Response has no or wrong rdata. Maybe suspicious and polluted target. Path {} is unhealthy.",
path.as_url()?
);
return Ok(());
}

path.make_healthy();
debug!("Path {} is healthy", path.as_url()?);
Ok(())
}
}
8 changes: 6 additions & 2 deletions dap-lib/src/doh_client/doh_client_main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub struct DoHClient {
/// auth_client to retrieve id token
auth_client: Option<Arc<Authenticator>>,
/// path candidates with health flags
path_manager: Arc<DoHPathManager>,
pub(super) path_manager: Arc<DoHPathManager>,
/// odoh config store
odoh_configs: Option<Arc<ODoHConfigStore>>,
/// DNS cache
Expand Down Expand Up @@ -192,7 +192,11 @@ impl DoHClient {

/// Make DoH query with a specifically given path.
/// Note cache and plugins are disabled to be used for health check
async fn make_doh_query_inner(&self, packet_buf: &[u8], path: &Arc<DoHPath>) -> Result<(Vec<u8>, Message)> {
pub(super) async fn make_doh_query_inner(
&self,
packet_buf: &[u8],
path: &Arc<DoHPath>,
) -> Result<(Vec<u8>, Message)> {
let headers = self.build_headers().await?;
let response_buf = match self.doh_type {
DoHType::Standard => self.serve_doh_query(packet_buf, path, headers).await,
Expand Down
1 change: 1 addition & 0 deletions dap-lib/src/doh_client/odoh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use rand::{rngs::StdRng, SeedableRng};
#[derive(Debug, Clone)]
/// ODoH config
pub struct ODoHConfig {
#[allow(dead_code)]
authority: String,
inner: ObliviousDoHConfigContents,
}
Expand Down
2 changes: 1 addition & 1 deletion dap-lib/src/doh_client/path_manage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ pub struct DoHPathManager {
/// first dimension: depends on doh target resolver
/// second dimension: depends on next-hop relays. for the standard doh, its is one dimensional.
/// third dimension: actual paths. for the standard doh, its is one dimensional.
paths: Vec<Vec<Vec<Arc<DoHPath>>>>,
pub(super) paths: Vec<Vec<Vec<Arc<DoHPath>>>>,
/// target randomization
target_randomization: bool,
/// next-hop randomization
Expand Down

0 comments on commit 72e98e5

Please sign in to comment.