From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 17F081FF17A for ; Sat, 28 Sep 2024 11:43:08 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 1C6DC31F60; Sat, 28 Sep 2024 11:43:22 +0200 (CEST) From: Christian Ebner To: pbs-devel@lists.proxmox.com Date: Sat, 28 Sep 2024 11:42:56 +0200 Message-Id: <20240928094256.153991-5-c.ebner@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20240928094256.153991-1-c.ebner@proxmox.com> References: <20240928094256.153991-1-c.ebner@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.024 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pbs-devel] [POC proxmox-backup 4/4] client: http: Use custom resolver for statically linked binary X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox Backup Server development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pbs-devel-bounces@lists.proxmox.com Sender: "pbs-devel" The dependency on the `getaddrinfo` based `GaiResolver` used by default for the `HttpClient` is not suitable for the statically linked binary of the `proxmox-backup-client`, because of the dependency on glibc NSS libraries, as described in glibc's FAQs [0]. As a workaround, conditionally compile the binary using the `hickory-dns` resolver. [0] https://sourceware.org/glibc/wiki/FAQ#Even_statically_linked_programs_need_some_shared_libraries_which_is_not_acceptable_for_me.__What_can_I_do.3F Suggested-by: Thomas Lamprecht Signed-off-by: Christian Ebner --- Cargo.toml | 6 +++ pbs-client/Cargo.toml | 1 + pbs-client/src/http_client.rs | 81 +++++++++++++++++++++++++++++++++-- 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fc1409d66..792226258 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -160,6 +160,7 @@ walkdir = "2" xdg = "2.2" zstd = { version = "0.12", features = [ "bindgen" ] } zstd-safe = "6.0" +hickory-resolver = { git = "https://github.com/hickory-dns/hickory-dns", tag = "v0.24.1", default-features = false } [dependencies] anyhow.workspace = true @@ -254,6 +255,11 @@ proxmox-rrd-api-types.workspace = true # Local path overrides # NOTE: You must run `cargo update` after changing this for it to take effect! [patch.crates-io] +hickory-proto = { git = "https://github.com/hickory-dns/hickory-dns", tag = "v0.24.1" } +ipconfig = { git = "https://github.com/liranringel/ipconfig", tag = "0.3.2" } +widestring = { git = "https://github.com/starkat99/widestring-rs", tag = "v1.1.0" } +windows-sys = { git = "https://github.com/microsoft/windows-rs", tag = "0.48.0" } +winreg = { git = "https://github.com/gentoo90/winreg-rs", tag = "v0.50.0" } #proxmox-apt = { path = "../proxmox/proxmox-apt" } #proxmox-apt-api-types = { path = "../proxmox/proxmox-apt-api-types" } diff --git a/pbs-client/Cargo.toml b/pbs-client/Cargo.toml index 00c18b83a..785e7c4de 100644 --- a/pbs-client/Cargo.toml +++ b/pbs-client/Cargo.toml @@ -29,6 +29,7 @@ tokio = { workspace = true, features = [ "fs", "signal" ] } tokio-stream.workspace = true tower-service.workspace = true xdg.workspace = true +hickory-resolver = { workspace = true, features = [ "system-config", "tokio-runtime" ] } pathpatterns.workspace = true diff --git a/pbs-client/src/http_client.rs b/pbs-client/src/http_client.rs index 8ae5edaa0..cdec8e42a 100644 --- a/pbs-client/src/http_client.rs +++ b/pbs-client/src/http_client.rs @@ -7,6 +7,8 @@ use futures::*; use http::header::HeaderValue; use http::Uri; use http::{Request, Response}; +#[cfg(not(target_feature = "crt-static"))] +use hyper::client::connect::dns::GaiResolver; use hyper::client::{Client, HttpConnector}; use hyper::Body; use openssl::{ @@ -32,6 +34,74 @@ use pbs_api_types::{Authid, RateLimitConfig, Userid}; use super::pipe_to_stream::PipeToSendStream; use super::PROXMOX_BACKUP_TCP_KEEPALIVE_TIME; +#[cfg(not(target_feature = "crt-static"))] +type DnsResolver = GaiResolver; + +#[cfg(target_feature = "crt-static")] +type DnsResolver = resolver::HickoryDnsResolver; + +#[cfg(target_feature = "crt-static")] +mod resolver { + use std::net::SocketAddr; + use std::pin::Pin; + use std::sync::Arc; + use std::task::{Context, Poll}; + + use futures::Future; + use hickory_resolver::error::ResolveError; + use hickory_resolver::lookup_ip::LookupIpIntoIter; + use hickory_resolver::TokioAsyncResolver; + use hyper::client::connect::dns::Name; + use tower_service::Service; + + pub(crate) struct SocketAddrIter { + inner: LookupIpIntoIter, + } + + impl Iterator for SocketAddrIter { + type Item = SocketAddr; + + fn next(&mut self) -> Option { + self.inner.next().map(|ip_addr| SocketAddr::new(ip_addr, 0)) + } + } + + #[derive(Clone)] + pub(crate) struct HickoryDnsResolver { + inner: Arc, + } + + impl HickoryDnsResolver { + pub(crate) fn new() -> Self { + Self { + inner: Arc::new(TokioAsyncResolver::tokio_from_system_conf().unwrap()), + } + } + } + + impl Service for HickoryDnsResolver { + type Response = SocketAddrIter; + type Error = ResolveError; + type Future = Pin> + Send>>; + + fn poll_ready(&mut self, _ctx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, name: Name) -> Self::Future { + let inner = self.inner.clone(); + Box::pin(async move { + inner + .lookup_ip(name.as_str()) + .await + .map(|r| SocketAddrIter { + inner: r.into_iter(), + }) + }) + } + } +} + /// Timeout used for several HTTP operations that are expected to finish quickly but may block in /// certain error conditions. Keep it generous, to avoid false-positive under high load. const HTTP_TIMEOUT: Duration = Duration::from_secs(2 * 60); @@ -133,7 +203,7 @@ impl Default for HttpClientOptions { /// HTTP(S) API client pub struct HttpClient { - client: Client, + client: Client>, server: String, port: u16, fingerprint: Arc>>, @@ -364,7 +434,8 @@ impl HttpClient { ssl_connector_builder.set_verify(openssl::ssl::SslVerifyMode::NONE); } - let mut httpc = HttpConnector::new(); + let resolver = DnsResolver::new(); + let mut httpc = HttpConnector::new_with_resolver(resolver); httpc.set_nodelay(true); // important for h2 download performance! httpc.enforce_http(false); // we want https... @@ -525,7 +596,9 @@ impl HttpClient { _options: options, }) } +} +impl HttpClient { /// Login /// /// Login is done on demand, so this is only required if you need @@ -814,7 +887,7 @@ impl HttpClient { } async fn credentials( - client: Client, + client: Client>, server: String, port: u16, username: Userid, @@ -859,7 +932,7 @@ impl HttpClient { } async fn api_request( - client: Client, + client: Client>, req: Request, ) -> Result { Self::api_response( -- 2.39.5 _______________________________________________ pbs-devel mailing list pbs-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel