Skip to content

Commit

Permalink
feat(tls): Add preconfigured TLS settings
Browse files Browse the repository at this point in the history
  • Loading branch information
0x676e67 committed Aug 13, 2024
1 parent 5e48411 commit 87f078f
Show file tree
Hide file tree
Showing 44 changed files with 953 additions and 831 deletions.
57 changes: 57 additions & 0 deletions examples/pre_configured_tls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::error::Error;

use boring::ssl::{SslConnector, SslMethod};
use hyper::{PseudoOrder, SettingsOrder, StreamDependency, StreamId};
use rquest::{
tls::{Http2FrameSettings, TlsExtensionSettings, TlsSettings, Version},
HttpVersionPref,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let settings = TlsSettings {
builder: SslConnector::builder(SslMethod::tls_client())?,
extension: TlsExtensionSettings {
tls_sni: true,
http_version_pref: HttpVersionPref::Http2,
min_tls_version: Some(Version::TLS_1_0),
max_tls_version: Some(Version::TLS_1_3),
application_settings: true,
pre_shared_key: true,
enable_ech_grease: true,
permute_extensions: true,
},
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: None,
headers_priority: Some(StreamDependency::new(StreamId::zero(), 255, true)),
headers_pseudo_order: Some([
PseudoOrder::Method,
PseudoOrder::Scheme,
PseudoOrder::Authority,
PseudoOrder::Path,
]),
settings_order: Some([
SettingsOrder::InitialWindowSize,
SettingsOrder::MaxConcurrentStreams,
]),
},
};

// Build a client to mimic Edge127
let client = rquest::Client::builder()
.use_preconfigured_tls(|_headers| settings)
.enable_ech_grease()
.permute_extensions()
.build()?;

// Use the API you're already familiar with
let resp = client.get("https://tls.peet.ws/api/all").send().await?;
println!("{}", resp.text().await?);

Ok(())
}
78 changes: 50 additions & 28 deletions src/async_impl/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::error;
use crate::into_url::{expect_uri, try_uri};
use crate::redirect::{self, remove_sensitive_headers};
#[cfg(feature = "boring-tls")]
use crate::tls::{self, BoringTlsConnector, Impersonate, Tls};
use crate::tls::{self, BoringTlsConnector, Impersonate, Tls, TlsSettings};
use crate::{IntoUrl, Method, Proxy, StatusCode, Url};
use log::{debug, trace};

Expand Down Expand Up @@ -62,11 +62,15 @@ pub struct ClientBuilder {
config: Config,
}

/// A `HttpVersionPref` is used to set the HTTP version preference.
#[derive(Debug, Clone, Copy)]
pub enum HttpVersionPref {
/// Prefer HTTP/1.1
Http1,
/// Prefer HTTP/2
#[cfg(feature = "http2")]
Http2,
/// Prefer HTTP/1 and HTTP/2
All,
}

Expand Down Expand Up @@ -266,36 +270,54 @@ impl ClientBuilder {
/// This will set the necessary headers and TLS settings.
/// This is only available with the `boring-tls` feature.
#[cfg(feature = "boring-tls")]
pub fn impersonate(mut self, impersonate: Impersonate) -> ClientBuilder {
if let Ok(settings) = tls::tls_settings(impersonate, &mut self.config.headers) {
// Set the TLS settings
self.config.tls.builder = Some(settings.builder);
self.config.tls.extension = settings.extension;

// Set the http2 version preference
#[cfg(feature = "http2")]
{
return self
.http2_initial_stream_window_size(settings.http2.initial_stream_window_size)
.http2_initial_connection_window_size(
settings.http2.initial_connection_window_size,
)
.http2_max_concurrent_streams(settings.http2.max_concurrent_streams)
.http2_max_header_list_size(settings.http2.max_header_list_size)
.http2_header_table_size(settings.http2.header_table_size)
.http2_enable_push(settings.http2.enable_push)
.http2_headers_priority(settings.http2.headers_priority)
.http2_headers_pseudo_order(settings.http2.headers_pseudo_order)
.http2_settings_order(settings.http2.settings_order);
}
pub fn impersonate(self, impersonate: Impersonate) -> ClientBuilder {
// Try to get the settings for the impersonate version
if let Ok((settings, func)) = tls::tls_settings(impersonate) {
return self.apply_tls_settings(settings, func);
}
self
}

#[cfg(not(feature = "http2"))]
{
return self;
}
/// Use the preconfigured TLS settings.
#[cfg(feature = "boring-tls")]
#[cfg(feature = "boring-tls")]
pub fn use_preconfigured_tls<F>(self, f: F) -> ClientBuilder
where
F: FnOnce(&mut HeaderMap) -> TlsSettings,
{
let mut headers = self.config.headers.clone();
let settings = f(&mut headers);
self.apply_tls_settings(settings, |_| {})
}

/// Apply the given TLS settings and header function.
#[cfg(feature = "boring-tls")]
fn apply_tls_settings<F>(mut self, settings: TlsSettings, func: F) -> ClientBuilder
where
F: FnOnce(&mut HeaderMap),
{
func(&mut self.config.headers);
self.config.tls.builder = Some(settings.builder);
self.config.tls.extension = settings.extension;

// Set the http2 version preference
#[cfg(feature = "http2")]
{
self.http2_initial_stream_window_size(settings.http2.initial_stream_window_size)
.http2_initial_connection_window_size(settings.http2.initial_connection_window_size)
.http2_max_concurrent_streams(settings.http2.max_concurrent_streams)
.http2_max_header_list_size(settings.http2.max_header_list_size)
.http2_header_table_size(settings.http2.header_table_size)
.http2_enable_push(settings.http2.enable_push)
.http2_headers_priority(settings.http2.headers_priority)
.http2_headers_pseudo_order(settings.http2.headers_pseudo_order)
.http2_settings_order(settings.http2.settings_order)
}

self
#[cfg(not(feature = "http2"))]
{
self
}
}

/// Enable Encrypted Client Hello (Secure SNI)
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,8 @@ pub use self::async_impl::websocket::{
CloseCode, Message, WebSocket, WebSocketRequestBuilder, WebSocketResponse,
};
pub use self::async_impl::{
Body, Client, ClientBuilder, Request, RequestBuilder, Response, Upgraded,
client::HttpVersionPref, Body, Client, ClientBuilder, Request, RequestBuilder, Response,
Upgraded,
};
pub use self::proxy::{NoProxy, Proxy};

Expand Down
35 changes: 18 additions & 17 deletions src/tls/impersonate/chrome/v100.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,25 @@ use http::{

pub(crate) fn get_settings(
settings: ImpersonateSettings,
headers: &mut HeaderMap,
) -> TlsResult<TlsSettings> {
init_headers(headers);
Ok(TlsSettings {
builder: ChromeTlsBuilder::new(&CIPHER_LIST)?,
extension: settings.extension,
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: None,
headers_priority: settings.headers_priority,
headers_pseudo_order: settings.headers_pseudo_order,
settings_order: settings.settings_order,
) -> TlsResult<(TlsSettings, impl FnOnce(&mut HeaderMap))> {
Ok((
TlsSettings {
builder: ChromeTlsBuilder::new(&CIPHER_LIST)?,
extension: settings.extension,
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: None,
headers_priority: settings.headers_priority,
headers_pseudo_order: settings.headers_pseudo_order,
settings_order: settings.settings_order,
},
},
})
init_headers,
))
}

fn init_headers(headers: &mut HeaderMap) {
Expand Down
35 changes: 18 additions & 17 deletions src/tls/impersonate/chrome/v101.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,25 @@ use http::{

pub(crate) fn get_settings(
settings: ImpersonateSettings,
headers: &mut HeaderMap,
) -> TlsResult<TlsSettings> {
init_headers(headers);
Ok(TlsSettings {
builder: ChromeTlsBuilder::new(&CIPHER_LIST)?,
extension: settings.extension,
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: None,
headers_priority: settings.headers_priority,
headers_pseudo_order: settings.headers_pseudo_order,
settings_order: settings.settings_order,
) -> TlsResult<(TlsSettings, impl FnOnce(&mut HeaderMap))> {
Ok((
TlsSettings {
builder: ChromeTlsBuilder::new(&CIPHER_LIST)?,
extension: settings.extension,
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: None,
headers_priority: settings.headers_priority,
headers_pseudo_order: settings.headers_pseudo_order,
settings_order: settings.settings_order,
},
},
})
init_headers,
))
}

fn init_headers(headers: &mut HeaderMap) {
Expand Down
35 changes: 18 additions & 17 deletions src/tls/impersonate/chrome/v104.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,25 @@ use http::{

pub(crate) fn get_settings(
settings: ImpersonateSettings,
headers: &mut HeaderMap,
) -> TlsResult<TlsSettings> {
init_headers(headers);
Ok(TlsSettings {
builder: ChromeTlsBuilder::new(&CIPHER_LIST)?,
extension: settings.extension,
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: None,
headers_priority: settings.headers_priority,
headers_pseudo_order: settings.headers_pseudo_order,
settings_order: settings.settings_order,
) -> TlsResult<(TlsSettings, impl FnOnce(&mut HeaderMap))> {
Ok((
TlsSettings {
builder: ChromeTlsBuilder::new(&CIPHER_LIST)?,
extension: settings.extension,
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: None,
headers_priority: settings.headers_priority,
headers_pseudo_order: settings.headers_pseudo_order,
settings_order: settings.settings_order,
},
},
})
init_headers,
))
}

fn init_headers(headers: &mut HeaderMap) {
Expand Down
35 changes: 18 additions & 17 deletions src/tls/impersonate/chrome/v105.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,25 @@ use http::{

pub(crate) fn get_settings(
settings: ImpersonateSettings,
headers: &mut HeaderMap,
) -> TlsResult<TlsSettings> {
init_headers(headers);
Ok(TlsSettings {
builder: ChromeTlsBuilder::new(&CIPHER_LIST)?,
extension: settings.extension,
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: None,
headers_priority: settings.headers_priority,
headers_pseudo_order: settings.headers_pseudo_order,
settings_order: settings.settings_order,
) -> TlsResult<(TlsSettings, impl FnOnce(&mut HeaderMap))> {
Ok((
TlsSettings {
builder: ChromeTlsBuilder::new(&CIPHER_LIST)?,
extension: settings.extension,
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: None,
headers_priority: settings.headers_priority,
headers_pseudo_order: settings.headers_pseudo_order,
settings_order: settings.settings_order,
},
},
})
init_headers,
))
}

fn init_headers(headers: &mut HeaderMap) {
Expand Down
35 changes: 18 additions & 17 deletions src/tls/impersonate/chrome/v106.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,25 @@ use http::{

pub(crate) fn get_settings(
settings: ImpersonateSettings,
headers: &mut HeaderMap,
) -> TlsResult<TlsSettings> {
init_headers(headers);
Ok(TlsSettings {
builder: ChromeTlsBuilder::new(&CIPHER_LIST)?,
extension: settings.extension,
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: Some(false),
headers_priority: settings.headers_priority,
headers_pseudo_order: settings.headers_pseudo_order,
settings_order: settings.settings_order,
) -> TlsResult<(TlsSettings, impl FnOnce(&mut HeaderMap))> {
Ok((
TlsSettings {
builder: ChromeTlsBuilder::new(&CIPHER_LIST)?,
extension: settings.extension,
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: Some(false),
headers_priority: settings.headers_priority,
headers_pseudo_order: settings.headers_pseudo_order,
settings_order: settings.settings_order,
},
},
})
init_headers,
))
}

fn init_headers(headers: &mut HeaderMap) {
Expand Down
Loading

0 comments on commit 87f078f

Please sign in to comment.