From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <pbs-devel-bounces@lists.proxmox.com> Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id D1FAD1FF15E for <inbox@lore.proxmox.com>; Tue, 8 Apr 2025 17:05:24 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 8004F31443; Tue, 8 Apr 2025 17:05:21 +0200 (CEST) From: Christian Ebner <c.ebner@proxmox.com> To: pbs-devel@lists.proxmox.com Date: Tue, 8 Apr 2025 17:04:17 +0200 Message-Id: <20250408150418.292311-5-c.ebner@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250408150418.292311-1-c.ebner@proxmox.com> References: <20250408150418.292311-1-c.ebner@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.030 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] [PATCH v4 proxmox-backup 4/5] 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 <pbs-devel.lists.proxmox.com> List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pbs-devel>, <mailto:pbs-devel-request@lists.proxmox.com?subject=unsubscribe> List-Archive: <http://lists.proxmox.com/pipermail/pbs-devel/> List-Post: <mailto:pbs-devel@lists.proxmox.com> List-Help: <mailto:pbs-devel-request@lists.proxmox.com?subject=help> List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel>, <mailto:pbs-devel-request@lists.proxmox.com?subject=subscribe> Reply-To: Proxmox Backup Server development discussion <pbs-devel@lists.proxmox.com> Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pbs-devel-bounces@lists.proxmox.com Sender: "pbs-devel" <pbs-devel-bounces@lists.proxmox.com> 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 <t.lamprecht@proxmox.com> Signed-off-by: Christian Ebner <c.ebner@proxmox.com> Tested-by: Lukas Wagner <l.wagner@proxmox.com> --- changes since version 3: - no changes Cargo.toml | 1 + pbs-client/Cargo.toml | 1 + pbs-client/src/http_client.rs | 81 +++++++++++++++++++++++++++++++++-- 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2b9fef9ed..50ae81db1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -127,6 +127,7 @@ futures = "0.3" h2 = { version = "0.4", features = [ "legacy", "stream" ] } handlebars = "3.0" hex = "0.4.3" +hickory-resolver = { version = "0.24.1", default-features = false, features = [ "system-config", "tokio-runtime" ] } hyper = { version = "0.14", features = [ "backports", "deprecated", "full" ] } libc = "0.2" log = "0.4.17" diff --git a/pbs-client/Cargo.toml b/pbs-client/Cargo.toml index c28fe87ca..b4f78b5fd 100644 --- a/pbs-client/Cargo.toml +++ b/pbs-client/Cargo.toml @@ -27,6 +27,7 @@ tokio = { workspace = true, features = [ "fs", "signal" ] } tokio-stream.workspace = true tower-service.workspace = true xdg.workspace = true +hickory-resolver.workspace = true pathpatterns.workspace = true diff --git a/pbs-client/src/http_client.rs b/pbs-client/src/http_client.rs index 8a89031c8..c95def07b 100644 --- a/pbs-client/src/http_client.rs +++ b/pbs-client/src/http_client.rs @@ -4,6 +4,8 @@ use std::time::Duration; use anyhow::{bail, format_err, Error}; use futures::*; +#[cfg(not(target_feature = "crt-static"))] +use hyper::client::connect::dns::GaiResolver; use hyper::client::{Client, HttpConnector}; use hyper::http::header::HeaderValue; use hyper::http::Uri; @@ -33,6 +35,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::Item> { + self.inner.next().map(|ip_addr| SocketAddr::new(ip_addr, 0)) + } + } + + #[derive(Clone)] + pub(crate) struct HickoryDnsResolver { + inner: Arc<TokioAsyncResolver>, + } + + impl HickoryDnsResolver { + pub(crate) fn new() -> Self { + Self { + inner: Arc::new(TokioAsyncResolver::tokio_from_system_conf().unwrap()), + } + } + } + + impl Service<Name> for HickoryDnsResolver { + type Response = SocketAddrIter; + type Error = ResolveError; + type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>; + + fn poll_ready(&mut self, _ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { + 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); @@ -134,7 +204,7 @@ impl Default for HttpClientOptions { /// HTTP(S) API client pub struct HttpClient { - client: Client<HttpsConnector>, + client: Client<HttpsConnector<DnsResolver>>, server: String, port: u16, fingerprint: Arc<Mutex<Option<String>>>, @@ -365,7 +435,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... @@ -526,7 +597,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<HttpsConnector>, + client: Client<HttpsConnector<DnsResolver>>, server: String, port: u16, username: Userid, @@ -859,7 +932,7 @@ impl HttpClient { } async fn api_request( - client: Client<HttpsConnector>, + client: Client<HttpsConnector<DnsResolver>>, req: Request<Body>, ) -> Result<Value, Error> { 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