* [pbs-devel] [PATCH v4 proxmox 1/5] http: client: make https connector generic over resolver
2025-04-08 15:04 [pbs-devel] [PATCH v4 proxmox proxmox-backup 0/5] fix 4788: statically linked proxmox-backup-client Christian Ebner
@ 2025-04-08 15:04 ` Christian Ebner
2025-04-08 15:04 ` [pbs-devel] [PATCH v4 proxmox-backup 2/5] fix: 4788: Makefile: target for statically linked client binary Christian Ebner
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Christian Ebner @ 2025-04-08 15:04 UTC (permalink / raw)
To: pbs-devel
Allow to instantiate a `HttpsConnector` not using the default
`getaddrinfo` based `GaiResolver` for domain name resolution, but
rather a custom resolver implementing the required traits.
The usecase for this is to swap out the DNS resolver for the
statically linked proxmox-backup-client binary, where the glibc
dependency is problematic because of possible ABI incompatibility.
However, set the generic type on `HttpsConnector` to default to
`GaiResolver` to limit inconvenience for implementations using it.
Adds tower-service as cargo workspace dependency and build dependency
to debian/control.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
changes since version 3:
- add GaiResolver as default type for generic on HttpsConnector
proxmox-http/Cargo.toml | 1 +
proxmox-http/src/client/connector.rs | 17 ++++++++++++-----
proxmox-http/src/client/simple.rs | 3 ++-
3 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/proxmox-http/Cargo.toml b/proxmox-http/Cargo.toml
index c8c963f7..6bfb1413 100644
--- a/proxmox-http/Cargo.toml
+++ b/proxmox-http/Cargo.toml
@@ -22,6 +22,7 @@ openssl = { version = "0.10", optional = true }
serde_json = { workspace = true, optional = true }
tokio = { workspace = true, features = [], optional = true }
tokio-openssl = { workspace = true, optional = true }
+tower-service.workspace = true
ureq = { version = "2.4", features = ["native-certs", "native-tls"], optional = true, default-features = false }
url = { workspace = true, optional = true }
diff --git a/proxmox-http/src/client/connector.rs b/proxmox-http/src/client/connector.rs
index 63b9d10c..2e04680f 100644
--- a/proxmox-http/src/client/connector.rs
+++ b/proxmox-http/src/client/connector.rs
@@ -6,6 +6,7 @@ use std::task::{Context, Poll};
use futures::*;
use http::Uri;
+use hyper::client::connect::dns::{GaiResolver, Name};
use hyper::client::HttpConnector;
use openssl::ssl::SslConnector;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
@@ -23,8 +24,8 @@ use crate::{RateLimitedStream, ShareableRateLimit};
type SharedRateLimit = Arc<dyn ShareableRateLimit>;
#[derive(Clone)]
-pub struct HttpsConnector {
- connector: HttpConnector,
+pub struct HttpsConnector<T = GaiResolver> {
+ connector: HttpConnector<T>,
ssl_connector: Arc<SslConnector>,
proxy: Option<ProxyConfig>,
tcp_keepalive: u32,
@@ -32,9 +33,9 @@ pub struct HttpsConnector {
write_limiter: Option<SharedRateLimit>,
}
-impl HttpsConnector {
+impl<T> HttpsConnector<T> {
pub fn with_connector(
- mut connector: HttpConnector,
+ mut connector: HttpConnector<T>,
ssl_connector: SslConnector,
tcp_keepalive: u32,
) -> Self {
@@ -122,7 +123,13 @@ impl HttpsConnector {
}
}
-impl hyper::service::Service<Uri> for HttpsConnector {
+impl<T> hyper::service::Service<Uri> for HttpsConnector<T>
+where
+ T: tower_service::Service<Name> + Clone + Send + Sync + 'static,
+ T::Future: Send,
+ T::Error: Into<Box<(dyn std::error::Error + Send + Sync + 'static)>>,
+ T::Response: std::iter::Iterator<Item = std::net::SocketAddr>,
+{
type Response = MaybeTlsStream<RateLimitedStream<TcpStream>>;
type Error = Error;
#[allow(clippy::type_complexity)]
diff --git a/proxmox-http/src/client/simple.rs b/proxmox-http/src/client/simple.rs
index 062889ac..cb8bb777 100644
--- a/proxmox-http/src/client/simple.rs
+++ b/proxmox-http/src/client/simple.rs
@@ -8,6 +8,7 @@ use futures::*;
#[cfg(all(feature = "client-trait", feature = "proxmox-async"))]
use http::header::HeaderName;
use http::{HeaderValue, Request, Response};
+use hyper::client::connect::dns::GaiResolver;
use hyper::client::Client as HyperClient;
use hyper::client::HttpConnector;
use hyper::Body;
@@ -18,7 +19,7 @@ use crate::HttpOptions;
/// Asynchronous HTTP client implementation
pub struct Client {
- client: HyperClient<HttpsConnector, Body>,
+ client: HyperClient<HttpsConnector<GaiResolver>, Body>,
options: HttpOptions,
}
--
2.39.5
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH v4 proxmox-backup 2/5] fix: 4788: Makefile: target for statically linked client binary
2025-04-08 15:04 [pbs-devel] [PATCH v4 proxmox proxmox-backup 0/5] fix 4788: statically linked proxmox-backup-client Christian Ebner
2025-04-08 15:04 ` [pbs-devel] [PATCH v4 proxmox 1/5] http: client: make https connector generic over resolver Christian Ebner
@ 2025-04-08 15:04 ` Christian Ebner
2025-04-08 15:04 ` [pbs-devel] [PATCH v4 proxmox-backup 3/5] Makefile: switch path based on build mode and target Christian Ebner
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Christian Ebner @ 2025-04-08 15:04 UTC (permalink / raw)
To: pbs-devel
Adds the build target including workarounds to generate a statically
linked version of the proxmox-backup-client binary.
Fixes: https://bugzilla.proxmox.com/show_bug.cgi?id=4788
Suggested-by: Christoph Heiss <c.heiss@proxmox.com>
Originally-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
Makefile | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Makefile b/Makefile
index dfbaacab4..00e7f7401 100644
--- a/Makefile
+++ b/Makefile
@@ -227,3 +227,12 @@ upload: $(SERVER_DEB) $(CLIENT_DEB) $(RESTORE_DEB) $(DOC_DEB)
| ssh -X repoman@repo.proxmox.com upload --product pbs --dist $(UPLOAD_DIST)
tar cf - $(CLIENT_DEB) $(CLIENT_DBG_DEB) | ssh -X repoman@repo.proxmox.com upload --product "pve,pmg,pbs-client" --dist $(UPLOAD_DIST)
tar cf - $(RESTORE_DEB) $(RESTORE_DBG_DEB) | ssh -X repoman@repo.proxmox.com upload --product "pve" --dist $(UPLOAD_DIST)
+
+.PHONY: proxmox-backup-client-static
+proxmox-backup-client-static:
+ mkdir -p target/release/deps/ && \
+ echo '!<arch>' > target/release/deps/libsystemd.a # workaround for to greedy linkage and proxmox-systemd
+ RUSTFLAGS='-C target-feature=+crt-static -C strip=debuginfo' \
+ $(CARGO) build $(CARGO_BUILD_ARGS) \
+ --package proxmox-backup-client --bin proxmox-backup-client \
+ --target x86_64-unknown-linux-gnu
--
2.39.5
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH v4 proxmox-backup 3/5] Makefile: switch path based on build mode and target
2025-04-08 15:04 [pbs-devel] [PATCH v4 proxmox proxmox-backup 0/5] fix 4788: statically linked proxmox-backup-client Christian Ebner
2025-04-08 15:04 ` [pbs-devel] [PATCH v4 proxmox 1/5] http: client: make https connector generic over resolver Christian Ebner
2025-04-08 15:04 ` [pbs-devel] [PATCH v4 proxmox-backup 2/5] fix: 4788: Makefile: target for statically linked client binary Christian Ebner
@ 2025-04-08 15:04 ` Christian Ebner
2025-04-08 15:04 ` [pbs-devel] [PATCH v4 proxmox-backup 4/5] client: http: Use custom resolver for statically linked binary Christian Ebner
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Christian Ebner @ 2025-04-08 15:04 UTC (permalink / raw)
To: pbs-devel
Define variables for the compile path and target and use these
instead of hard-coding the path. Allows to easily switch between
debug and release mode for compilation.
Also, place the libsystemd stub into its own subdirectory for cleaner
separation from the compiled artifacts.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
Tested-by: Lukas Wagner <l.wagner@proxmox.com>
---
changes since version 3:
- no changes
Makefile | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
index 00e7f7401..428ef40b9 100644
--- a/Makefile
+++ b/Makefile
@@ -36,11 +36,15 @@ SUBCRATES != cargo metadata --no-deps --format-version=1 \
| grep "$$PWD/" \
| sed -e "s!.*$$PWD/!!g" -e 's/\#.*$$//g' -e 's/)$$//g'
+STATIC_TARGET ?= x86_64-unknown-linux-gnu
+
ifeq ($(BUILD_MODE), release)
CARGO_BUILD_ARGS += --release
COMPILEDIR := target/$(DEB_HOST_RUST_TYPE)/release
+STATIC_COMPILEDIR := target/$(STATIC_TARGET)/release
else
COMPILEDIR := target/$(DEB_HOST_RUST_TYPE)/debug
+STATIC_COMPILEDIR := target/$(STATIC_TARGET)/debug
endif
ifeq ($(valgrind), yes)
@@ -230,9 +234,9 @@ upload: $(SERVER_DEB) $(CLIENT_DEB) $(RESTORE_DEB) $(DOC_DEB)
.PHONY: proxmox-backup-client-static
proxmox-backup-client-static:
- mkdir -p target/release/deps/ && \
- echo '!<arch>' > target/release/deps/libsystemd.a # workaround for to greedy linkage and proxmox-systemd
- RUSTFLAGS='-C target-feature=+crt-static -C strip=debuginfo' \
+ mkdir -p $(STATIC_COMPILEDIR)/deps-stubs/ && \
+ echo '!<arch>' > $(STATIC_COMPILEDIR)/deps-stubs/libsystemd.a # workaround for to greedy linkage and proxmox-systemd
+ RUSTFLAGS='-C target-feature=+crt-static -C strip=debuginfo -L $(STATIC_COMPILEDIR)/deps-stubs/' \
$(CARGO) build $(CARGO_BUILD_ARGS) \
--package proxmox-backup-client --bin proxmox-backup-client \
- --target x86_64-unknown-linux-gnu
+ --target $(STATIC_TARGET)
--
2.39.5
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH v4 proxmox-backup 4/5] client: http: Use custom resolver for statically linked binary
2025-04-08 15:04 [pbs-devel] [PATCH v4 proxmox proxmox-backup 0/5] fix 4788: statically linked proxmox-backup-client Christian Ebner
` (2 preceding siblings ...)
2025-04-08 15:04 ` [pbs-devel] [PATCH v4 proxmox-backup 3/5] Makefile: switch path based on build mode and target Christian Ebner
@ 2025-04-08 15:04 ` Christian Ebner
2025-04-08 15:04 ` [pbs-devel] [PATCH v4 proxmox-backup 5/5] docs: mention different name resolution " Christian Ebner
2025-04-09 11:12 ` [pbs-devel] superseded: [PATCH v4 proxmox proxmox-backup 0/5] fix 4788: statically linked proxmox-backup-client Christian Ebner
5 siblings, 0 replies; 7+ messages in thread
From: Christian Ebner @ 2025-04-08 15:04 UTC (permalink / raw)
To: 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 <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
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH v4 proxmox-backup 5/5] docs: mention different name resolution for statically linked binary
2025-04-08 15:04 [pbs-devel] [PATCH v4 proxmox proxmox-backup 0/5] fix 4788: statically linked proxmox-backup-client Christian Ebner
` (3 preceding siblings ...)
2025-04-08 15:04 ` [pbs-devel] [PATCH v4 proxmox-backup 4/5] client: http: Use custom resolver for statically linked binary Christian Ebner
@ 2025-04-08 15:04 ` Christian Ebner
2025-04-09 11:12 ` [pbs-devel] superseded: [PATCH v4 proxmox proxmox-backup 0/5] fix 4788: statically linked proxmox-backup-client Christian Ebner
5 siblings, 0 replies; 7+ messages in thread
From: Christian Ebner @ 2025-04-08 15:04 UTC (permalink / raw)
To: pbs-devel
Add a note mentioning that the statically linked binary does not use
the same mechanism for name resolution as the regular client, in
particular that this does not support NSS.
The statically linked binary cannot use the `getaddrinfo` based name
resolution because of possible ABI incompatibility. It therefore is
conditionally compiled and linked using the name resolution provided
by hickory-resolver, part of hickory-dns [0].
[0] https://github.com/hickory-dns/hickory-dns
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
changes since version 3:
- not present in previous version
docs/backup-client.rst | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/docs/backup-client.rst b/docs/backup-client.rst
index bc80525be..1e0b4ac6b 100644
--- a/docs/backup-client.rst
+++ b/docs/backup-client.rst
@@ -44,6 +44,11 @@ user\@pbs!token@host:store ``user@pbs!token`` host:8007 store
[ff80::51]:1234:mydatastore ``root@pam`` [ff80::51]:1234 mydatastore
================================ ================== ================== ===========
+.. Note:: If you are using the statically linked binary of proxmox backup client
+ name resolution will not be performed via the mechanisms provided by libc,
+ but uses a resolver written purely in the Rust programming language.
+ Therefore, features and modules provided by Name Service Switch cannot be
+ used.
.. _environment-variables:
--
2.39.5
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] superseded: [PATCH v4 proxmox proxmox-backup 0/5] fix 4788: statically linked proxmox-backup-client
2025-04-08 15:04 [pbs-devel] [PATCH v4 proxmox proxmox-backup 0/5] fix 4788: statically linked proxmox-backup-client Christian Ebner
` (4 preceding siblings ...)
2025-04-08 15:04 ` [pbs-devel] [PATCH v4 proxmox-backup 5/5] docs: mention different name resolution " Christian Ebner
@ 2025-04-09 11:12 ` Christian Ebner
5 siblings, 0 replies; 7+ messages in thread
From: Christian Ebner @ 2025-04-09 11:12 UTC (permalink / raw)
To: pbs-devel
superseded-by version 5:
https://lore.proxmox.com/pbs-devel/20250409110520.170697-1-c.ebner@proxmox.com/T/
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread