Skip to main content

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}