domain_fronting/lib.rs
1// Copyright (C) 2026 Mullvad VPN AB
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program. If not, see <https://www.gnu.org/licenses/>.
15//
16// SPDX-License-Identifier: GPL-3.0-or-later
17
18//! Domain fronting library for tunneling connections through HTTP POST requests.
19//!
20//! This crate provides both client and server components for domain fronting,
21//! allowing API connections to be tunneled through HTTP POST requests.
22//!
23//! # Features
24//!
25//! - **Client**: [`domain_fronting::ProxyConnection`] implements [`tokio::io::AsyncRead`] + [`tokio::io::AsyncWrite`]
26//! - **Server**: [`domain_fronting::server::Sessions`] manages HTTP sessions and forwards to upstream
27//! - **Testing**: Both components support custom transports for testing
28//!
29//! # Examples
30//!
31//! See the module documentation for [`domain_fronting`] for usage examples.
32
33use std::{io, net::SocketAddr};
34
35pub mod domain_fronting;
36#[cfg(feature = "tls")]
37mod tls_stream;
38
39pub use domain_fronting::{DomainFronting, Error, ProxyConfig, ProxyConnection};
40
41/// DNS resolver trait for resolving hostnames to IP addresses.
42#[async_trait::async_trait]
43pub trait DnsResolver: 'static + Send + Sync {
44 async fn resolve(&self, host: String) -> io::Result<Vec<SocketAddr>>;
45}
46
47/// Default DNS resolver that uses `ToSocketAddrs` (`getaddrinfo`).
48pub struct DefaultDnsResolver;
49
50#[async_trait::async_trait]
51impl DnsResolver for DefaultDnsResolver {
52 async fn resolve(&self, host: String) -> io::Result<Vec<SocketAddr>> {
53 use std::net::ToSocketAddrs;
54 tokio::task::spawn_blocking(move || {
55 format!("{host}:443")
56 .to_socket_addrs()
57 .map(|addrs| addrs.collect())
58 })
59 .await
60 .map_err(io::Error::other)?
61 }
62}