allow to turn off forced connection timeout
This commit is contained in:
parent
4aef34434a
commit
b2b3b05fcb
9 changed files with 41 additions and 19 deletions
|
|
@ -98,6 +98,11 @@ reverse_proxy = [{ upstream = [{ location = 'www.google.com', tls = true }] }]
|
||||||
# We should note that this strongly depends on the client implementation.
|
# We should note that this strongly depends on the client implementation.
|
||||||
ignore_sni_consistency = false
|
ignore_sni_consistency = false
|
||||||
|
|
||||||
|
# Force connection handling timeout regardless of the connection status, i.e., idle or not.
|
||||||
|
# 0 represents an infinite timeout. [default: 0]
|
||||||
|
# Note that idel and header read timeouts are always specified independently of this.
|
||||||
|
connection_handling_timeout = 0 # sec
|
||||||
|
|
||||||
# If this specified, h3 is enabled
|
# If this specified, h3 is enabled
|
||||||
[experimental.h3]
|
[experimental.h3]
|
||||||
alt_svc_max_age = 3600 # sec
|
alt_svc_max_age = 3600 # sec
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ rpxy-lib = { path = "../rpxy-lib/", default-features = false, features = [
|
||||||
|
|
||||||
anyhow = "1.0.79"
|
anyhow = "1.0.79"
|
||||||
rustc-hash = "1.1.0"
|
rustc-hash = "1.1.0"
|
||||||
serde = { version = "1.0.195", default-features = false, features = ["derive"] }
|
serde = { version = "1.0.196", default-features = false, features = ["derive"] }
|
||||||
derive_builder = "0.13.0"
|
derive_builder = "0.13.0"
|
||||||
tokio = { version = "1.35.1", default-features = false, features = [
|
tokio = { version = "1.35.1", default-features = false, features = [
|
||||||
"net",
|
"net",
|
||||||
|
|
@ -42,8 +42,8 @@ mimalloc = { version = "*", default-features = false }
|
||||||
|
|
||||||
# config
|
# config
|
||||||
clap = { version = "4.4.18", features = ["std", "cargo", "wrap_help"] }
|
clap = { version = "4.4.18", features = ["std", "cargo", "wrap_help"] }
|
||||||
toml = { version = "0.8.8", default-features = false, features = ["parse"] }
|
toml = { version = "0.8.9", default-features = false, features = ["parse"] }
|
||||||
hot_reload = "0.1.4"
|
hot_reload = "0.1.5"
|
||||||
|
|
||||||
# logging
|
# logging
|
||||||
tracing = { version = "0.1.40" }
|
tracing = { version = "0.1.40" }
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use rpxy_lib::{reexports::Uri, AppConfig, ProxyConfig, ReverseProxyConfig, TlsCo
|
||||||
use rustc_hash::FxHashMap as HashMap;
|
use rustc_hash::FxHashMap as HashMap;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{fs, net::SocketAddr};
|
use std::{fs, net::SocketAddr};
|
||||||
|
use tokio::time::Duration;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Default, PartialEq, Eq, Clone)]
|
#[derive(Deserialize, Debug, Default, PartialEq, Eq, Clone)]
|
||||||
pub struct ConfigToml {
|
pub struct ConfigToml {
|
||||||
|
|
@ -48,6 +49,7 @@ pub struct Experimental {
|
||||||
#[cfg(feature = "cache")]
|
#[cfg(feature = "cache")]
|
||||||
pub cache: Option<CacheOption>,
|
pub cache: Option<CacheOption>,
|
||||||
pub ignore_sni_consistency: Option<bool>,
|
pub ignore_sni_consistency: Option<bool>,
|
||||||
|
pub connection_handling_timeout: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Default, PartialEq, Eq, Clone)]
|
#[derive(Deserialize, Debug, Default, PartialEq, Eq, Clone)]
|
||||||
|
|
@ -162,7 +164,7 @@ impl TryInto<ProxyConfig> for &ConfigToml {
|
||||||
if x == 0u64 {
|
if x == 0u64 {
|
||||||
proxy_config.h3_max_idle_timeout = None;
|
proxy_config.h3_max_idle_timeout = None;
|
||||||
} else {
|
} else {
|
||||||
proxy_config.h3_max_idle_timeout = Some(tokio::time::Duration::from_secs(x))
|
proxy_config.h3_max_idle_timeout = Some(Duration::from_secs(x))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -172,6 +174,14 @@ impl TryInto<ProxyConfig> for &ConfigToml {
|
||||||
proxy_config.sni_consistency = !ignore;
|
proxy_config.sni_consistency = !ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(timeout) = exp.connection_handling_timeout {
|
||||||
|
if timeout == 0u64 {
|
||||||
|
proxy_config.connection_handling_timeout = Duration::from_secs(u64::MAX);
|
||||||
|
} else {
|
||||||
|
proxy_config.connection_handling_timeout = Duration::from_secs(timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "cache")]
|
#[cfg(feature = "cache")]
|
||||||
if let Some(cache_option) = &exp.cache {
|
if let Some(cache_option) = &exp.cache {
|
||||||
proxy_config.cache_enabled = true;
|
proxy_config.cache_enabled = true;
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ thiserror = "1.0.56"
|
||||||
http = "1.0.0"
|
http = "1.0.0"
|
||||||
http-body-util = "0.1.0"
|
http-body-util = "0.1.0"
|
||||||
hyper = { version = "1.1.0", default-features = false }
|
hyper = { version = "1.1.0", default-features = false }
|
||||||
hyper-util = { version = "0.1.2", features = ["full"] }
|
hyper-util = { version = "0.1.3", features = ["full"] }
|
||||||
futures-util = { version = "0.3.30", default-features = false }
|
futures-util = { version = "0.3.30", default-features = false }
|
||||||
futures-channel = { version = "0.3.30", default-features = false }
|
futures-channel = { version = "0.3.30", default-features = false }
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ hyper-rustls = { version = "0.26.0", default-features = false, features = [
|
||||||
], optional = true }
|
], optional = true }
|
||||||
|
|
||||||
# tls and cert management for server
|
# tls and cert management for server
|
||||||
hot_reload = "0.1.4"
|
hot_reload = "0.1.5"
|
||||||
rustls = { version = "0.21.10", default-features = false }
|
rustls = { version = "0.21.10", default-features = false }
|
||||||
tokio-rustls = { version = "0.24.1", features = ["early-data"] }
|
tokio-rustls = { version = "0.24.1", features = ["early-data"] }
|
||||||
webpki = "0.22.4"
|
webpki = "0.22.4"
|
||||||
|
|
@ -93,11 +93,11 @@ socket2 = { version = "0.5.5", features = ["all"], optional = true }
|
||||||
|
|
||||||
# cache
|
# cache
|
||||||
http-cache-semantics = { path = "../submodules/rusty-http-cache-semantics/", optional = true }
|
http-cache-semantics = { path = "../submodules/rusty-http-cache-semantics/", optional = true }
|
||||||
lru = { version = "0.12.1", optional = true }
|
lru = { version = "0.12.2", optional = true }
|
||||||
sha2 = { version = "0.10.8", default-features = false, optional = true }
|
sha2 = { version = "0.10.8", default-features = false, optional = true }
|
||||||
|
|
||||||
# cookie handling for sticky cookie
|
# cookie handling for sticky cookie
|
||||||
chrono = { version = "0.4.32", default-features = false, features = [
|
chrono = { version = "0.4.33", default-features = false, features = [
|
||||||
"unstable-locales",
|
"unstable-locales",
|
||||||
"alloc",
|
"alloc",
|
||||||
"clock",
|
"clock",
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@ pub const MAX_CONCURRENT_STREAMS: u32 = 64;
|
||||||
pub const CERTS_WATCH_DELAY_SECS: u32 = 60;
|
pub const CERTS_WATCH_DELAY_SECS: u32 = 60;
|
||||||
pub const LOAD_CERTS_ONLY_WHEN_UPDATED: bool = true;
|
pub const LOAD_CERTS_ONLY_WHEN_UPDATED: bool = true;
|
||||||
|
|
||||||
pub const CONNECTION_TIMEOUT_SEC: u64 = 60; // timeout to serve a connection, total time of receive request, serve, and send response. this might limits the max length of response.
|
|
||||||
|
|
||||||
// #[cfg(feature = "http3")]
|
// #[cfg(feature = "http3")]
|
||||||
// pub const H3_RESPONSE_BUF_SIZE: usize = 65_536; // 64KB
|
// pub const H3_RESPONSE_BUF_SIZE: usize = 65_536; // 64KB
|
||||||
// #[cfg(feature = "http3")]
|
// #[cfg(feature = "http3")]
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,11 @@ pub struct ProxyConfig {
|
||||||
pub keepalive: bool, // when instantiate server
|
pub keepalive: bool, // when instantiate server
|
||||||
|
|
||||||
// experimentals
|
// experimentals
|
||||||
|
/// SNI consistency check
|
||||||
pub sni_consistency: bool, // Handler
|
pub sni_consistency: bool, // Handler
|
||||||
|
/// Connection handling timeout
|
||||||
|
/// timeout to handle a connection, total time of receive request, serve, and send response. this might limits the max length of response.
|
||||||
|
pub connection_handling_timeout: Duration,
|
||||||
|
|
||||||
#[cfg(feature = "cache")]
|
#[cfg(feature = "cache")]
|
||||||
pub cache_enabled: bool,
|
pub cache_enabled: bool,
|
||||||
|
|
@ -90,6 +94,7 @@ impl Default for ProxyConfig {
|
||||||
keepalive: true,
|
keepalive: true,
|
||||||
|
|
||||||
sni_consistency: true,
|
sni_consistency: true,
|
||||||
|
connection_handling_timeout: Duration::from_secs(u64::MAX),
|
||||||
|
|
||||||
#[cfg(feature = "cache")]
|
#[cfg(feature = "cache")]
|
||||||
cache_enabled: false,
|
cache_enabled: false,
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,12 @@ where
|
||||||
if proxy_config.https_port.is_some() {
|
if proxy_config.https_port.is_some() {
|
||||||
info!("Listen port: {} (for TLS)", proxy_config.https_port.unwrap());
|
info!("Listen port: {} (for TLS)", proxy_config.https_port.unwrap());
|
||||||
}
|
}
|
||||||
|
if proxy_config.connection_handling_timeout.as_secs() < u64::MAX {
|
||||||
|
info!(
|
||||||
|
"Force connection handling timeout: {} sec",
|
||||||
|
proxy_config.connection_handling_timeout.as_secs()
|
||||||
|
);
|
||||||
|
}
|
||||||
#[cfg(any(feature = "http3-quinn", feature = "http3-s2n"))]
|
#[cfg(any(feature = "http3-quinn", feature = "http3-s2n"))]
|
||||||
if proxy_config.http3 {
|
if proxy_config.http3 {
|
||||||
info!("Experimental HTTP/3.0 is enabled. Note it is still very unstable.");
|
info!("Experimental HTTP/3.0 is enabled. Note it is still very unstable.");
|
||||||
|
|
@ -64,10 +70,7 @@ where
|
||||||
}
|
}
|
||||||
#[cfg(feature = "cache")]
|
#[cfg(feature = "cache")]
|
||||||
if proxy_config.cache_enabled {
|
if proxy_config.cache_enabled {
|
||||||
info!(
|
info!("Cache is enabled: cache dir = {:?}", proxy_config.cache_dir.as_ref().unwrap());
|
||||||
"Cache is enabled: cache dir = {:?}",
|
|
||||||
proxy_config.cache_dir.as_ref().unwrap()
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
info!("Cache is disabled")
|
info!("Cache is disabled")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use super::proxy_main::Proxy;
|
use super::proxy_main::Proxy;
|
||||||
use crate::{
|
use crate::{
|
||||||
constants::CONNECTION_TIMEOUT_SEC,
|
|
||||||
crypto::CryptoSource,
|
crypto::CryptoSource,
|
||||||
error::*,
|
error::*,
|
||||||
hyper_ext::body::{IncomingLike, RequestBody},
|
hyper_ext::body::{IncomingLike, RequestBody},
|
||||||
|
|
@ -11,7 +10,7 @@ use bytes::{Buf, Bytes};
|
||||||
use http::{Request, Response};
|
use http::{Request, Response};
|
||||||
use http_body_util::BodyExt;
|
use http_body_util::BodyExt;
|
||||||
use hyper_util::client::legacy::connect::Connect;
|
use hyper_util::client::legacy::connect::Connect;
|
||||||
use std::{net::SocketAddr, time::Duration};
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
#[cfg(feature = "http3-quinn")]
|
#[cfg(feature = "http3-quinn")]
|
||||||
use h3::{quic::BidiStream, quic::Connection as ConnectionQuic, server::RequestStream};
|
use h3::{quic::BidiStream, quic::Connection as ConnectionQuic, server::RequestStream};
|
||||||
|
|
@ -72,7 +71,7 @@ where
|
||||||
let tls_server_name_inner = tls_server_name.clone();
|
let tls_server_name_inner = tls_server_name.clone();
|
||||||
self.globals.runtime_handle.spawn(async move {
|
self.globals.runtime_handle.spawn(async move {
|
||||||
if let Err(e) = tokio::time::timeout(
|
if let Err(e) = tokio::time::timeout(
|
||||||
Duration::from_secs(CONNECTION_TIMEOUT_SEC + 1), // just in case...
|
self_inner.globals.proxy_config.connection_handling_timeout,
|
||||||
self_inner.h3_serve_stream(req, stream, client_addr, tls_server_name_inner),
|
self_inner.h3_serve_stream(req, stream, client_addr, tls_server_name_inner),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use super::socket::bind_tcp_socket;
|
use super::socket::bind_tcp_socket;
|
||||||
use crate::{
|
use crate::{
|
||||||
constants::{CONNECTION_TIMEOUT_SEC, TLS_HANDSHAKE_TIMEOUT_SEC},
|
constants::TLS_HANDSHAKE_TIMEOUT_SEC,
|
||||||
crypto::{CryptoSource, ServerCrypto, SniServerCryptoMap},
|
crypto::{CryptoSource, ServerCrypto, SniServerCryptoMap},
|
||||||
error::*,
|
error::*,
|
||||||
globals::Globals,
|
globals::Globals,
|
||||||
|
|
@ -88,9 +88,11 @@ where
|
||||||
let message_handler_clone = self.message_handler.clone();
|
let message_handler_clone = self.message_handler.clone();
|
||||||
let tls_enabled = self.tls_enabled;
|
let tls_enabled = self.tls_enabled;
|
||||||
let listening_on = self.listening_on;
|
let listening_on = self.listening_on;
|
||||||
|
let handling_timeout = self.globals.proxy_config.connection_handling_timeout;
|
||||||
|
|
||||||
self.globals.runtime_handle.clone().spawn(async move {
|
self.globals.runtime_handle.clone().spawn(async move {
|
||||||
timeout(
|
timeout(
|
||||||
Duration::from_secs(CONNECTION_TIMEOUT_SEC) + Duration::from_secs(1), // just in case...
|
handling_timeout,
|
||||||
server_clone.serve_connection_with_upgrades(
|
server_clone.serve_connection_with_upgrades(
|
||||||
stream,
|
stream,
|
||||||
service_fn(move |req: Request<Incoming>| {
|
service_fn(move |req: Request<Incoming>| {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue